async_graphql/types/
id.rs1use std::{
2 num::ParseIntError,
3 ops::{Deref, DerefMut},
4};
5
6use async_graphql_value::ConstValue;
7#[cfg(feature = "bson")]
8use bson::oid::{self, ObjectId};
9use serde::{Deserialize, Serialize};
10
11use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value};
12
13#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Serialize, Deserialize, Default)]
18#[serde(transparent)]
19pub struct ID(pub String);
20
21impl AsRef<str> for ID {
22 fn as_ref(&self) -> &str {
23 self.0.as_str()
24 }
25}
26
27impl Deref for ID {
28 type Target = String;
29
30 fn deref(&self) -> &Self::Target {
31 &self.0
32 }
33}
34
35impl DerefMut for ID {
36 fn deref_mut(&mut self) -> &mut Self::Target {
37 &mut self.0
38 }
39}
40
41impl<T: std::fmt::Display> From<T> for ID {
42 fn from(value: T) -> Self {
43 ID(value.to_string())
44 }
45}
46
47impl From<ID> for String {
48 fn from(id: ID) -> Self {
49 id.0
50 }
51}
52
53impl From<ID> for ConstValue {
54 fn from(id: ID) -> Self {
55 ConstValue::String(id.0)
56 }
57}
58
59macro_rules! try_from_integers {
60 ($($ty:ty),*) => {
61 $(
62 impl TryFrom<ID> for $ty {
63 type Error = ParseIntError;
64
65 fn try_from(id: ID) -> Result<Self, Self::Error> {
66 id.0.parse()
67 }
68 }
69 )*
70 };
71}
72
73try_from_integers!(
74 i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, isize, usize
75);
76
77#[cfg(feature = "uuid")]
78impl TryFrom<ID> for uuid::Uuid {
79 type Error = uuid::Error;
80
81 fn try_from(id: ID) -> Result<Self, Self::Error> {
82 uuid::Uuid::parse_str(&id.0)
83 }
84}
85
86#[cfg(feature = "bson")]
87impl TryFrom<ID> for ObjectId {
88 type Error = oid::Error;
89
90 fn try_from(id: ID) -> std::result::Result<Self, oid::Error> {
91 ObjectId::parse_str(id.0)
92 }
93}
94
95impl PartialEq<&str> for ID {
96 fn eq(&self, other: &&str) -> bool {
97 self.0.as_str() == *other
98 }
99}
100
101#[Scalar(internal, name = "ID")]
102impl ScalarType for ID {
103 fn parse(value: Value) -> InputValueResult<Self> {
104 match value {
105 Value::Number(n) if n.is_i64() => Ok(ID(n.to_string())),
106 Value::String(s) => Ok(ID(s)),
107 _ => Err(InputValueError::expected_type(value)),
108 }
109 }
110
111 fn is_valid(value: &Value) -> bool {
112 match value {
113 Value::Number(n) if n.is_i64() => true,
114 Value::String(_) => true,
115 _ => false,
116 }
117 }
118
119 fn to_value(&self) -> Value {
120 Value::String(self.0.clone())
121 }
122}