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