Skip to main content

jvm_class/
cursor.rs

1use crate::{
2    CpIndex,
3    error::{Error, Result},
4};
5
6/// Cursor over a borrowed byte slice, reading big-endian values from the front.
7#[derive(Debug, Clone, Copy)]
8pub struct Cursor<'a>(&'a [u8]);
9
10impl<'a> Cursor<'a> {
11    /// Creates a cursor positioned at the start of `bytes`.
12    pub fn new(bytes: &'a [u8]) -> Self {
13        Self(bytes)
14    }
15
16    /// Returns the not yet consumed bytes.
17    pub fn remaining(&self) -> &'a [u8] {
18        self.0
19    }
20
21    /// Returns the number of not yet consumed bytes.
22    pub fn len(&self) -> usize {
23        self.0.len()
24    }
25
26    /// Returns `true` if everything has been consumed.
27    pub fn is_empty(&self) -> bool {
28        self.0.is_empty()
29    }
30}
31
32impl<'a> From<&'a [u8]> for Cursor<'a> {
33    fn from(value: &'a [u8]) -> Self {
34        Self::new(value)
35    }
36}
37
38/// Generates big-endian readers for fixed-size integer types.
39macro_rules! read_int {
40    ($($name:ident -> $type:ty),* $(,)?) => {$(
41        /// Reads a big-endian value, advancing past it.
42        fn $name(&mut self) -> Result<$type> {
43            let mut buf = [0u8; size_of::<$type>()];
44            buf.copy_from_slice(self.read_bytes(size_of::<$type>())?);
45
46            Ok(<$type>::from_be_bytes(buf))
47        }
48    )*};
49}
50
51/// Big-endian reading primitives shared by every parser in this crate.
52pub trait ReadBytes<'a> {
53    /// Consumes exactly `len` bytes, or fails with [`Error::UnexpectedEof`].
54    fn read_bytes(&mut self, len: usize) -> Result<&'a [u8]>;
55
56    /// Consumes and returns everything that is left.
57    fn read_rest(&mut self) -> &'a [u8];
58
59    read_int! {
60        read_u8 -> u8,
61        read_u16 -> u16,
62        read_u32 -> u32,
63        read_u64 -> u64,
64        read_i32 -> i32,
65        read_i64 -> i64,
66    }
67
68    /// Reads an IEEE 754 single-precision float.
69    fn read_f32(&mut self) -> Result<f32> {
70        Ok(f32::from_bits(self.read_u32()?))
71    }
72
73    /// Reads an IEEE 754 double-precision float.
74    fn read_f64(&mut self) -> Result<f64> {
75        Ok(f64::from_bits(self.read_u64()?))
76    }
77
78    /// Reads a `u16` count, then applies `fun` that many times.
79    fn repeat_by_u16<T>(&mut self, mut fun: impl FnMut(&mut Self) -> Result<T>) -> Result<Vec<T>>
80    where
81        Self: Sized,
82    {
83        let count = self.read_u16()?;
84        let mut items = Vec::with_capacity(count as usize);
85
86        for _ in 0..count {
87            items.push(fun(self)?);
88        }
89
90        Ok(items)
91    }
92
93    /// Reads a `u8` count, then applies `fun` that many times.
94    fn repeat_by_u8<T>(&mut self, mut fun: impl FnMut(&mut Self) -> Result<T>) -> Result<Vec<T>>
95    where
96        Self: Sized,
97    {
98        let count = self.read_u8()?;
99        let mut items = Vec::with_capacity(count as usize);
100
101        for _ in 0..count {
102            items.push(fun(self)?);
103        }
104
105        Ok(items)
106    }
107
108    /// Reads a `u16`-prefixed list of constant pool indices.
109    fn read_indices(&mut self) -> Result<Vec<CpIndex>>
110    where
111        Self: Sized,
112    {
113        self.repeat_by_u16(|cursor| cursor.read_u16())
114    }
115
116    /// Reads a constant pool index where `0` means "absent".
117    fn read_optional_index(&mut self) -> Result<Option<CpIndex>> {
118        let index = self.read_u16()?;
119
120        Ok((index != 0).then_some(index))
121    }
122}
123
124impl<'a> ReadBytes<'a> for Cursor<'a> {
125    fn read_bytes(&mut self, len: usize) -> Result<&'a [u8]> {
126        match self.0.split_at_checked(len) {
127            Some((head, tail)) => {
128                self.0 = tail;
129
130                Ok(head)
131            }
132            None => Err(Error::UnexpectedEof {
133                needed: len,
134                available: self.0.len(),
135            }),
136        }
137    }
138
139    fn read_rest(&mut self) -> &'a [u8] {
140        std::mem::take(&mut self.0)
141    }
142}