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