defuse_serde_utils/
tlb.rs

1use std::marker::PhantomData;
2
3use near_sdk::serde::{self, Deserializer, Serializer};
4use serde_with::{DeserializeAs, SerializeAs};
5use tlb_ton::{
6    BagOfCellsArgs, BoC, Context,
7    r#as::Same,
8    de::r#as::CellDeserializeAsOwned,
9    ser::{
10        CellSerializeExt,
11        r#as::{CellSerializeAs, CellSerializeWrapAsExt},
12    },
13};
14
15pub struct AsBoC<As: ?Sized, CellAs: ?Sized = Same>(PhantomData<As>, PhantomData<CellAs>);
16
17impl<T, As, CellAs> SerializeAs<T> for AsBoC<As, CellAs>
18where
19    CellAs: CellSerializeAs<T>,
20    for<'a> As: SerializeAs<&'a [u8]>,
21{
22    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
23    where
24        S: Serializer,
25    {
26        let bytes = source
27            .wrap_as::<CellAs>()
28            .to_cell()
29            .map(BoC::from_root)
30            .and_then(|boc| {
31                boc.serialize(BagOfCellsArgs {
32                    has_idx: false,
33                    has_crc32c: false,
34                })
35                .context("BoC")
36            })
37            .context("TL-B")
38            .map_err(serde::ser::Error::custom)?;
39
40        As::serialize_as(&bytes.as_slice(), serializer)
41    }
42}
43
44impl<'de, T, As, CellAs> DeserializeAs<'de, T> for AsBoC<As, CellAs>
45where
46    CellAs: CellDeserializeAsOwned<T>,
47    As: DeserializeAs<'de, Vec<u8>>,
48{
49    fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
50    where
51        D: Deserializer<'de>,
52    {
53        let bytes = As::deserialize_as(deserializer)?;
54        BoC::deserialize(bytes)
55            .and_then(|boc| boc.into_single_root().context("multiple roots"))
56            .context("BoC")
57            .and_then(|root| root.parse_fully_as::<T, CellAs>())
58            .context("TL-B")
59            .map_err(serde::de::Error::custom)
60    }
61}
62
63#[cfg(all(feature = "abi", not(target_arch = "wasm32")))]
64const _: () = {
65    use near_sdk::schemars::{SchemaGenerator, schema::Schema};
66    use serde_with::schemars_0_8::JsonSchemaAs;
67
68    impl<T, As, CellAs> JsonSchemaAs<T> for AsBoC<As, CellAs>
69    where
70        As: JsonSchemaAs<T>,
71    {
72        fn schema_name() -> String {
73            As::schema_name()
74        }
75
76        fn json_schema(generator: &mut SchemaGenerator) -> Schema {
77            As::json_schema(generator)
78        }
79
80        fn is_referenceable() -> bool {
81            As::is_referenceable()
82        }
83    }
84};