use std::collections::HashMap;
use std::sync::Arc as Rc;
use error::{EncodeErrorKind, EncodeResult};
pub struct BinEncoder<'a> {
offset: u32,
buffer: &'a mut Vec<u8>,
name_pointers: HashMap<Vec<Rc<String>>, u16>, mode: EncodeMode,
canonical_names: bool,
}
impl<'a> BinEncoder<'a> {
pub fn new(buf: &'a mut Vec<u8>) -> Self {
Self::with_offset(buf, 0, EncodeMode::Normal)
}
pub fn with_mode(buf: &'a mut Vec<u8>, mode: EncodeMode) -> Self {
Self::with_offset(buf, 0, mode)
}
pub fn with_offset(buf: &'a mut Vec<u8>, offset: u32, mode: EncodeMode) -> Self {
BinEncoder {
offset: offset,
buffer: buf,
name_pointers: HashMap::new(),
mode: mode,
canonical_names: false,
}
}
pub fn as_bytes(self) -> &'a Vec<u8> {
self.buffer
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn offset(&self) -> u32 {
self.offset
}
pub fn mode(&self) -> EncodeMode {
self.mode
}
pub fn set_canonical_names(&mut self, canonical_names: bool) {
self.canonical_names = canonical_names;
}
pub fn is_canonical_names(&self) -> bool {
self.canonical_names
}
pub fn reserve(&mut self, extra: usize) {
self.buffer.reserve(extra);
}
pub fn emit(&mut self, b: u8) -> EncodeResult {
self.offset += 1;
self.buffer.push(b);
Ok(())
}
pub fn store_label_pointer(&mut self, labels: Vec<Rc<String>>) {
if self.offset < 0x3FFFu32 {
self.name_pointers.insert(labels, self.offset as u16); }
}
pub fn get_label_pointer(&self, labels: &[Rc<String>]) -> Option<u16> {
self.name_pointers.get(labels).map(|i| *i)
}
pub fn emit_character_data(&mut self, char_data: &str) -> EncodeResult {
let char_bytes = char_data.as_bytes();
if char_bytes.len() > 255 {
return Err(EncodeErrorKind::CharacterDataTooLong(char_bytes.len()).into());
}
self.buffer.reserve(char_bytes.len() + 1); try!(self.emit(char_bytes.len() as u8));
for b in char_bytes {
try!(self.emit(*b));
}
Ok(())
}
pub fn emit_u16(&mut self, data: u16) -> EncodeResult {
self.buffer.reserve(2);
let b1: u8 = (data >> 8 & 0xFF) as u8;
let b2: u8 = (data & 0xFF) as u8;
try!(self.emit(b1));
try!(self.emit(b2));
Ok(())
}
pub fn emit_i32(&mut self, data: i32) -> EncodeResult {
self.buffer.reserve(4);
let b1: u8 = (data >> 24 & 0xFF) as u8;
let b2: u8 = (data >> 16 & 0xFF) as u8;
let b3: u8 = (data >> 8 & 0xFF) as u8;
let b4: u8 = (data & 0xFF) as u8;
try!(self.emit(b1));
try!(self.emit(b2));
try!(self.emit(b3));
try!(self.emit(b4));
Ok(())
}
pub fn emit_u32(&mut self, data: u32) -> EncodeResult {
self.buffer.reserve(4);
let b1: u8 = (data >> 24 & 0xFF) as u8;
let b2: u8 = (data >> 16 & 0xFF) as u8;
let b3: u8 = (data >> 8 & 0xFF) as u8;
let b4: u8 = (data & 0xFF) as u8;
try!(self.emit(b1));
try!(self.emit(b2));
try!(self.emit(b3));
try!(self.emit(b4));
Ok(())
}
pub fn emit_vec(&mut self, data: &[u8]) -> EncodeResult {
self.buffer.reserve(data.len());
for i in data {
try!(self.emit(*i));
}
Ok(())
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum EncodeMode {
Signing,
Normal,
}