1use std::borrow::Cow;
2use std::collections::{BTreeMap, HashMap};
3use std::hash::{BuildHasher, Hash};
4use std::marker::PhantomData;
5use std::rc::Rc;
6use std::sync::Arc;
7
8use serde::de::{MapAccess, Visitor};
9use serde::ser::SerializeTuple;
10use serde::{Deserialize, Deserializer, Serialize, Serializer};
11
12use crate::cell::{Cell, DynCell};
13
14#[repr(transparent)]
19pub struct SerdeBoc<T: ?Sized>(T);
20
21impl<T: ?Sized> SerdeBoc<T> {
22 #[inline(always)]
24 pub const fn wrap(value: &T) -> &Self {
25 unsafe { &*(value as *const T as *const Self) }
27 }
28}
29
30impl<T> SerdeBoc<T> {
31 #[inline(always)]
32 const fn wrap_slice(value: &[T]) -> &[Self] {
33 unsafe { std::slice::from_raw_parts(value.as_ptr() as *const Self, value.len()) }
35 }
36
37 #[inline(always)]
39 pub fn into_inner(self) -> T {
40 self.0
41 }
42}
43
44impl<T> From<T> for SerdeBoc<T> {
45 #[inline]
46 fn from(val: T) -> SerdeBoc<T> {
47 Self(val)
48 }
49}
50
51impl<T: SerializeAsBoc + ?Sized> Serialize for SerdeBoc<T> {
52 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
53 self.0.serialize_as_boc(serializer)
54 }
55}
56
57impl<'de, T: DeserializeAsBoc<'de>> Deserialize<'de> for SerdeBoc<T> {
58 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
59 where
60 D: Deserializer<'de>,
61 {
62 T::deserialize_as_boc(deserializer).map(Self)
63 }
64}
65
66trait SerializeAsBoc {
69 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
70}
71
72impl SerializeAsBoc for Cell {
73 #[inline]
74 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
75 self.as_ref().serialize(serializer)
76 }
77}
78
79impl SerializeAsBoc for DynCell {
80 #[inline]
81 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
82 self.serialize(serializer)
83 }
84}
85
86impl<T: SerializeAsBoc + ?Sized> SerializeAsBoc for &'_ T {
87 #[inline]
88 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
89 T::serialize_as_boc(self, serializer)
90 }
91}
92
93impl<T: SerializeAsBoc> SerializeAsBoc for Option<T> {
94 #[inline]
95 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
96 self.as_ref().map(SerdeBoc::<T>::wrap).serialize(serializer)
97 }
98}
99
100impl<T: SerializeAsBoc + ?Sized> SerializeAsBoc for Box<T> {
101 #[inline]
102 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
103 T::serialize_as_boc(self.as_ref(), serializer)
104 }
105}
106
107impl<T: SerializeAsBoc + ?Sized> SerializeAsBoc for Rc<T> {
108 #[inline]
109 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
110 T::serialize_as_boc(self.as_ref(), serializer)
111 }
112}
113
114impl<T: SerializeAsBoc + ?Sized> SerializeAsBoc for Arc<T> {
115 #[inline]
116 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
117 T::serialize_as_boc(self.as_ref(), serializer)
118 }
119}
120
121impl<T: SerializeAsBoc> SerializeAsBoc for [T] {
122 #[inline]
123 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
124 SerdeBoc::wrap_slice(self).serialize(serializer)
125 }
126}
127
128impl<T: SerializeAsBoc> SerializeAsBoc for Vec<T> {
129 #[inline]
130 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
131 self.as_slice().serialize_as_boc(serializer)
132 }
133}
134
135impl<T> SerializeAsBoc for [T; 0] {
136 #[inline]
137 fn serialize_as_boc<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
138 ok!(serializer.serialize_tuple(0)).end()
139 }
140}
141
142macro_rules! serialize_as_boc_array_impls {
143 ($($len:tt)+) => {
144 $(
145 #[allow(clippy::zero_prefixed_literal)]
146 impl<T: SerializeAsBoc> SerializeAsBoc for [T; $len] {
147 #[inline]
148 fn serialize_as_boc<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
149 where
150 S: Serializer,
151 {
152 let mut seq = ok!(serializer.serialize_tuple($len));
153 for e in self {
154 ok!(seq.serialize_element(SerdeBoc::<T>::wrap(e)));
155 }
156 seq.end()
157 }
158 }
159 )+
160 }
161}
162
163serialize_as_boc_array_impls! {
164 01 02 03 04 05 06 07 08 09 10
165 11 12 13 14 15 16 17 18 19 20
166 21 22 23 24 25 26 27 28 29 30
167 31 32
168}
169
170macro_rules! serialize_as_boc_map_impl {
171 ($ty:ident<K$(: $kbound1:ident $(+ $kbound2:ident)*)*, V$(, $typaram:ident: $bound:ident)*>) => {
172 impl<K, V$(, $typaram)*> SerializeAsBoc for $ty<K, V$(, $typaram)*>
173 where
174 K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
175 V: SerializeAsBoc,
176 $($typaram: $bound,)*
177 {
178 #[inline]
179 fn serialize_as_boc<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
180 where
181 S: Serializer,
182 {
183 serializer.collect_map(self.iter().map(|(k, v)| (k, SerdeBoc::wrap(v))))
184 }
185 }
186 }
187}
188
189serialize_as_boc_map_impl! { BTreeMap<K: Ord, V> }
190serialize_as_boc_map_impl! { HashMap<K: Eq + Hash, V, H: BuildHasher> }
191
192trait DeserializeAsBoc<'de>: Sized {
195 fn deserialize_as_boc<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>;
196}
197
198impl<'de> DeserializeAsBoc<'de> for Cell {
199 fn deserialize_as_boc<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
200 use serde::de::Error;
201
202 let is_human_readable = deserializer.is_human_readable();
203 let mut boc = ok!(borrow_cow_bytes(deserializer));
204
205 if is_human_readable {
206 match crate::util::decode_base64(boc) {
207 Ok(bytes) => {
208 boc = Cow::Owned(bytes);
209 }
210 Err(_) => return Err(Error::custom("invalid base64 string")),
211 }
212 }
213
214 match crate::boc::Boc::decode(boc) {
215 Ok(cell) => Ok(cell),
216 Err(e) => Err(Error::custom(e)),
217 }
218 }
219}
220
221impl<'de, T: DeserializeAsBoc<'de>> DeserializeAsBoc<'de> for Box<T> {
222 #[inline]
223 fn deserialize_as_boc<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
224 let value = ok!(Box::<SerdeBoc<T>>::deserialize(deserializer));
225 Ok(unsafe { Box::from_raw(Box::into_raw(value).cast::<T>()) })
227 }
228}
229
230impl<'de, T: DeserializeAsBoc<'de>> DeserializeAsBoc<'de> for Option<T> {
231 #[inline]
232 fn deserialize_as_boc<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
233 Ok(ok!(Option::<SerdeBoc<T>>::deserialize(deserializer)).map(SerdeBoc::into_inner))
234 }
235}
236
237impl<'de, T: DeserializeAsBoc<'de>> DeserializeAsBoc<'de> for Vec<T> {
238 #[inline]
239 fn deserialize_as_boc<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
240 Ok(ok!(Vec::<SerdeBoc<T>>::deserialize(deserializer))
241 .into_iter()
242 .map(SerdeBoc::into_inner)
243 .collect())
244 }
245}
246
247impl<'de, T: DeserializeAsBoc<'de>, const N: usize> DeserializeAsBoc<'de> for [T; N]
248where
249 [SerdeBoc<T>; N]: Deserialize<'de>,
250{
251 fn deserialize_as_boc<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
252 let value = ok!(<[SerdeBoc<T>; N]>::deserialize(deserializer));
253 Ok(value.map(SerdeBoc::into_inner))
254 }
255}
256
257macro_rules! deserialize_as_boc_map_impl {
258 (
259 $ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
260 $access:ident,
261 $with_capacity:expr,
262 ) => {
263 impl<'de, K, V $(, $typaram)*> DeserializeAsBoc<'de> for $ty<K, V $(, $typaram)*>
264 where
265 K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*,
266 V: DeserializeAsBoc<'de>,
267 $($typaram: $bound1 $(+ $bound2)*),*
268 {
269 fn deserialize_as_boc<D>(deserializer: D) -> Result<Self, D::Error>
270 where
271 D: Deserializer<'de>,
272 {
273 struct MapVisitor<K, V $(, $typaram)*> {
274 marker: PhantomData<$ty<K, V $(, $typaram)*>>,
275 }
276
277 impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor<K, V $(, $typaram)*>
278 where
279 K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*,
280 V: DeserializeAsBoc<'de>,
281 $($typaram: $bound1 $(+ $bound2)*),*
282 {
283 type Value = $ty<K, V $(, $typaram)*>;
284
285 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
286 formatter.write_str("a map")
287 }
288
289 #[inline]
290 fn visit_map<A>(self, mut $access: A) -> Result<Self::Value, A::Error>
291 where
292 A: MapAccess<'de>,
293 {
294 let mut values = $with_capacity;
295
296 while let Some((key, SerdeBoc(value))) = ok!($access.next_entry()) {
297 values.insert(key, value);
298 }
299
300 Ok(values)
301 }
302 }
303
304 let visitor = MapVisitor { marker: PhantomData };
305 deserializer.deserialize_map(visitor)
306 }
307 }
308 }
309}
310
311deserialize_as_boc_map_impl! {
312 BTreeMap<K: Ord, V>,
313 map,
314 BTreeMap::new(),
315}
316
317deserialize_as_boc_map_impl! {
318 HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
319 map,
320 HashMap::with_capacity_and_hasher(cautious_size_hint::<(K, V)>(map.size_hint()), S::default()),
321}
322
323fn cautious_size_hint<Element>(hint: Option<usize>) -> usize {
324 const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
325
326 if std::mem::size_of::<Element>() == 0 {
327 0
328 } else {
329 std::cmp::min(
330 hint.unwrap_or(0),
331 MAX_PREALLOC_BYTES / std::mem::size_of::<Element>(),
332 )
333 }
334}
335
336fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result<std::borrow::Cow<'a, [u8]>, D::Error>
339where
340 D: Deserializer<'de>,
341{
342 use serde::de::Error;
343
344 struct CowBytesVisitor;
345
346 impl<'a> Visitor<'a> for CowBytesVisitor {
347 type Value = Cow<'a, [u8]>;
348
349 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
350 formatter.write_str("a byte array")
351 }
352
353 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
354 where
355 E: Error,
356 {
357 Ok(Cow::Owned(v.as_bytes().to_vec()))
358 }
359
360 fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
361 where
362 E: Error,
363 {
364 Ok(Cow::Borrowed(v.as_bytes()))
365 }
366
367 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
368 where
369 E: Error,
370 {
371 Ok(Cow::Owned(v.into_bytes()))
372 }
373
374 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
375 where
376 E: Error,
377 {
378 Ok(Cow::Owned(v.to_vec()))
379 }
380
381 fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
382 where
383 E: Error,
384 {
385 Ok(Cow::Borrowed(v))
386 }
387
388 fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
389 where
390 E: Error,
391 {
392 Ok(Cow::Owned(v))
393 }
394 }
395
396 deserializer.deserialize_bytes(CowBytesVisitor)
397}
398
399#[cfg(test)]
400mod tests {
401 use crate::cell::CellFamily;
402
403 use super::*;
404
405 #[derive(serde::Serialize)]
406 struct StructWithDynCell<'a> {
407 #[serde(with = "crate::boc::Boc")]
408 cell: &'a DynCell,
409 }
410
411 #[test]
412 fn serde_dyn_cell_works() {
413 serde_json::to_string(&StructWithDynCell {
414 cell: Cell::empty_cell_ref(),
415 })
416 .unwrap();
417 }
418}