use rustc_serialize::Encoder;
use rustc_serialize::Encodable;
use rustc_serialize::Decoder;
use rustc_serialize::Decodable;
use rustc_serialize::hex::FromHex;
#[derive(Clone,Debug,PartialEq)]
pub struct BytesContainer {
bytes: Vec<u8>,
}
impl BytesContainer {
pub fn new(bytes: Vec<u8>) -> BytesContainer {
BytesContainer { bytes: bytes }
}
pub fn get(&self) -> &Vec<u8> {
&self.bytes
}
pub fn to_bytestr(&self) -> String {
let bytestr: Vec<String> = self.bytes.iter().map(|b| format!("{:02X}", b)).collect();
bytestr.join("")
}
pub fn from_bytestr(bytestr: &str) -> Result<BytesContainer, ()> {
if bytestr.is_empty() {
return Ok(BytesContainer::new(vec![]));
}
match bytestr.from_hex() {
Ok(vec) => Ok(BytesContainer::new(vec)),
_ => Err(()),
}
}
}
impl Decodable for BytesContainer {
fn decode<T: Decoder>(d: &mut T) -> Result<BytesContainer, T::Error> {
let bytestr = try!(String::decode(d));
match BytesContainer::from_bytestr(&bytestr) {
Ok(bc) => Ok(bc),
Err(_) => Err(d.error("Failed to parse hex string")),
}
}
}
impl Encodable for BytesContainer {
fn encode<T: Encoder>(&self, d: &mut T) -> Result<(), T::Error> {
self.to_bytestr().encode(d)
}
}
impl Drop for BytesContainer {
fn drop(&mut self) {
use std::ptr::write_volatile;
for a in &mut self.bytes {
unsafe {
write_volatile(a, 0xA0);
}
}
}
}
#[test]
fn test_encoding() {
use rustc_serialize::json;
let bc = BytesContainer::new(vec![1, 2, 3, 100]);
assert_eq!(json::encode(&bc).unwrap(), "\"01020364\"");
let bc = BytesContainer::new(vec![]);
assert_eq!(json::encode(&bc).unwrap(), "\"\"");
}
#[test]
fn test_decoding() {
use rustc_serialize::json;
let bytestr = "\"A099\"";
let bc: BytesContainer = json::decode(bytestr).unwrap();
assert_eq!(bc.get(), &vec![160, 153]);
let bytestr = "\"\"";
let bc: BytesContainer = json::decode(bytestr).unwrap();
assert_eq!(bc.get(), &vec![]);
}
#[test]
fn test_memclear() {
unsafe {
let ptr: *const Vec<u8>;
{
let a = vec![1, 2, 3];
let bc = BytesContainer::new(a);
ptr = bc.get();
}
assert_eq!(*ptr, vec![0, 0, 0]);
}
}