defuse_serde_utils/
tlb.rs1use 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};