cyfs_base/codec/
serde_codec.rs1use crate::{ChunkId, HashValue, NamedObjectId, ObjectType, JsonCodec, BuckyError};
2
3use serde::de::{self, Deserialize, Deserializer, Visitor};
4use serde::ser::{Serialize, Serializer};
5use std::str::FromStr;
6use std::convert::TryFrom;
7
8pub struct TStringVisitor<T>
10where
11 T: FromStr,
12{
13 dummy: std::marker::PhantomData<T>,
14}
15
16impl<T> TStringVisitor<T>
17where
18 T: FromStr,
19{
20 pub fn new() -> Self {
21 Self {
22 dummy: std::marker::PhantomData,
23 }
24 }
25}
26impl<'de, T> Visitor<'de> for TStringVisitor<T>
27where
28 T: FromStr,
29 <T as FromStr>::Err: std::fmt::Display,
30{
31 type Value = T;
32
33 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
34 formatter.write_str("encoded string value error")
35 }
36
37 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
38 where
39 E: de::Error,
40 <T as FromStr>::Err: std::fmt::Display,
41 {
42 match T::from_str(v) {
43 Ok(ret) => Ok(ret),
44 Err(e) => {
45 let msg = format!("invalid string value: {}, {}", v, e);
46 Err(E::custom(msg))
47 }
48 }
49 }
50}
51
52pub struct TU8Visitor<T>
54where
55 T: TryFrom<u8>,
56{
57 dummy: std::marker::PhantomData<T>,
58}
59
60impl<T> TU8Visitor<T>
61where
62 T: TryFrom<u8>,
63{
64 pub fn new() -> Self {
65 Self {
66 dummy: std::marker::PhantomData,
67 }
68 }
69}
70impl<'de, T> Visitor<'de> for TU8Visitor<T>
71where
72 T: TryFrom<u8>,
73 <T as TryFrom<u8>>::Error: std::fmt::Display,
74{
75 type Value = T;
76
77 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
78 formatter.write_str("encoded u8 value error")
79 }
80
81 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
82 where
83 E: de::Error,
84 {
85 match T::try_from(v) {
86 Ok(ret) => Ok(ret),
87 Err(e) => {
88 let msg = format!("invalid u8 value: {}, {}", v, e);
89 Err(E::custom(msg))
90 }
91 }
92 }
93}
94
95
96impl<T: ObjectType> Serialize for NamedObjectId<T> {
98 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
99 where
100 S: Serializer,
101 {
102 serializer.serialize_str(&self.to_string())
103 }
104}
105
106impl<'de, T: ObjectType> Deserialize<'de> for NamedObjectId<T> {
107 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108 where
109 D: Deserializer<'de>,
110 {
111 deserializer.deserialize_str(TStringVisitor::<Self>::new())
112 }
113}
114
115impl Serialize for ChunkId {
117 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118 where
119 S: Serializer,
120 {
121 serializer.serialize_str(&self.to_string())
122 }
123}
124
125impl<'de> Deserialize<'de> for ChunkId {
126 fn deserialize<D>(deserializer: D) -> Result<ChunkId, D::Error>
127 where
128 D: Deserializer<'de>,
129 {
130 deserializer.deserialize_str(TStringVisitor::<ChunkId>::new())
131 }
132}
133
134impl Serialize for HashValue {
136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where
138 S: Serializer,
139 {
140 serializer.serialize_str(&self.to_string())
141 }
142}
143
144impl<'de> Deserialize<'de> for HashValue {
145 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
146 where
147 D: Deserializer<'de>,
148 {
149 deserializer.deserialize_str(TStringVisitor::<Self>::new())
150 }
151}
152
153
154#[macro_export]
155macro_rules! serde_with_json_codec {
156 ($content:ty) => {
157 impl serde::ser::Serialize for $content {
158 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
159 where
160 S: serde::ser::Serializer,
161 {
162 self.encode_value().serialize(serializer)
163 }
164 }
165
166 impl<'de> serde::de::Deserialize<'de> for $content {
167 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
168 where
169 D: serde::de::Deserializer<'de>,
170 {
171 let value = serde_json::Value::deserialize(deserializer)?;
172 match <$content>::decode_value(&value) {
173 Ok(ret) => Ok(ret),
174 Err(e) => {
175 let msg = format!("invalid json value: {}", e);
176 Err(serde::de::Error::custom(msg))
177 }
178 }
179 }
180 }
181 };
182}
183
184serde_with_json_codec!(BuckyError);
185
186
187#[cfg(test)]
188mod test {
189 use crate::*;
190 use serde::*;
191 use std::str::FromStr;
192
193 #[derive(Serialize, Deserialize)]
194 struct TestError {
195 pub s: String,
196 pub err: BuckyError,
197 }
198
199 #[test]
200 fn test_bucky_error_codec() {
201 let err = BuckyError::new(BuckyErrorCode::AlreadyExists, "test error");
202 let es = TestError {
203 s: "test".to_owned(),
204 err: err.clone(),
205 };
206 let s = serde_json::to_string(&es).unwrap();
207 println!("{}", s);
208
209 let s = err.encode_string();
211 let s2 = serde_json::to_string(&err).unwrap();
212 assert_eq!(s, s2);
213 }
214
215 #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
216 struct OODStatus {
217 pub device_id: DeviceId,
218 pub people_id: PeopleId,
219 }
220
221 #[test]
222 fn test_codec() {
223 let people = "5r4MYfFAAwQGDHccsyTX1wnshnEu6UYW3SZ3AHnNm2g9";
224 let ood = "5aSixgLkHa2NR4vSKJLYLPo5Av6CY3RJeFJegtF5iR1g";
225
226 let status = OODStatus {
227 people_id: PeopleId::from_str(people).unwrap(),
228 device_id: DeviceId::from_str(ood).unwrap(),
229 };
230
231 let s = serde_json::to_string(&status).unwrap();
232 println!("{}", s);
233
234 let status2: OODStatus = serde_json::from_str(&s).unwrap();
235 assert_eq!(status, status2);
236
237 let hash = hash_data("test".as_bytes());
238 let s = serde_json::to_string(&hash).unwrap();
239 println!("{}", s);
240
241 let hash2: HashValue = serde_json::from_str(&s).unwrap();
242 assert_eq!(hash, hash2);
243 }
244}