Skip to main content

binrw/binread/
mod.rs

1mod impls;
2
3use crate::{
4    __private::Required,
5    io::{Read, Seek},
6    meta::ReadEndian,
7    BinResult, Endian,
8};
9pub use impls::VecArgs;
10
11/// The `BinRead` trait reads data from streams and converts it into objects.
12///
13/// This trait is usually derived, but can also be manually implemented by
14/// writing an appropriate [`Args`] type and [`read_options()`] function.
15///
16/// [`Args`]: Self::Args
17/// [`read_options()`]: Self::read_options
18///
19/// # Derivable
20///
21/// This trait can be used with `#[derive]` or `#[binread]`. Each field of a
22/// derived type must either implement `BinRead` or be annotated with an
23/// attribute containing a [`map`], [`try_map`], or [`parse_with`] directive.
24///
25/// [`map`]: crate::docs::attribute#map
26/// [`parse_with`]: crate::docs::attribute#custom-parserswriters
27/// [`try_map`]: crate::docs::attribute#map
28///
29/// Using `#[binread]` instead of `#[derive]` is required when using
30/// [temporary fields].
31///
32/// [temporary fields]: crate::docs::attribute#temp
33pub trait BinRead: Sized {
34    /// The type used for the `args` parameter of [`read_args()`] and
35    /// [`read_options()`].
36    ///
37    /// When the given type implements [`Default`], convenience functions like
38    /// [`read()`] are enabled. `BinRead` implementations that don’t receive any
39    /// arguments should use the `()` type.
40    ///
41    /// When `BinRead` is derived, the [`import`] and [`import_tuple`]
42    /// directives define this type.
43    ///
44    /// [`import`]: crate::docs::attribute#arguments
45    /// [`import_tuple`]: crate::docs::attribute#arguments
46    /// [`read()`]: Self::read
47    /// [`read_args()`]: Self::read_args
48    /// [`read_options()`]: Self::read_options
49    type Args<'a>;
50
51    /// Read `Self` from the reader using default arguments.
52    ///
53    /// # Errors
54    ///
55    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
56    #[inline]
57    fn read<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
58    where
59        Self: ReadEndian,
60        for<'a> Self::Args<'a>: Required,
61    {
62        Self::read_args(reader, Self::Args::args())
63    }
64
65    /// Read `Self` from the reader using default arguments and assuming
66    /// big-endian byte order.
67    ///
68    /// # Errors
69    ///
70    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
71    #[inline]
72    fn read_be<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
73    where
74        for<'a> Self::Args<'a>: Required,
75    {
76        Self::read_be_args(reader, Self::Args::args())
77    }
78
79    /// Read `Self` from the reader using default arguments and assuming
80    /// little-endian byte order.
81    ///
82    /// # Errors
83    ///
84    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
85    #[inline]
86    fn read_le<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
87    where
88        for<'a> Self::Args<'a>: Required,
89    {
90        Self::read_le_args(reader, Self::Args::args())
91    }
92
93    /// Read `T` from the reader assuming native-endian byte order.
94    ///
95    /// # Errors
96    ///
97    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
98    #[inline]
99    fn read_ne<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
100    where
101        for<'a> Self::Args<'a>: Required,
102    {
103        Self::read_ne_args(reader, Self::Args::args())
104    }
105
106    /// Read `Self` from the reader using the given arguments.
107    ///
108    /// # Errors
109    ///
110    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
111    #[inline]
112    fn read_args<R: Read + Seek>(reader: &mut R, args: Self::Args<'_>) -> BinResult<Self>
113    where
114        Self: ReadEndian,
115    {
116        Self::read_options(reader, Endian::Little, args)
117    }
118
119    /// Read `Self` from the reader, assuming big-endian byte order, using the
120    /// given arguments.
121    ///
122    /// # Errors
123    ///
124    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
125    #[inline]
126    fn read_be_args<R: Read + Seek>(reader: &mut R, args: Self::Args<'_>) -> BinResult<Self> {
127        Self::read_options(reader, Endian::Big, args)
128    }
129
130    /// Read `Self` from the reader, assuming little-endian byte order, using
131    /// the given arguments.
132    ///
133    /// # Errors
134    ///
135    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
136    #[inline]
137    fn read_le_args<R: Read + Seek>(reader: &mut R, args: Self::Args<'_>) -> BinResult<Self> {
138        Self::read_options(reader, Endian::Little, args)
139    }
140
141    /// Read `T` from the reader, assuming native-endian byte order, using the
142    /// given arguments.
143    ///
144    /// # Errors
145    ///
146    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
147    #[inline]
148    fn read_ne_args<R: Read + Seek>(reader: &mut R, args: Self::Args<'_>) -> BinResult<Self> {
149        Self::read_options(reader, Endian::NATIVE, args)
150    }
151
152    /// Read `Self` from the reader using the given [`Endian`] and
153    /// arguments.
154    ///
155    /// # Errors
156    ///
157    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
158    ///
159    /// # Examples
160    ///
161    /// ```
162    /// # use binrw::{BinRead, BinResult};
163    /// # use binrw::io::{Read, Seek, SeekFrom};
164    /// struct CustomPtr32<T>(T);
165    ///
166    /// impl<T> BinRead for CustomPtr32<T>
167    /// where
168    ///     for<'a> T: BinRead<Args<'a> = ()>,
169    /// {
170    ///     type Args<'a> = u64;
171    ///
172    ///     fn read_options<R: Read + Seek>(
173    ///         reader: &mut R,
174    ///         endian: binrw::Endian,
175    ///         args: Self::Args<'_>,
176    ///     ) -> BinResult<Self> {
177    ///         let offset = u32::read_options(reader, endian, ())?;
178    ///         let saved_position = reader.stream_position()?;
179    ///
180    ///         // Read from an offset with a provided base offset.
181    ///         reader.seek(SeekFrom::Start(args + offset as u64))?;
182    ///         let value = T::read_options(reader, endian, ())?;
183    ///
184    ///         reader.seek(SeekFrom::Start(saved_position))?;
185    ///
186    ///         Ok(CustomPtr32(value))
187    ///     }
188    /// }
189    /// ```
190    fn read_options<R: Read + Seek>(
191        reader: &mut R,
192        endian: Endian,
193        args: Self::Args<'_>,
194    ) -> BinResult<Self>;
195}
196
197/// Extension methods for reading [`BinRead`] objects directly from a reader.
198///
199/// # Examples
200///
201/// ```
202/// use binrw::{BinReaderExt, Endian, io::Cursor};
203///
204/// let mut reader = Cursor::new(b"\x07\0\0\0\xCC\0\0\x05");
205/// let x: u32 = reader.read_le().unwrap();
206/// let y: u16 = reader.read_type(Endian::Little).unwrap();
207/// let z = reader.read_be::<u16>().unwrap();
208///
209/// assert_eq!((x, y, z), (7u32, 0xCCu16, 5u16));
210/// ```
211pub trait BinReaderExt: Read + Seek + Sized {
212    /// Read `T` from the reader with the given byte order.
213    ///
214    /// # Errors
215    ///
216    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
217    #[inline]
218    fn read_type<'a, T>(&mut self, endian: Endian) -> BinResult<T>
219    where
220        T: BinRead,
221        T::Args<'a>: Required,
222    {
223        self.read_type_args(endian, T::Args::args())
224    }
225
226    /// Read `T` from the reader assuming big-endian byte order.
227    ///
228    /// # Errors
229    ///
230    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
231    #[inline]
232    fn read_be<'a, T>(&mut self) -> BinResult<T>
233    where
234        T: BinRead,
235        T::Args<'a>: Required,
236    {
237        self.read_type(Endian::Big)
238    }
239
240    /// Read `T` from the reader assuming little-endian byte order.
241    ///
242    /// # Errors
243    ///
244    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
245    #[inline]
246    fn read_le<'a, T>(&mut self) -> BinResult<T>
247    where
248        T: BinRead,
249        T::Args<'a>: Required,
250    {
251        self.read_type(Endian::Little)
252    }
253
254    /// Read `T` from the reader assuming native-endian byte order.
255    ///
256    /// # Errors
257    ///
258    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
259    #[inline]
260    fn read_ne<'a, T>(&mut self) -> BinResult<T>
261    where
262        T: BinRead,
263        T::Args<'a>: Required,
264    {
265        self.read_type(Endian::NATIVE)
266    }
267
268    /// Read `T` from the reader with the given byte order and arguments.
269    ///
270    /// # Errors
271    ///
272    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
273    #[inline]
274    fn read_type_args<T>(&mut self, endian: Endian, args: T::Args<'_>) -> BinResult<T>
275    where
276        T: BinRead,
277    {
278        T::read_options(self, endian, args)
279    }
280
281    /// Read `T` from the reader, assuming big-endian byte order, using the
282    /// given arguments.
283    ///
284    /// # Errors
285    ///
286    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
287    #[inline]
288    fn read_be_args<T>(&mut self, args: T::Args<'_>) -> BinResult<T>
289    where
290        T: BinRead,
291    {
292        self.read_type_args(Endian::Big, args)
293    }
294
295    /// Read `T` from the reader, assuming little-endian byte order, using the
296    /// given arguments.
297    ///
298    /// # Errors
299    ///
300    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
301    #[inline]
302    fn read_le_args<T>(&mut self, args: T::Args<'_>) -> BinResult<T>
303    where
304        T: BinRead,
305    {
306        self.read_type_args(Endian::Little, args)
307    }
308
309    /// Read `T` from the reader, assuming native-endian byte order, using the
310    /// given arguments.
311    ///
312    /// # Errors
313    ///
314    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
315    #[inline]
316    fn read_ne_args<T>(&mut self, args: T::Args<'_>) -> BinResult<T>
317    where
318        T: BinRead,
319    {
320        self.read_type_args(Endian::NATIVE, args)
321    }
322}
323
324impl<R: Read + Seek + Sized> BinReaderExt for R {}