tlb/as/
reference.rs

1use core::marker::PhantomData;
2
3use tlbits::{r#as::args::NoArgs, either::Either, ser::BitWriter};
4
5use crate::{
6    Cell, Context,
7    de::{
8        CellParser, CellParserError, args::r#as::CellDeserializeAsWithArgs, r#as::CellDeserializeAs,
9    },
10    ser::{
11        CellBuilder, CellBuilderError, args::r#as::CellSerializeAsWithArgs, r#as::CellSerializeAs,
12    },
13};
14
15use super::Same;
16
17/// Adapter to **de**/**ser**ialize value from/into reference to the child cell.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct Ref<As: ?Sized = Same>(PhantomData<As>);
20
21impl<T, As> CellSerializeAs<T> for Ref<As>
22where
23    As: CellSerializeAs<T> + ?Sized,
24{
25    #[inline]
26    fn store_as(source: &T, builder: &mut CellBuilder) -> Result<(), CellBuilderError> {
27        builder.store_reference_as::<&T, &As>(source).context("^")?;
28        Ok(())
29    }
30}
31
32impl<T, As> CellSerializeAsWithArgs<T> for Ref<As>
33where
34    As: CellSerializeAsWithArgs<T> + ?Sized,
35{
36    type Args = As::Args;
37
38    fn store_as_with(
39        source: &T,
40        builder: &mut CellBuilder,
41        args: Self::Args,
42    ) -> Result<(), CellBuilderError> {
43        builder
44            .store_reference_as_with::<&T, &As>(source, args)
45            .context("^")?;
46        Ok(())
47    }
48}
49
50impl<'de, T, As> CellDeserializeAs<'de, T> for Ref<As>
51where
52    As: CellDeserializeAs<'de, T> + ?Sized,
53{
54    #[inline]
55    fn parse_as(parser: &mut CellParser<'de>) -> Result<T, CellParserError<'de>> {
56        parser.parse_reference_as::<T, As>().context("^")
57    }
58}
59
60impl<'de, T, As> CellDeserializeAsWithArgs<'de, T> for Ref<As>
61where
62    As: CellDeserializeAsWithArgs<'de, T> + ?Sized,
63{
64    type Args = As::Args;
65
66    #[inline]
67    fn parse_as_with(
68        parser: &mut CellParser<'de>,
69        args: Self::Args,
70    ) -> Result<T, CellParserError<'de>> {
71        parser.parse_reference_as_with::<T, As>(args).context("^")
72    }
73}
74
75/// ```tlb
76/// {X:Type} Either X ^X = EitherInlineOrRef X
77/// ```
78pub struct EitherInlineOrRef<As: ?Sized = Same>(PhantomData<As>);
79
80impl<T, As> CellSerializeAs<T> for EitherInlineOrRef<As>
81where
82    As: CellSerializeAs<T>,
83{
84    #[inline]
85    fn store_as(source: &T, builder: &mut CellBuilder) -> Result<(), CellBuilderError> {
86        EitherInlineOrRef::<NoArgs<(), As>>::store_as_with(source, builder, ())
87    }
88}
89
90impl<T, As> CellSerializeAsWithArgs<T> for EitherInlineOrRef<As>
91where
92    As: CellSerializeAsWithArgs<T>,
93{
94    type Args = As::Args;
95
96    #[inline]
97    fn store_as_with(
98        source: &T,
99        builder: &mut CellBuilder,
100        args: Self::Args,
101    ) -> Result<(), CellBuilderError> {
102        let mut b = Cell::builder();
103        As::store_as_with(source, &mut b, args)?;
104        let cell = b.into_cell();
105        builder.store_as::<_, Either<Same, Ref>>(
106            if cell.data.len() <= builder.capacity_left() {
107                Either::Left
108            } else {
109                Either::Right
110            }(cell),
111        )?;
112        Ok(())
113    }
114}
115
116impl<'de, T, As> CellDeserializeAs<'de, T> for EitherInlineOrRef<As>
117where
118    As: CellDeserializeAs<'de, T>,
119{
120    #[inline]
121    fn parse_as(parser: &mut CellParser<'de>) -> Result<T, CellParserError<'de>> {
122        EitherInlineOrRef::<NoArgs<(), As>>::parse_as_with(parser, ())
123    }
124}
125
126impl<'de, T, As> CellDeserializeAsWithArgs<'de, T> for EitherInlineOrRef<As>
127where
128    As: CellDeserializeAsWithArgs<'de, T>,
129{
130    type Args = As::Args;
131
132    #[inline]
133    fn parse_as_with(
134        parser: &mut CellParser<'de>,
135        args: Self::Args,
136    ) -> Result<T, CellParserError<'de>> {
137        Either::<As, Ref<As>>::parse_as_with(parser, args).map(Either::into_inner)
138    }
139}