Browse Source

Remove byteorder crate dependency. Move I/O outside of decoding

tags/v0.3.0
Alex Williams 8 months ago
parent
commit
f44996c9b4
Signed by: aw GPG Key ID: 19EE4AAA361A7E2C
3 changed files with 58 additions and 99 deletions
  1. +0
    -9
      Cargo.lock
  2. +0
    -1
      Cargo.toml
  3. +58
    -89
      src/lib.rs

+ 0
- 9
Cargo.lock View File

@ -3,12 +3,3 @@
[[package]]
name = "boawp-validator"
version = "0.3.0"
dependencies = [
"byteorder",
]
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"

+ 0
- 1
Cargo.toml View File

@ -12,4 +12,3 @@ publish = false
default-run = "validate"
[dependencies]
byteorder = "1"

+ 58
- 89
src/lib.rs View File

@ -44,8 +44,7 @@ assert_eq!(validated.3, Body { body: vec![] });
There are future plans to export the public functions for C/FFI bindings.
*/
use byteorder::{BigEndian, ReadBytesExt};
use std::{io::ErrorKind, io::BufReader, io::Cursor, io::Error, io::Read, str::from_utf8_unchecked};
use std::{io::ErrorKind, io::BufReader, io::Error, io::Read, str::from_utf8_unchecked, convert::TryInto};
pub mod protocols;
@ -54,7 +53,7 @@ use protocols::http::commands;
use protocols::http::header_names;
use protocols::http::header_names_rev;
type HeaderBuffer<'a> = &'a mut Vec<u8>;
type DataBuffer<'a> = &'a mut Vec<u8>;
type HeaderLength<'a> = u8;
type BufferVector<'a> = Result<Vec<u8>, Error>;
@ -122,7 +121,7 @@ pub enum Integer {
}
impl Header {
fn get_string(buffer: HeaderBuffer, vlength: HeaderLength) -> Result<String, Error> {
fn get_string(buffer: DataBuffer, vlength: HeaderLength) -> Result<String, Error> {
let res = String::from_utf8(Header::get_vec(buffer, vlength));
if let Ok(x) = res {
Ok(x)
@ -130,24 +129,24 @@ impl Header {
Err(Error::new(ErrorKind::InvalidData, "Invalid UTF-8 string"))
}
}
fn get_integer(buffer: HeaderBuffer, vlength: HeaderLength) -> Result<Integer, Error> {
let mut reader = Cursor::new(Header::get_vec(buffer, vlength));
fn get_integer(buffer: DataBuffer, vlength: HeaderLength) -> Result<Integer, Error> {
let res = Header::get_vec(buffer, vlength);
let int = match vlength {
0 => Integer::Zero(),
1 => Integer::One(reader.read_u8()?),
2 => Integer::Two(reader.read_i16::<BigEndian>()?),
4 => Integer::Four(reader.read_i32::<BigEndian>()?),
8 => Integer::Eight(reader.read_i64::<BigEndian>()?),
16 => Integer::Sixteen(reader.read_i128::<BigEndian>()?),
_ => Integer::BigNum(reader.into_inner()),
1 => Integer::One(u8::from_be_bytes(res[0..1].try_into().unwrap())),
2 => Integer::Two(i16::from_be_bytes(res[0..2].try_into().unwrap())),
4 => Integer::Four(i32::from_be_bytes(res[0..4].try_into().unwrap())),
8 => Integer::Eight(i64::from_be_bytes(res[0..8].try_into().unwrap())),
16 => Integer::Sixteen(i128::from_be_bytes(res[0..16].try_into().unwrap())),
_ => Integer::BigNum(res[0..vlength as usize].try_into().unwrap()),
};
Ok(int)
}
fn get_headers(buffer: HeaderBuffer, vlength: HeaderLength) -> Result<Headers, Error> {
fn get_headers(buffer: DataBuffer, vlength: HeaderLength) -> Result<Headers, Error> {
let res = Headers { headers: decode_headers(&mut Header::get_vec(buffer, vlength))? };
Ok(res)
}
fn get_vec(buffer: HeaderBuffer, vlength: HeaderLength) -> Vec<u8> {
fn get_vec(buffer: DataBuffer, vlength: HeaderLength) -> Vec<u8> {
buffer.drain(..vlength as usize).collect()
}
}
@ -159,7 +158,7 @@ impl Header {
///
/// The length of all frame headers can not be 1, 2, or 3, and must adhere to
/// other strict formatting rules.
pub fn decode_headers(buf: HeaderBuffer) -> Result<Vec<(String, Header)>, Error> {
pub fn decode_headers(buf: DataBuffer) -> Result<Vec<(String, Header)>, Error> {
let mut buffer = buf;
let mut headers = Vec::with_capacity(buffer.len());
@ -250,17 +249,13 @@ pub fn decode_headers(buf: HeaderBuffer) -> Result<Vec<(String, Header)>, Error>
///
/// A valid NOOP frame contains a fixed header with the `\n` (0x0A) command, and
/// a zero-length headers and zero-length body.
pub fn decode_fixed_header<R: Read>(reader: &mut R) -> Result<Fixed, Error> {
let mut buffer = [0; 2];
reader.read(&mut buffer)?;
let hlength = reader.read_u16::<BigEndian>()?;
let blength = reader.read_u32::<BigEndian>()?;
pub fn decode_fixed_header(null: u8, cmd: u8, hlength: u16, blength: u32) -> Result<Fixed, Error> {
let fixed = Fixed {
null: buffer[0],
cmd: buffer[1] as char,
null,
cmd: cmd as char,
hlength,
blength,
command: commands(buffer[1]).to_string(),
command: commands(cmd).to_string(),
};
match fixed {
f if commands(f.cmd as u8).is_empty() => Err(Error::new(ErrorKind::InvalidData, "Unknown command")),
@ -271,28 +266,10 @@ pub fn decode_fixed_header<R: Read>(reader: &mut R) -> Result<Fixed, Error> {
}
}
/// Decodes a BOAWP frame: fixed header, frame headers, body.
pub fn decode_frame<R: Read>(reader: &mut R) -> Result<Frame, Error> {
// fixed header
let fixed = decode_fixed_header(reader)?;
// frame headers
let mut buffer = get_frame_data(reader, fixed.hlength as usize)?;
let headers = Headers { headers: decode_headers(&mut buffer)? };
// body
let body = Body { body: get_frame_data(reader, fixed.blength as usize)? };
let frame = Frame { fixed, headers, body };
Ok(frame)
}
/// Decodes a BOAWP protocol init string.
///
/// The init string is 4 octets (bytes) and must be exactly `"B0A\n"`.
pub fn decode_init<R: Read>(reader: &mut R) -> Result<Init, Error> {
let mut buffer = [0; 4];
reader.read(&mut buffer)?;
pub fn decode_init(buffer: [u8; 4]) -> Result<Init, Error> {
let init = Init {
name: buffer[0] as char,
version: buffer[1] as char,
@ -308,16 +285,38 @@ pub fn decode_init<R: Read>(reader: &mut R) -> Result<Init, Error> {
/// Validates data to ensure it is a correctly formatted BOAWP frame.
pub fn validate<R: Read>(reader: &mut R) -> Result<(Init, Fixed, Headers, Body), Error> {
// protocol init
let init = decode_init(reader)?;
let mut buffer = [0; 4];
reader.read(&mut buffer)?;
let init = decode_init(buffer)?;
// frame
let frame = decode_frame(reader)?;
// fixed header
let mut buffer = [0; 8];
reader.read(&mut buffer)?;
let null = buffer[0];
let cmd = buffer[1];
let hlength: u16 = u16::from_be_bytes([buffer[2], buffer[3]]);
let blength: u32 = u32::from_be_bytes([buffer[4], buffer[5], buffer[6], buffer[7]]);
let fixed = decode_fixed_header(null, cmd, hlength, blength)?;
Ok((init, frame.fixed, frame.headers, frame.body))
// frame headers
let mut buffer = get_frame_data(reader, fixed.hlength as usize)?;
let headers = Headers { headers: decode_headers(&mut buffer)? };
// body
let body = Body { body: get_frame_data(reader, fixed.blength as usize)? };
Ok((init, fixed, headers, body))
}
fn get_frame_data<R: Read>(r: &mut R, len: usize) -> Result<Vec<u8>, Error> {
let mut reader = BufReader::with_capacity(len, r);
let mut buffer: Vec<u8> = vec![0; len]; // allocated on the heap
reader.read(&mut buffer)?;
Ok(buffer)
}
// ENCODING
fn encode_integer<'a>(z: &Integer) -> BufferVector<'a> {
let mut res: Vec<u8> = vec!['i' as u8];
let mut int = match z {
@ -358,7 +357,6 @@ fn encode_string<'a>(z: &String) -> BufferVector<'a> {
Ok(res)
}
// ENCODING
pub fn encode_headers<'a>(headers: &Headers) -> BufferVector<'a> {
let res: Vec<_> = headers.headers.iter()
.map(|(x,y)| {
@ -432,12 +430,7 @@ pub fn encode<'a>(init_str: &str, command_char: char, headers_vec: Headers, body
Ok(res)
}
fn get_frame_data<R: Read>(r: &mut R, len: usize) -> Result<Vec<u8>, Error> {
let mut reader = BufReader::with_capacity(len, r);
let mut buffer: Vec<u8> = vec![0; len]; // allocated on the heap
reader.read(&mut buffer)?;
Ok(buffer)
}
// TESTS
#[cfg(test)]
mod tests {
@ -454,8 +447,7 @@ mod tests {
}
fn _decode_init() {
let x: [u8; 4] = [66, 48, 65, 10];
let mut reader = BufReader::new(&x[..]);
let init = decode_init(&mut reader).unwrap();
let init = decode_init(x).unwrap();
assert_eq!(init.name, 'B');
assert_eq!(init.version, '0');
assert_eq!(init.status, 'A');
@ -464,94 +456,71 @@ mod tests {
#[test]
fn _decode_init_error1() {
let x: [u8; 4] = [65, 48, 65, 10];
let mut reader = BufReader::new(&x[..]);
let res = decode_init(&mut reader);
let res = decode_init(x);
assert!(res.is_err());
assert_eq!(res.unwrap_err().into_inner().unwrap().to_string(), "Invalid protocol init string");
}
#[test]
fn _decode_init_error2() {
let x: [u8; 4] = [66, 49, 65, 10];
let mut reader = BufReader::new(&x[..]);
let res = decode_init(&mut reader);
let res = decode_init(x);
assert!(res.is_err());
assert_eq!(res.unwrap_err().into_inner().unwrap().to_string(), "Invalid protocol init string");
}
#[test]
fn _decode_init_error3() {
let x: [u8; 4] = [66, 48, 65, 11];
let mut reader = BufReader::new(&x[..]);
let res = decode_init(&mut reader);
let res = decode_init(x);
assert!(res.is_err());
assert_eq!(res.unwrap_err().into_inner().unwrap().to_string(), "Invalid protocol init string");
}
#[test]
fn _decode_init_error5() {
let x: [u8; 4] = [66, 48, 66, 10];
let mut reader = BufReader::new(&x[..]);
let res = decode_init(&mut reader);
let res = decode_init(x);
assert!(res.is_err());
assert_eq!(res.unwrap_err().into_inner().unwrap().to_string(), "Invalid protocol init string");
}
#[test]
fn _decode_fixed_header() {
let x: [u8; 8] = [0, 33, 0, 10, 0, 0, 127, 5];
let mut reader = BufReader::new(&x[..]);
let fixed = decode_fixed_header(&mut reader).unwrap();
let fixed = decode_fixed_header(0, 33, 10, 32517).unwrap();
assert_eq!(fixed.cmd, '!');
assert_eq!(fixed.hlength, 10);
assert_eq!(fixed.blength, 32517);
}
#[test]
fn _decode_fixed_header_noop() {
let x: [u8; 8] = [0, 10, 0, 0, 0, 0, 0, 0];
let mut reader = BufReader::new(&x[..]);
let fixed = decode_fixed_header(&mut reader).unwrap();
let fixed = decode_fixed_header(0, 10, 0, 0).unwrap();
assert_eq!(fixed.cmd, '\n');
assert_eq!(fixed.hlength, 0);
assert_eq!(fixed.blength, 0);
}
#[test]
fn _decode_fixed_header_error2() {
let x: [u8; 8] = [0, 10, 0, 0, 0, 0, 0, 5];
let mut reader = BufReader::new(&x[..]);
let res = decode_fixed_header(&mut reader);
let res = decode_fixed_header(0, 10, 0, 5);
assert!(res.is_err());
assert_eq!(res.unwrap_err().into_inner().unwrap().to_string(), "Invalid NOOP frame");
}
#[test]
fn _decode_fixed_header_error3() {
let x: [u8; 8] = [0, 10, 0, 10, 0, 0, 0, 0];
let mut reader = BufReader::new(&x[..]);
let res = decode_fixed_header(&mut reader);
let res = decode_fixed_header(0, 10, 10, 0);
assert!(res.is_err());
assert_eq!(res.unwrap_err().into_inner().unwrap().to_string(), "Invalid NOOP frame");
}
#[test]
fn _decode_fixed_header_error4() {
let x: [u8; 8] = [0, 3, 0, 10, 0, 0, 0, 0];
let mut reader = BufReader::new(&x[..]);
let res = decode_fixed_header(&mut reader);
let res = decode_fixed_header(0, 3, 10, 0);
assert!(res.is_err());
assert_eq!(res.unwrap_err().into_inner().unwrap().to_string(), "Unknown command");
}
#[test]
fn _decode_fixed_header_error5() {
let x: [u8; 8] = [1, 33, 0, 10, 0, 0, 127, 5];
let mut reader = BufReader::new(&x[..]);
let res = decode_fixed_header(&mut reader);
let res = decode_fixed_header(1, 33, 10, 32517);
assert!(res.is_err());
assert_eq!(res.unwrap_err().into_inner().unwrap().to_string(), "Invalid NULL octet");
}
#[test]
fn _decode_frame_data() {
let x = vec![1, 70, 120, 4, 159, 134, 208, 129];
let mut reader = BufReader::new(&x[..]);
let res = get_frame_data(&mut reader, 8).unwrap();
assert_eq!(res, [1, 70, 120, 4, 159, 134, 208, 129]);
}
#[test]
fn _get_vec() {
let mut x = vec![1, 2, 3, 4];
let value = Header::get_vec(&mut x, 4);


Loading…
Cancel
Save