1use jxl_bitstream::Bitstream;
2
3#[macro_export]
4#[doc(hidden)]
5macro_rules! expand_u32 {
6 ($bitstream:ident; $($rest:tt)*) => {
7 $crate::expand_u32!(@convert $bitstream; (); ($($rest)*,))
8 };
9 (@convert $bitstream:ident; ($($done:tt)*); ()) => {
10 $bitstream.read_u32($($done)*)
11 };
12 (@convert $bitstream:ident; ($($done:tt)*); ($c:literal, $($rest:tt)*)) => {
13 $crate::expand_u32!(@convert $bitstream; ($($done)* $c,); ($($rest)*))
14 };
15 (@convert $bitstream:ident; ($($done:tt)*); (u($n:literal), $($rest:tt)*)) => {
16 $crate::expand_u32!(@convert $bitstream; ($($done)* ::jxl_bitstream::U($n),); ($($rest)*))
17 };
18 (@convert $bitstream:ident; ($($done:tt)*); ($c:literal + u($n:literal), $($rest:tt)*)) => {
19 $crate::expand_u32!(@convert $bitstream; ($($done)* $c + ::jxl_bitstream::U($n),); ($($rest)*))
20 };
21}
22
23#[macro_export]
24#[doc(hidden)]
25macro_rules! read_bits {
26 ($bistream:ident, $c:literal $(, $ctx:expr)?) => {
27 ::jxl_bitstream::Result::Ok($c)
28 };
29 ($bitstream:ident, u($n:literal) $(, $ctx:expr)?) => {
30 $bitstream.read_bits($n)
31 };
32 ($bitstream:ident, u($n:literal); UnpackSigned $(, $ctx:expr)?) => {
33 $bitstream.read_bits($n).map(::jxl_bitstream::unpack_signed)
34 };
35 ($bitstream:ident, $c:literal + u($n:literal) $(, $ctx:expr)?) => {
36 $bitstream.read_bits($n).map(|v| v.wrapping_add($c))
37 };
38 ($bitstream:ident, $c:literal + u($n:literal); UnpackSigned $(, $ctx:expr)?) => {
39 $bitstream.read_bits($n).map(|v| ::jxl_bitstream::unpack_signed(v.wrapping_add($c)))
40 };
41 ($bitstream:ident, U32($($args:tt)+) $(, $ctx:expr)?) => {
42 $crate::expand_u32!($bitstream; $($args)+)
43 };
44 ($bitstream:ident, U32($($args:tt)+); UnpackSigned $(, $ctx:expr)?) => {
45 $crate::expand_u32!($bitstream; $($args)+).map(::jxl_bitstream::unpack_signed)
46 };
47 ($bitstream:ident, U64 $(, $ctx:expr)?) => {
48 $bitstream.read_u64()
49 };
50 ($bitstream:ident, U64; UnpackSigned $(, $ctx:expr)?) => {
51 $bitstream.read_u64().map(::jxl_bitstream::unpack_signed_u64)
52 };
53 ($bitstream:ident, F16 $(, $ctx:expr)?) => {
54 $bitstream.read_f16_as_f32()
55 };
56 ($bitstream:ident, Bool $(, $ctx:expr)?) => {
57 $bitstream.read_bool()
58 };
59 ($bitstream:ident, Enum($enumtype:ty) $(, $ctx:expr)?) => {
60 $bitstream.read_enum::<$enumtype>()
61 };
62 ($bitstream:ident, ZeroPadToByte $(, $ctx:expr)?) => {
63 $bitstream.zero_pad_to_byte()
64 };
65 ($bitstream:ident, Bundle($bundle:ty)) => {
66 <$bundle>::parse($bitstream, ())
67 };
68 ($bitstream:ident, Bundle($bundle:ty), $ctx:expr) => {
69 <$bundle>::parse($bitstream, $ctx)
70 };
71 ($bitstream:ident, Vec[$($inner:tt)*]; $count:expr $(, $ctx:expr)?) => {
72 {
73 let count = $count as usize;
74 (0..count)
75 .into_iter()
76 .map(|_| $crate::read_bits!($bitstream, $($inner)* $(, $ctx)?))
77 .collect::<::std::result::Result<Vec<_>, _>>()
78 }
79 };
80 ($bitstream:ident, Array[$($inner:tt)*]; $count:expr $(, $ctx:expr)?) => {
81 (|| -> ::std::result::Result<[_; $count], _> {
82 let mut ret = [Default::default(); $count];
83 for point in &mut ret {
84 *point = match $crate::read_bits!($bitstream, $($inner)* $(, $ctx)?) {
85 ::std::result::Result::Ok(v) => v,
86 ::std::result::Result::Err(err) => return ::std::result::Result::Err(err),
87 };
88 }
89 Ok(ret)
90 })()
91 };
92}
93
94#[macro_export]
95#[doc(hidden)]
96macro_rules! make_def {
97 (@ty; $c:literal) => { u32 };
98 (@ty; u($n:literal)) => { u32 };
99 (@ty; u($n:literal); UnpackSigned) => { i32 };
100 (@ty; $c:literal + u($n:literal)) => { u32 };
101 (@ty; $c:literal + u($n:literal); UnpackSigned) => { i32 };
102 (@ty; U32($($args:tt)*)) => { u32 };
103 (@ty; U32($($args:tt)*); UnpackSigned) => { i32 };
104 (@ty; U64) => { u64 };
105 (@ty; U64; UnpackSigned) => { i64 };
106 (@ty; F16) => { f32 };
107 (@ty; Bool) => { bool };
108 (@ty; Enum($enum:ty)) => { $enum };
109 (@ty; Bundle($bundle:ty)) => { $bundle };
110 (@ty; Vec[$($inner:tt)*]; $count:expr) => { Vec<$crate::make_def!(@ty; $($inner)*)> };
111 (@ty; Array[$($inner:tt)*]; $count:expr) => { [$crate::make_def!(@ty; $($inner)*); $count] };
112 ($(#[$attrs:meta])* $v:vis struct $bundle_name:ident {
113 $($(#[$fieldattrs:meta])* $vfield:vis $field:ident: ty($($expr:tt)*) $(ctx($ctx_for_field:expr))? $(cond($cond:expr))? $(default($def_expr:expr))? ,)*
114 }) => {
115 $(#[$attrs])*
116 $v struct $bundle_name {
117 $($(#[$fieldattrs])* $vfield $field: $crate::make_def!(@ty; $($expr)*),)*
118 }
119 };
120}
121
122#[macro_export]
123#[doc(hidden)]
124macro_rules! make_parse {
125 (@parse $bitstream:ident; cond($cond:expr); default($def_expr:expr); ty($($spec:tt)*); ctx($ctx:expr)) => {
126 if $cond {
127 $crate::read_bits!($bitstream, $($spec)*, $ctx)?
128 } else {
129 $def_expr
130 }
131 };
132 (@parse $bitstream:ident; cond($cond:expr); ty($($spec:tt)*); ctx($ctx:expr)) => {
133 if $cond {
134 $crate::read_bits!($bitstream, $($spec)*, $ctx)?
135 } else {
136 <$crate::make_def!(@ty; $($spec)*)>::default_with_context($ctx)
137 }
138 };
139 (@parse $bitstream:ident; $(default($def_expr:expr);)? ty($($spec:tt)*); ctx($ctx:expr)) => {
140 $crate::read_bits!($bitstream, $($spec)*, $ctx)?
141 };
142 (@default($($spec:tt)*); ; $ctx:expr) => {
143 <$crate::make_def!(@ty; $($spec)*)>::default_with_context($ctx)
144 };
145 (@default($($spec:tt)*); $def_expr:expr $(; $ctx:expr)?) => {
146 $def_expr
147 };
148 (@select_ctx; $ctx_id:ident; $ctx:expr) => {
149 $ctx
150 };
151 (@select_ctx; $ctx_id:ident;) => {
152 $ctx_id
153 };
154 (@select_error_ty;) => {
155 ::jxl_bitstream::Error
156 };
157 (@select_error_ty; $err:ty) => {
158 $err
159 };
160 ($bundle_name:ident $(error($err:ty))? {
161 $($(#[$fieldattrs:meta])* $v:vis $field:ident: ty($($expr:tt)*) $(ctx($ctx_for_field:expr))? $(cond($cond:expr))? $(default($def_expr:expr))? ,)*
162 }) => {
163 impl<Ctx: Copy> $crate::Bundle<Ctx> for $bundle_name {
164 type Error = $crate::make_parse!(@select_error_ty; $($err)?);
165
166 #[allow(unused)]
167 fn parse(bitstream: &mut ::jxl_bitstream::Bitstream, ctx: Ctx) -> ::std::result::Result<Self, Self::Error> where Self: Sized {
168 use $crate::{Bundle, BundleDefault};
169 $(
170 let $field = $crate::make_parse!(
171 @parse bitstream;
172 $(cond($cond);)?
173 $(default($def_expr);)?
174 ty($($expr)*);
175 ctx($crate::make_parse!(@select_ctx; ctx; $($ctx_for_field)?))
176 );
177 )*
178 Ok(Self { $($field,)* })
179 }
180 }
181
182 impl<Ctx: Copy> $crate::BundleDefault<Ctx> for $bundle_name {
183 #[allow(unused)]
184 fn default_with_context(_ctx: Ctx) -> Self where Self: Sized {
185 use $crate::BundleDefault;
186 $(
187 let $field = $crate::make_parse!(
188 @default($($expr)*);
189 $($def_expr)?;
190 $crate::make_parse!(@select_ctx; _ctx; $($ctx_for_field)?)
191 );
192 )*
193 Self { $($field,)* }
194 }
195 }
196 };
197 ($bundle_name:ident ctx($ctx_id:ident : $ctx:ty) $(error($err:ty))? {
198 $($(#[$fieldattrs:meta])* $v:vis $field:ident: ty($($expr:tt)*) $(ctx($ctx_for_field:expr))? $(cond($cond:expr))? $(default($def_expr:expr))? ,)*
199 }) => {
200 impl $crate::Bundle<$ctx> for $bundle_name {
201 type Error = $crate::make_parse!(@select_error_ty; $($err)?);
202
203 #[allow(unused)]
204 fn parse(bitstream: &mut ::jxl_bitstream::Bitstream, $ctx_id: $ctx) -> ::std::result::Result<Self, Self::Error> where Self: Sized {
205 use $crate::{Bundle, BundleDefault};
206 $(
207 let $field = $crate::make_parse!(
208 @parse bitstream;
209 $(cond($cond);)?
210 $(default($def_expr);)?
211 ty($($expr)*);
212 ctx($crate::make_parse!(@select_ctx; $ctx_id; $($ctx_for_field)?))
213 );
214 )*
215 Ok(Self { $($field,)* })
216 }
217 }
218
219 impl $crate::BundleDefault<$ctx> for $bundle_name {
220 #[allow(unused)]
221 fn default_with_context($ctx_id: $ctx) -> Self where Self: Sized {
222 use $crate::BundleDefault;
223 $(
224 let $field = $crate::make_parse!(
225 @default($($expr)*);
226 $($def_expr)?;
227 $crate::make_parse!(@select_ctx; $ctx_id; $($ctx_for_field)?)
228 );
229 )*
230 Self { $($field,)* }
231 }
232 }
233 };
234}
235
236#[macro_export]
237macro_rules! define_bundle {
238 (
239 $(
240 $(#[$attrs:meta])*
241 $v:vis struct $bundle_name:ident
242 $(aligned($aligned:literal))?
243 $(ctx($ctx_id:ident : $ctx:ty))?
244 $(error($err:ty))?
245 {
246 $($body:tt)*
247 }
248 )*
249 ) => {
250 $(
251 $crate::make_def!($(#[$attrs])* $v struct $bundle_name { $($body)* });
252 $crate::make_parse!($bundle_name $(aligned($aligned))? $(ctx($ctx_id: $ctx))? $(error($err))? { $($body)* });
253 )*
254 };
255}
256
257pub trait Bundle<Ctx = ()>: Sized {
258 type Error;
259
260 fn parse(bitstream: &mut Bitstream<'_>, ctx: Ctx) -> Result<Self, Self::Error>;
262}
263
264pub trait BundleDefault<Ctx = ()>: Sized {
265 fn default_with_context(ctx: Ctx) -> Self;
267}
268
269impl<T, Ctx> BundleDefault<Ctx> for T
270where
271 T: Default + Sized,
272{
273 fn default_with_context(_: Ctx) -> Self {
274 Default::default()
275 }
276}
277
278impl<T, Ctx> Bundle<Ctx> for Option<T>
279where
280 T: Bundle<Ctx>,
281{
282 type Error = T::Error;
283
284 fn parse(bitstream: &mut Bitstream, ctx: Ctx) -> Result<Self, Self::Error> {
285 T::parse(bitstream, ctx).map(Some)
286 }
287}
288
289#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
291pub struct Name(String);
292
293impl<Ctx> Bundle<Ctx> for Name {
294 type Error = jxl_bitstream::Error;
295
296 fn parse(bitstream: &mut Bitstream, _: Ctx) -> Result<Self, Self::Error> {
297 let len = read_bits!(bitstream, U32(0, u(4), 16 + u(5), 48 + u(10)))? as usize;
298 let mut data = vec![0u8; len];
299 for b in &mut data {
300 *b = bitstream.read_bits(8)? as u8;
301 }
302 let name = String::from_utf8(data)
303 .map_err(|_| jxl_bitstream::Error::ValidationFailed("non-UTF-8 name"))?;
304 Ok(Self(name))
305 }
306}
307
308impl std::ops::Deref for Name {
309 type Target = String;
310
311 fn deref(&self) -> &Self::Target {
312 &self.0
313 }
314}
315
316impl std::ops::DerefMut for Name {
317 fn deref_mut(&mut self) -> &mut Self::Target {
318 &mut self.0
319 }
320}