Skip to content

Instantly share code, notes, and snippets.

@richo
Created May 29, 2015 03:01
Show Gist options
  • Select an option

  • Save richo/219fe5dad8c4d78aca71 to your computer and use it in GitHub Desktop.

Select an option

Save richo/219fe5dad8c4d78aca71 to your computer and use it in GitHub Desktop.
#![feature(convert)]
/* Documentation for the various blocktypes
0x00000000 Reserved ???
0x00000001 Interface Description Block
0x00000002 Packet Block
0x00000003 Simple Packet Block
0x00000004 Name Resolution Block
0x00000005 Interface Statistics Block
0x00000006 Enhanced Packet Block
0x00000007 IRIG Timestamp Block (requested by Gianluca Varenni <[email protected]>, CACE Technologies LLC)
0x00000008 Arinc 429 in AFDX Encapsulation Information Block (requested by Gianluca Varenni <[email protected]>, CACE Technologies LLC)
0x0A0D0D0A Section Header Block
*/
use std::io;
use std::io::{Read,SeekFrom,Seek};
use std::mem;
type Body = [u8];
pub type BlockType = u32;
pub type BlockLength = u32;
const BOM: u32 = 0x1A2B3C4D;
pub struct SecHdr {
ty: BlockType,
total_length: u32,
pub major_version: u16,
pub minor_version: u16,
pub section_length: u64,
buf: Vec<u8>,
}
pub enum Block {
SectionHeader(SecHdr),
// InterfaceDescription(Box<Body>),
// Packet(Box<Body>),
// TODO other block types
Debug(BlockType, BlockLength, Vec<u8>)
}
macro_rules! read_to {
($ty:ty, $len:expr, $reader:expr) => {{
let mut buf: [u8; $len] = [0; $len];
try!($reader.read(&mut buf));
let ret: $ty = unsafe { mem::transmute(buf) };
ret
}}
}
const BLOCK_ALIGN: u32 = 4; // 32 bits
impl Block {
pub fn read_from_file<R>(reader: &mut R) -> Result<Block, io::Error>
where R: Read + Seek {
let ty = read_to!(u32, 4, reader);
let block_len = read_to!(u32, 4, reader);
let body_len = block_len - 12; // An empty block is 12 byte
let mut body = vec![0; body_len as usize];
let read = try!(reader.read(&mut body));
assert!(read == body_len as usize, "Couldn't read the whole body into the vector");
// Advance the reader to u32 alignment
let spill = BLOCK_ALIGN - (body_len % BLOCK_ALIGN);
if spill != BLOCK_ALIGN {
try!(reader.seek(SeekFrom::Current(spill as i64)));
}
let check_len = read_to!(u32, 4, reader);
assert!(check_len == block_len, "Invalid block, len's don't match");
Ok(Block::block_from_type(ty, body))
}
fn block_from_type(ty: u32, body: Vec<u8>) -> Block {
match ty {
0x0A0D0D0A => { // Section Header Block
// TODO maybe this wants to go into a SecHdr constructor
// let bom: u32 = unsafe { mem::transmute(&body[8..12]) };
// assert!(bom == BOM, "Invalid bom in a section header");
// let minor: u16 = unsafe { mem::transmute(&body[12..14]) };
// let major: u16 = unsafe { mem::transmute(&body[14..16]) };
// let section_length: u64 = unsafe { mem::transmute(&body[16..24]) };
// Block::SectionHeader(SecHdr {
// ty: ty,
// total_length: body.len() as u32,
// major_version: major,
// minor_version: minor,
// section_length: section_length,
// buf: body,
// }
Block::Debug(ty, body.len() as u32, body)
},
_ => panic!("Unknown block type: {:x}", ty),
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment