1use std::{borrow::Cow, rc::Rc, sync::Arc};
2
3use bitvec::{order::Msb0, vec::BitVec};
4use either::Either;
5
6use crate::{
7 StringError,
8 r#as::{AsWrap, Same},
9};
10
11use super::{BitPack, BitWriter, BitWriterExt};
12
13pub trait BitPackAs<T: ?Sized> {
19 type Args;
21
22 fn pack_as<W>(source: &T, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
24 where
25 W: BitWriter + ?Sized;
26}
27
28#[inline]
30pub fn pack_as<T, As>(value: T, args: As::Args) -> Result<BitVec<u8, Msb0>, StringError>
31where
32 As: BitPackAs<T> + ?Sized,
33{
34 let mut writer = BitVec::new();
35 writer.pack_as::<_, As>(value, args)?;
36 Ok(writer)
37}
38
39impl<'a, T, As> BitPackAs<&'a T> for &'a As
40where
41 As: BitPackAs<T> + ?Sized,
42 T: ?Sized,
43{
44 type Args = As::Args;
45
46 #[inline]
47 fn pack_as<W>(source: &&'a T, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
48 where
49 W: BitWriter + ?Sized,
50 {
51 AsWrap::<&T, As>::new(source).pack(writer, args)
52 }
53}
54
55impl<'a, T, As> BitPackAs<&'a mut T> for &'a mut As
56where
57 As: BitPackAs<T> + ?Sized,
58 T: ?Sized,
59{
60 type Args = As::Args;
61
62 #[inline]
63 fn pack_as<W>(source: &&'a mut T, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
64 where
65 W: BitWriter + ?Sized,
66 {
67 AsWrap::<&T, As>::new(source).pack(writer, args)
68 }
69}
70
71impl<T, As> BitPackAs<[T]> for [As]
72where
73 As: BitPackAs<T>,
74 As::Args: Clone,
75{
76 type Args = As::Args;
77
78 #[inline]
79 fn pack_as<W>(source: &[T], writer: &mut W, args: Self::Args) -> Result<(), W::Error>
80 where
81 W: BitWriter + ?Sized,
82 {
83 writer.pack_many_as::<_, &As>(source, args)?;
84 Ok(())
85 }
86}
87
88impl<T, As, const N: usize> BitPackAs<[T; N]> for [As; N]
89where
90 As: BitPackAs<T>,
91 As::Args: Clone,
92{
93 type Args = As::Args;
94
95 #[inline]
96 fn pack_as<W>(source: &[T; N], writer: &mut W, args: Self::Args) -> Result<(), W::Error>
97 where
98 W: BitWriter + ?Sized,
99 {
100 <[As]>::pack_as(source.as_slice(), writer, args)
101 }
102}
103
104macro_rules! impl_bit_pack_as_for_tuple {
105 ($($t:ident as $a:ident:$n:tt),*) => {
106 impl<$($t, $a),*> BitPackAs<($($t,)*)> for ($($a,)*)
107 where $(
108 $a: BitPackAs<$t>,
109 )*
110 {
111 type Args = ($($a::Args,)*);
112
113 #[inline]
114 #[allow(unused_variables)]
115 fn pack_as<W>(source: &($($t,)*), writer: &mut W, args: Self::Args) -> Result<(), W::Error>
116 where
117 W: BitWriter + ?Sized,
118 {$(
119 $a::pack_as(&source.$n, writer, args.$n)?;)*
120 Ok(())
121 }
122 }
123 };
124}
125impl_bit_pack_as_for_tuple!();
126impl_bit_pack_as_for_tuple!(T0 as As0:0);
127impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1);
128impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2);
129impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3);
130impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4);
131impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5);
132impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5,T6 as As6:6);
133impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5,T6 as As6:6,T7 as As7:7);
134impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5,T6 as As6:6,T7 as As7:7,T8 as As8:8);
135impl_bit_pack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5,T6 as As6:6,T7 as As7:7,T8 as As8:8,T9 as As9:9);
136
137impl<T, As> BitPackAs<Rc<T>> for Box<As>
138where
139 As: BitPackAs<T> + ?Sized,
140{
141 type Args = As::Args;
142
143 #[inline]
144 fn pack_as<W>(source: &Rc<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
145 where
146 W: BitWriter + ?Sized,
147 {
148 AsWrap::<&T, As>::new(source).pack(writer, args)
149 }
150}
151
152impl<T, As> BitPackAs<Rc<T>> for Rc<As>
153where
154 As: BitPackAs<T> + ?Sized,
155{
156 type Args = As::Args;
157
158 #[inline]
159 fn pack_as<W>(source: &Rc<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
160 where
161 W: BitWriter + ?Sized,
162 {
163 AsWrap::<&T, As>::new(source).pack(writer, args)
164 }
165}
166
167impl<T, As> BitPackAs<Arc<T>> for Arc<As>
168where
169 As: BitPackAs<T> + ?Sized,
170{
171 type Args = As::Args;
172
173 #[inline]
174 fn pack_as<W>(source: &Arc<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
175 where
176 W: BitWriter + ?Sized,
177 {
178 AsWrap::<&T, As>::new(source).pack(writer, args)
179 }
180}
181
182impl<'a, T, As> BitPackAs<Cow<'a, T>> for Cow<'a, As>
183where
184 T: ToOwned + ?Sized,
185 As: ToOwned + BitPackAs<T> + ?Sized,
186{
187 type Args = As::Args;
188
189 #[inline]
190 fn pack_as<W>(source: &Cow<'a, T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
191 where
192 W: BitWriter + ?Sized,
193 {
194 AsWrap::<&T, As>::new(source).pack(writer, args)
195 }
196}
197
198impl<Left, Right, AsLeft, AsRight> BitPackAs<Either<Left, Right>> for Either<AsLeft, AsRight>
204where
205 AsLeft: BitPackAs<Left>,
206 AsRight: BitPackAs<Right>,
207{
208 type Args = (AsLeft::Args, AsRight::Args);
209
210 #[inline]
211 fn pack_as<W>(
212 source: &Either<Left, Right>,
213 writer: &mut W,
214 args: Self::Args,
215 ) -> Result<(), W::Error>
216 where
217 W: BitWriter + ?Sized,
218 {
219 source
220 .as_ref()
221 .map_either(AsWrap::<&Left, AsLeft>::new, AsWrap::<&Right, AsRight>::new)
222 .pack(writer, args)
223 }
224}
225
226impl<T, As> BitPackAs<Option<T>> for Either<(), As>
227where
228 As: BitPackAs<T>,
229{
230 type Args = As::Args;
231
232 #[inline]
233 fn pack_as<W>(source: &Option<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
234 where
235 W: BitWriter + ?Sized,
236 {
237 Either::<Same, &As>::pack_as(
238 &match source.as_ref() {
239 None => Either::Left(()),
240 Some(v) => Either::Right(v),
241 },
242 writer,
243 ((), args),
244 )
245 }
246}
247
248impl<T, As> BitPackAs<Option<T>> for Option<As>
254where
255 As: BitPackAs<T>,
256{
257 type Args = As::Args;
258
259 #[inline]
260 fn pack_as<W>(source: &Option<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
261 where
262 W: BitWriter + ?Sized,
263 {
264 source
265 .as_ref()
266 .map(AsWrap::<&T, As>::new)
267 .pack(writer, args)
268 }
269}
270
271pub trait BitPackWrapAsExt {
272 #[inline]
273 fn wrap_as<As>(&self) -> AsWrap<&'_ Self, As>
274 where
275 As: BitPackAs<Self> + ?Sized,
276 {
277 AsWrap::new(self)
278 }
279}
280impl<T> BitPackWrapAsExt for T {}