| 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 | |