defuse_serde_utils/
tlb.rs

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