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