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