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#[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
75pub 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}