1use bytes::Bytes;
2use serde::{de, ser, ser::SerializeSeq, Deserialize, Deserializer, Serializer};
3use uuid7::Uuid;
4
5pub fn serialize_id<S, T>(bytes: T, serializer: S) -> Result<S::Ok, S::Error>
6where
7 S: Serializer,
8 T: AsRef<[u8]>,
9{
10 let bytes = bytes.as_ref();
11 if bytes.is_empty() {
12 return serializer.serialize_str("");
13 }
14 if bytes.len() != 16 {
15 return Err(ser::Error::custom("invalid id length"));
16 }
17 let id = u128::from_be_bytes(bytes.try_into().map_err(ser::Error::custom)?);
18 serializer.collect_str(&Uuid::from(id).to_string())
19}
20
21pub fn deserialize_id_vec<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
22where
23 D: Deserializer<'de>,
24{
25 let s = String::deserialize(deserializer)?;
26 if s.is_empty() {
27 return Ok(vec![]);
28 }
29 let id: Uuid = s.parse().map_err(de::Error::custom)?;
30 Ok(id.as_bytes().to_vec())
31}
32
33pub fn deserialize_id_bytes<'de, D>(deserializer: D) -> Result<Bytes, D::Error>
34where
35 D: Deserializer<'de>,
36{
37 deserialize_id_vec(deserializer).map(Bytes::from)
38}
39
40pub fn serialize_repeat_id<S, T>(data: &[T], serializer: S) -> Result<S::Ok, S::Error>
41where
42 S: Serializer,
43 T: AsRef<[u8]>,
44{
45 let mut seq = serializer.serialize_seq(Some(data.len()))?;
46 for item in data {
47 let bytes = item.as_ref();
48 if bytes.is_empty() {
49 seq.serialize_element("")?;
50 continue;
51 }
52 if bytes.len() != 16 {
53 return Err(ser::Error::custom("invalid id length"));
54 }
55 let id = u128::from_be_bytes(item.as_ref().try_into().map_err(ser::Error::custom)?);
56 let e = Uuid::from(id).to_string();
57 seq.serialize_element(&e)?;
58 }
59 seq.end()
60}
61
62pub fn deserialize_repeat_id_vec<'de, D>(deserializer: D) -> Result<Vec<Vec<u8>>, D::Error>
63where
64 D: Deserializer<'de>,
65{
66 struct Visitor;
67
68 impl<'de> ::serde::de::Visitor<'de> for Visitor {
69 type Value = Vec<Vec<u8>>;
70
71 fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
72 write!(f, "a sequence of uuid7 ASCII text")
73 }
74
75 fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
76 where
77 S: de::SeqAccess<'de>,
78 {
79 let mut data: Vec<Vec<u8>> = Vec::with_capacity(seq.size_hint().unwrap_or(0));
80 while let Some(s) = seq.next_element::<String>()? {
81 if s.is_empty() {
82 data.push(vec![]);
83 continue;
84 }
85 let id: Uuid = s.parse().map_err(de::Error::custom)?;
86 data.push(id.as_bytes().to_vec());
87 }
88 Ok(data)
89 }
90 }
91
92 deserializer.deserialize_seq(Visitor)
93}
94
95pub fn deserialize_repeat_id_bytes<'de, D>(deserializer: D) -> Result<Vec<Bytes>, D::Error>
96where
97 D: Deserializer<'de>,
98{
99 struct Visitor;
100
101 impl<'de> ::serde::de::Visitor<'de> for Visitor {
102 type Value = Vec<Bytes>;
103
104 fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
105 write!(f, "a sequence of uuid7 ASCII text")
106 }
107
108 fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
109 where
110 S: de::SeqAccess<'de>,
111 {
112 let mut data: Vec<Bytes> = Vec::with_capacity(seq.size_hint().unwrap_or(0));
113 while let Some(s) = seq.next_element::<String>()? {
114 if s.is_empty() {
115 data.push(Bytes::new());
116 continue;
117 }
118 let id: Uuid = s.parse().map_err(de::Error::custom)?;
119 data.push(Bytes::from(id.as_bytes().to_vec()));
120 }
121 Ok(data)
122 }
123 }
124
125 deserializer.deserialize_seq(Visitor)
126}
127
128#[cfg(all(feature = "id", feature = "json"))]
129#[cfg(test)]
130mod tests {
131 use std::str::FromStr;
132
133 use super::*;
134 use prost::{Message, Oneof};
135 use serde::{Deserialize, Serialize};
136
137 #[derive(serde::Serialize, serde::Deserialize)]
138 #[serde(default)]
139 #[derive(Clone, PartialEq, Eq, ::prost::Message)]
140 pub struct Hello {
141 #[prost(string, tag = "1")]
142 pub msg: String,
143 #[serde(
144 serialize_with = "serialize_id",
145 deserialize_with = "deserialize_id_vec"
146 )]
147 #[prost(bytes, tag = "2")]
148 pub value_vec: ::prost::alloc::vec::Vec<u8>,
149 #[serde(
150 serialize_with = "serialize_repeat_id",
151 deserialize_with = "deserialize_repeat_id_vec"
152 )]
153 #[prost(bytes = "vec", repeated, tag = "3")]
154 pub list_vec: Vec<Vec<u8>>,
155 #[serde(
156 serialize_with = "serialize_id",
157 deserialize_with = "deserialize_id_bytes"
158 )]
159 #[prost(bytes, tag = "4")]
160 pub value_bytes: ::prost::bytes::Bytes,
161 #[serde(
162 serialize_with = "serialize_repeat_id",
163 deserialize_with = "deserialize_repeat_id_bytes"
164 )]
165 #[prost(bytes = "bytes", repeated, tag = "5")]
166 pub list_bytes: ::prost::alloc::vec::Vec<::prost::bytes::Bytes>,
167 }
168
169 #[derive(serde::Serialize, serde::Deserialize)]
170 #[serde(default)]
171 #[derive(Clone, PartialEq, Eq, Message)]
172 pub struct ObjectId {
173 #[prost(oneof = "Data", tags = "2, 3")]
175 pub data: ::core::option::Option<Data>,
176 }
177
178 #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Oneof)]
179 pub enum Data {
180 #[prost(string, tag = "2")]
181 Result(String),
182 #[serde(
183 serialize_with = "serialize_id",
184 deserialize_with = "deserialize_id_vec"
185 )]
186 #[prost(bytes, tag = "3")]
187 Value(Vec<u8>),
188 }
189
190 #[test]
191 fn vec_u8_encoded_with_uuid7() {
192 let hello = Hello {
193 msg: "world".to_owned(),
194 value_vec: uuid_vec(),
195 ..Default::default()
196 };
197 let s = serde_json::to_string(&hello).unwrap();
198 assert_eq!(
199 s,
200 r#"{"msg":"world","value_vec":"018c8afb-43d7-7f73-be38-95ed30027670","list_vec":[],"value_bytes":"","list_bytes":[]}"#
201 );
202 }
203
204 #[test]
205 fn vec_u8_in_enum_encoded_with_uuid7() {
206 let data = ObjectId {
207 data: Some(Data::Value(uuid_vec())),
208 };
209 let s = serde_json::to_string(&data).unwrap();
210 assert_eq!(
211 s,
212 r#"{"data":{"Value":"018c8afb-43d7-7f73-be38-95ed30027670"}}"#
213 );
214 }
215
216 #[test]
217 fn repeat_vec_u8_encoded_with_uuid7() {
218 let hello = Hello {
219 msg: "world".to_owned(),
220 list_vec: vec![uuid_vec(), vec![]],
221 ..Default::default()
222 };
223 let s = serde_json::to_string(&hello).unwrap();
224 assert_eq!(
225 s,
226 r#"{"msg":"world","value_vec":"","list_vec":["018c8afb-43d7-7f73-be38-95ed30027670",""],"value_bytes":"","list_bytes":[]}"#
227 );
228 }
229
230 #[test]
231 fn bytes_encoded_with_uuid7() {
232 let hello = Hello {
233 msg: "world".to_owned(),
234 value_bytes: uuid_vec().into(),
235 ..Default::default()
236 };
237 let s = serde_json::to_string(&hello).unwrap();
238 assert_eq!(
239 s,
240 r#"{"msg":"world","value_vec":"","list_vec":[],"value_bytes":"018c8afb-43d7-7f73-be38-95ed30027670","list_bytes":[]}"#
241 );
242 let data = serde_json::from_str::<Hello>(&s).unwrap();
243 assert_eq!(data, hello);
244 }
245
246 #[test]
247 fn repeat_bytes_encoded_with_uuid7() {
248 let hello = Hello {
249 msg: "world".to_owned(),
250 list_bytes: vec![uuid_vec().into(), Bytes::new()],
251 ..Default::default()
252 };
253 let s = serde_json::to_string(&hello).unwrap();
254 assert_eq!(
255 s,
256 r#"{"msg":"world","value_vec":"","list_vec":[],"value_bytes":"","list_bytes":["018c8afb-43d7-7f73-be38-95ed30027670",""]}"#
257 );
258 }
259
260 fn uuid() -> &'static str {
261 "018c8afb-43d7-7f73-be38-95ed30027670"
262 }
263
264 fn uuid_vec() -> Vec<u8> {
265 Uuid::from_str(uuid()).unwrap().as_bytes().to_vec()
266 }
267}