binrw/
pos_value.rs

1use crate::{
2    io::{Read, Seek},
3    BinRead, BinResult, Endian,
4};
5use core::fmt;
6
7/// A wrapper that stores a value’s position alongside the value.
8///
9/// # Examples
10///
11/// ```
12/// use binrw::{BinRead, PosValue, BinReaderExt, io::Cursor};
13///
14/// #[derive(BinRead)]
15/// struct MyType {
16///     a: u16,
17///     b: PosValue<u8>
18/// }
19///
20/// let val = Cursor::new(b"\xFF\xFE\xFD").read_be::<MyType>().unwrap();
21/// assert_eq!(val.b.pos, 2);
22/// assert_eq!(*val.b, 0xFD);
23/// ```
24pub struct PosValue<T> {
25    /// The read value.
26    pub val: T,
27
28    /// The byte position of the start of the value.
29    pub pos: u64,
30}
31
32impl<T: BinRead> BinRead for PosValue<T> {
33    type Args<'a> = T::Args<'a>;
34
35    fn read_options<R: Read + Seek>(
36        reader: &mut R,
37        endian: Endian,
38        args: Self::Args<'_>,
39    ) -> BinResult<Self> {
40        let pos = reader.stream_position()?;
41
42        Ok(PosValue {
43            pos,
44            val: T::read_options(reader, endian, args)?,
45        })
46    }
47}
48
49impl<T> core::ops::Deref for PosValue<T> {
50    type Target = T;
51
52    fn deref(&self) -> &T {
53        &self.val
54    }
55}
56
57impl<T> core::ops::DerefMut for PosValue<T> {
58    fn deref_mut(&mut self) -> &mut T {
59        &mut self.val
60    }
61}
62
63impl<T: fmt::Debug> fmt::Debug for PosValue<T> {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        self.val.fmt(f)
66    }
67}
68
69impl<T: Clone> Clone for PosValue<T> {
70    fn clone(&self) -> Self {
71        Self {
72            val: self.val.clone(),
73            pos: self.pos,
74        }
75    }
76}
77
78impl<U, T: PartialEq<U>> PartialEq<U> for PosValue<T> {
79    fn eq(&self, other: &U) -> bool {
80        self.val == *other
81    }
82}