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