lsda 0.1.0

Read and write the language-specific data area of GCC-compatible exception handling (.gcc_except_table).
Documentation
use alloc::vec::Vec;
use core::mem;

use crate::endianity::Endianity;
use crate::write::{Result, Writer};

/// A `Vec<u8>` with endianity metadata.
///
/// This implements the [`Writer`] trait, which is used for all writing of
/// LSDA sections.
#[derive(Debug, Clone)]
pub struct EndianVec<Endian>
where
    Endian: Endianity,
{
    vec: Vec<u8>,
    endian: Endian,
}

impl<Endian> EndianVec<Endian>
where
    Endian: Endianity,
{
    /// Construct an empty `EndianVec` with the given endianity.
    pub fn new(endian: Endian) -> EndianVec<Endian> {
        EndianVec {
            vec: Vec::new(),
            endian,
        }
    }

    /// Return a reference to the raw slice.
    pub fn slice(&self) -> &[u8] {
        &self.vec
    }

    /// Convert into a `Vec<u8>`.
    pub fn into_vec(self) -> Vec<u8> {
        self.vec
    }

    /// Take any written data out of the `EndianVec`, leaving an empty `Vec`
    /// in its place.
    pub fn take(&mut self) -> Vec<u8> {
        mem::take(&mut self.vec)
    }
}

impl<Endian> Writer for EndianVec<Endian>
where
    Endian: Endianity,
{
    type Endian = Endian;

    #[inline]
    fn endian(&self) -> Self::Endian {
        self.endian
    }

    #[inline]
    fn len(&self) -> usize {
        self.vec.len()
    }

    fn write(&mut self, bytes: &[u8]) -> Result<()> {
        self.vec.extend_from_slice(bytes);
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::endianity::{BigEndian, LittleEndian};

    #[test]
    fn test_endian_vec() {
        let mut w = EndianVec::new(LittleEndian);
        w.write_u32(0x0102_0304).unwrap();
        w.write_u16(0x0506).unwrap();
        assert_eq!(w.slice(), [4, 3, 2, 1, 6, 5]);

        let mut w = EndianVec::new(BigEndian);
        w.write_u32(0x0102_0304).unwrap();
        assert_eq!(w.take(), [1, 2, 3, 4]);
        assert_eq!(w.len(), 0);
    }
}