defuse_serde_utils/
tlb.rs

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