gimli/write/
endian_vec.rs

1use alloc::vec::Vec;
2use std::mem;
3
4use crate::endianity::Endianity;
5use crate::write::{Error, Result, Writer};
6
7/// A `Vec<u8>` with endianity metadata.
8///
9/// This implements the `Writer` trait, which is used for all writing of DWARF sections.
10#[derive(Debug, Clone)]
11pub struct EndianVec<Endian>
12where
13    Endian: Endianity,
14{
15    vec: Vec<u8>,
16    endian: Endian,
17}
18
19impl<Endian> EndianVec<Endian>
20where
21    Endian: Endianity,
22{
23    /// Construct an empty `EndianVec` with the given endianity.
24    pub fn new(endian: Endian) -> EndianVec<Endian> {
25        EndianVec {
26            vec: Vec::new(),
27            endian,
28        }
29    }
30
31    /// Return a reference to the raw slice.
32    pub fn slice(&self) -> &[u8] {
33        &self.vec
34    }
35
36    /// Convert into a `Vec<u8>`.
37    pub fn into_vec(self) -> Vec<u8> {
38        self.vec
39    }
40
41    /// Take any written data out of the `EndianVec`, leaving an empty `Vec` in its place.
42    pub fn take(&mut self) -> Vec<u8> {
43        let mut vec = Vec::new();
44        mem::swap(&mut self.vec, &mut vec);
45        vec
46    }
47}
48
49impl<Endian> Writer for EndianVec<Endian>
50where
51    Endian: Endianity,
52{
53    type Endian = Endian;
54
55    #[inline]
56    fn endian(&self) -> Self::Endian {
57        self.endian
58    }
59
60    #[inline]
61    fn len(&self) -> usize {
62        self.vec.len()
63    }
64
65    fn write(&mut self, bytes: &[u8]) -> Result<()> {
66        self.vec.extend(bytes);
67        Ok(())
68    }
69
70    fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> {
71        if offset > self.vec.len() {
72            return Err(Error::OffsetOutOfBounds);
73        }
74        let to = &mut self.vec[offset..];
75        if bytes.len() > to.len() {
76            return Err(Error::LengthOutOfBounds);
77        }
78        let to = &mut to[..bytes.len()];
79        to.copy_from_slice(bytes);
80        Ok(())
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87    use crate::LittleEndian;
88
89    #[test]
90    fn test_endian_vec() {
91        let mut w = EndianVec::new(LittleEndian);
92        assert_eq!(w.endian(), LittleEndian);
93        assert_eq!(w.len(), 0);
94
95        w.write(&[1, 2]).unwrap();
96        assert_eq!(w.slice(), &[1, 2]);
97        assert_eq!(w.len(), 2);
98
99        w.write(&[3, 4, 5]).unwrap();
100        assert_eq!(w.slice(), &[1, 2, 3, 4, 5]);
101        assert_eq!(w.len(), 5);
102
103        w.write_at(0, &[6, 7]).unwrap();
104        assert_eq!(w.slice(), &[6, 7, 3, 4, 5]);
105        assert_eq!(w.len(), 5);
106
107        w.write_at(3, &[8, 9]).unwrap();
108        assert_eq!(w.slice(), &[6, 7, 3, 8, 9]);
109        assert_eq!(w.len(), 5);
110
111        assert_eq!(w.write_at(4, &[6, 7]), Err(Error::LengthOutOfBounds));
112        assert_eq!(w.write_at(5, &[6, 7]), Err(Error::LengthOutOfBounds));
113        assert_eq!(w.write_at(6, &[6, 7]), Err(Error::OffsetOutOfBounds));
114
115        assert_eq!(w.into_vec(), vec![6, 7, 3, 8, 9]);
116    }
117}