Skip to content

Commit fd56089

Browse files
committed
Implement BinRead for all array lengths using const generics.
This increases the minimum supported Rust version to 1.51.0. I sadly had to introduce another unsafe statement, because: * `Default` is only implemented for array lengths up to 32 (rust-lang/rust#61415) * arr_macro doesn't support const generics (JoshMcguigan/arr_macro#2) * Direct initialization via [T; N] adds a trait bound BinRead: Copy
1 parent 18398c3 commit fd56089

File tree

1 file changed

+38
-43
lines changed

1 file changed

+38
-43
lines changed

binread/src/binread_impls.rs

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -117,55 +117,50 @@ impl<C: Copy + 'static, B: BinRead<Args = C>> BinRead for Vec<B> {
117117
}
118118
}
119119

120-
macro_rules! binread_array_impl {
121-
($($size:literal),*$(,)?) => {
122-
$(
123-
impl<C: Copy + 'static, B: BinRead<Args = C> + Default> BinRead for [B; $size] {
124-
type Args = B::Args;
120+
impl<C: Copy + 'static, B: BinRead<Args = C>, const N: usize> BinRead for [B; N] {
121+
type Args = B::Args;
125122

126-
fn read_options<R: Read + Seek>(reader: &mut R, options: &ReadOptions, args: Self::Args) -> BinResult<Self> {
127-
#[cfg(feature = "debug_template")]
128-
{
129-
let pos = reader.seek(SeekFrom::Current(0))?;
130-
let type_name = core::any::type_name::<B>().rsplitn(1, "::").nth(0).unwrap();
131-
132-
if let Some(name) = options.variable_name {
133-
binary_template::write_vec_named(
134-
options.endian, pos, type_name, $size, name
135-
);
136-
} else {
137-
binary_template::write_vec(options.endian, pos, type_name, $size);
138-
}
139-
}
123+
fn read_options<R: Read + Seek>(
124+
reader: &mut R,
125+
options: &ReadOptions,
126+
args: Self::Args,
127+
) -> BinResult<Self> {
128+
#[cfg(feature = "debug_template")]
129+
{
130+
let pos = reader.seek(SeekFrom::Current(0))?;
131+
let type_name = core::any::type_name::<B>().rsplitn(1, "::").nth(0).unwrap();
140132

141-
#[cfg(feature = "debug_template")]
142-
let options = &ReadOptions {
143-
dont_output_to_template: true,
144-
..*options
145-
};
146-
147-
let mut arr: [B; $size] = Default::default();
148-
for elem in arr.iter_mut() {
149-
*elem = BinRead::read_options(reader, options, args)?;
150-
}
151-
Ok(arr)
152-
}
133+
if let Some(name) = options.variable_name {
134+
binary_template::write_vec_named(options.endian, pos, type_name, N, name);
135+
} else {
136+
binary_template::write_vec(options.endian, pos, type_name, N);
137+
}
138+
}
153139

154-
fn after_parse<R>(&mut self, reader: &mut R, ro: &ReadOptions, args: B::Args)-> BinResult<()>
155-
where R: Read + Seek,
156-
{
157-
for val in self.iter_mut() {
158-
val.after_parse(reader, ro, args)?;
159-
}
140+
#[cfg(feature = "debug_template")]
141+
let options = &ReadOptions {
142+
dont_output_to_template: true,
143+
..*options
144+
};
160145

161-
Ok(())
162-
}
163-
}
164-
)*
146+
let mut arr: [B; N] = unsafe { core::mem::MaybeUninit::uninit().assume_init() };
147+
for elem in arr.iter_mut() {
148+
*elem = BinRead::read_options(reader, options, args)?;
149+
}
150+
Ok(arr)
165151
}
166-
}
167152

168-
binread_array_impl!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);
153+
fn after_parse<R>(&mut self, reader: &mut R, ro: &ReadOptions, args: B::Args) -> BinResult<()>
154+
where
155+
R: Read + Seek,
156+
{
157+
for val in self.iter_mut() {
158+
val.after_parse(reader, ro, args)?;
159+
}
160+
161+
Ok(())
162+
}
163+
}
169164

170165
/// Internal macro to recursively implement BinRead for every size tuple given
171166
/// in the invocation

0 commit comments

Comments
 (0)