1 | use alloc::vec::Vec; |
2 | use std::mem; |
3 | |
4 | use crate::endianity::Endianity; |
5 | use 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)] |
11 | pub struct EndianVec<Endian> |
12 | where |
13 | Endian: Endianity, |
14 | { |
15 | vec: Vec<u8>, |
16 | endian: Endian, |
17 | } |
18 | |
19 | impl<Endian> EndianVec<Endian> |
20 | where |
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 | |
49 | impl<Endian> Writer for EndianVec<Endian> |
50 | where |
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)] |
85 | mod 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 | } |
118 | |