twilight_model/
visitor.rs1pub mod null_boolean {
9 use serde::{
10 de::{Deserializer, Error as DeError, Visitor},
11 ser::Serializer,
12 };
13 use std::fmt::{Formatter, Result as FmtResult};
14
15 struct NullBooleanVisitor;
16
17 impl Visitor<'_> for NullBooleanVisitor {
18 type Value = bool;
19
20 fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
21 f.write_str("null")
22 }
23
24 fn visit_none<E: DeError>(self) -> Result<Self::Value, E> {
25 Ok(true)
26 }
27
28 fn visit_unit<E: DeError>(self) -> Result<Self::Value, E> {
32 Ok(true)
33 }
34 }
35
36 #[allow(clippy::trivially_copy_pass_by_ref)]
39 pub fn serialize<S: Serializer>(_: &bool, serializer: S) -> Result<S::Ok, S::Error> {
40 serializer.serialize_none()
41 }
42
43 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<bool, D::Error> {
44 deserializer.deserialize_option(NullBooleanVisitor)
45 }
46}
47
48pub mod zeroable_id {
56 use crate::id::Id;
57 use serde::{
58 de::{Deserializer, Error as DeError, Visitor},
59 ser::Serializer,
60 Deserialize,
61 };
62 use std::{
63 fmt::{Formatter, Result as FmtResult},
64 marker::PhantomData,
65 str::FromStr,
66 };
67
68 struct ZeroableIdVisitor<T> {
69 phantom: PhantomData<T>,
70 }
71
72 impl<'de, T> Visitor<'de> for ZeroableIdVisitor<T> {
73 type Value = Option<Id<T>>;
74
75 fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
76 f.write_str(r#"ID, 0, "0", or null"#)
77 }
78
79 fn visit_newtype_struct<D: Deserializer<'de>>(
80 self,
81 deserializer: D,
82 ) -> Result<Self::Value, D::Error> {
83 let stringified_number = String::deserialize(deserializer)?;
84
85 self.visit_str(&stringified_number)
86 }
87
88 fn visit_none<E: DeError>(self) -> Result<Self::Value, E> {
89 Ok(None)
90 }
91
92 fn visit_some<D: Deserializer<'de>>(
93 self,
94 deserializer: D,
95 ) -> Result<Self::Value, D::Error> {
96 deserializer.deserialize_any(self)
97 }
98
99 fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
100 Id::from_str(v).map(Some).map_err(DeError::custom)
101 }
102
103 fn visit_u64<E: DeError>(self, v: u64) -> Result<Self::Value, E> {
104 Ok(Id::new_checked(v))
105 }
106
107 fn visit_unit<E: DeError>(self) -> Result<Self::Value, E> {
108 Ok(None)
109 }
110 }
111
112 #[allow(clippy::ref_option, clippy::trivially_copy_pass_by_ref)]
115 pub fn serialize<S: Serializer, T>(
116 value: &Option<Id<T>>,
117 serializer: S,
118 ) -> Result<S::Ok, S::Error> {
119 if let Some(id) = value {
120 serializer.serialize_some(id)
121 } else {
122 serializer.serialize_none()
123 }
124 }
125
126 pub fn deserialize<'de, D: Deserializer<'de>, T>(
127 deserializer: D,
128 ) -> Result<Option<Id<T>>, D::Error> {
129 deserializer.deserialize_any(ZeroableIdVisitor::<T> {
130 phantom: PhantomData,
131 })
132 }
133}