use crate::attributes::ExportsFlags;
use crate::byte_reader::ByteReader;
use crate::error::Result;
use byteorder::{BigEndian, WriteBytesExt};
use std::fmt;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Exports {
pub index: u16,
pub flags: ExportsFlags,
pub to_index: Vec<u16>,
}
impl Exports {
pub fn from_bytes(bytes: &mut ByteReader<'_>) -> Result<Exports> {
let index = bytes.read_u16()?;
let flags = ExportsFlags::from_bytes(bytes)?;
let to_index_count = bytes.read_u16()?;
let mut to_index = Vec::with_capacity(to_index_count as usize);
for _ in 0..to_index_count {
to_index.push(bytes.read_u16()?);
}
let requires = Exports {
index,
flags,
to_index,
};
Ok(requires)
}
pub fn to_bytes(&self, bytes: &mut Vec<u8>) -> Result<()> {
bytes.write_u16::<BigEndian>(self.index)?;
self.flags.to_bytes(bytes)?;
let to_index_length = u16::try_from(self.to_index.len())?;
bytes.write_u16::<BigEndian>(to_index_length)?;
for index in &self.to_index {
bytes.write_u16::<BigEndian>(*index)?;
}
Ok(())
}
}
impl fmt::Display for Exports {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"index: {}, flags: {}, to_index: {:?}",
self.index, self.flags, self.to_index
)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_to_string() {
let exports = Exports {
index: 1,
flags: ExportsFlags::MANDATED,
to_index: vec![3],
};
assert_eq!(
"index: 1, flags: (0x8000) ACC_MANDATED, to_index: [3]",
exports.to_string()
);
}
#[test]
fn test_serialization() -> Result<()> {
let exports = Exports {
index: 1,
flags: ExportsFlags::MANDATED,
to_index: vec![3],
};
let expected_value = [0, 1, 128, 0, 0, 1, 0, 3];
let mut bytes = Vec::new();
exports.clone().to_bytes(&mut bytes)?;
assert_eq!(expected_value, &bytes[..]);
let mut bytes = ByteReader::new(&expected_value);
assert_eq!(exports, Exports::from_bytes(&mut bytes)?);
Ok(())
}
}