Rust implementation and BOAWP data validation tool https://boawp.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

726 lines
27 KiB

/*!
This crate is a decoder implementation of the [BOAWP specification](https://boawp.org)
(Binary Oriented Application Wire Protocol). It is used to validate `BOAWP` frames
and ensure serialization implementations are compliant with the spec.
This implementation is 100% spec compliant and should never exit with a panic or
segfault. If it does, please [file an issue](https://git.boawp.org/boawp/boawp-validator/issues/new)
to help resolve that.
Usage is intended through the cli binary `validate`.
## Example
```bash
validate noop.bin
Decoded: (Init { name: 'B', version: '0', status: 'A', lf: '\n' }, Fixed { null: 0, cmd: '\n', hlength: 0, blength: 0, command: "NOOP" }, Headers { headers: [] }, Body { body: [] })
```
A correctly validated file will output the deserialized data to `STDOUT` and the
program will exit with `0`.
It is also possible to call the public functions directly.
## Example
```rust
use std::io::BufReader;
use boawp_validator::*;
// The data we want to decode, a simple NOOP frame
let data: [u8; 12] = [66, 48, 65, 10, 0, 10, 0, 0, 0, 0, 0, 0];
// Create a BufReader to buffer the data
let mut reader = BufReader::new(&data[..]);
// Validate the BOAWP frame
let validated = validate(&mut reader).unwrap();
assert_eq!(validated.0, Init { name: 'B', version: '0', status: 'A', lf: '\n' });
assert_eq!(validated.1, Fixed { null: 0, cmd: '\n', hlength: 0, blength: 0, command: "NOOP".to_string() });
assert_eq!(validated.2, Headers { headers: vec![] });
assert_eq!(validated.3, Body { body: vec![] });
```
There are future plans to export the public functions for C/FFI bindings.
*/
use std::{io::ErrorKind, io::BufReader, io::Error, io::Read, str::from_utf8_unchecked, convert::TryInto};
pub mod protocols;
// use the 'HTTP' protocol by default
use protocols::http::commands;
use protocols::http::header_names;
use protocols::http::header_names_rev;
type DataBuffer<'a> = &'a mut Vec<u8>;
type HeaderLength<'a> = u8;
type BufferVector<'a> = Result<Vec<u8>, Error>;
/// The protocol init string of a BOAWP frame.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Init {
pub name: char,
pub version: char,
pub status: char,
pub lf: char,
}
/// The fixed headers of a BOAWP frame.
#[derive(Clone, Debug, PartialEq)]
pub struct Fixed {
pub null: u8,
pub cmd: char,
pub hlength: u16,
pub blength: u32,
pub command: String,
}
/// The frame headers of a BOAWP frame.
#[derive(Debug, PartialEq)]
pub struct Headers {
pub headers: Vec<(String, Header)>,
}
/// The body of a BOAWP frame.
#[derive(Debug, PartialEq)]
pub struct Body {
pub body: Vec<u8>,
}
/// The fixed header, frame headers, and body of a BOAWP frame.
#[derive(Debug, PartialEq)]
pub struct Frame {
pub fixed: Fixed,
pub headers: Headers,
pub body: Body,
}
/// Header types such as null, bool, string, etc.
#[derive(Debug, PartialEq)]
pub enum Header {
Null,
Boolean(bool),
Integer(Integer),
String(String),
Binary(Vec<u8>),
Header(Headers),
}
/// Signed integer types: 0,8,16,32,64,128-bits,BigNum.
#[derive(Debug, PartialEq)]
pub enum Integer {
Zero(),
One(u8),
Two(i16),
Four(i32),
Eight(i64),
Sixteen(i128),
BigNum(Vec<u8>),
}
impl Header {
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)
} else {
Err(Error::new(ErrorKind::InvalidData, "Invalid UTF-8 string"))
}
}
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(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: DataBuffer, vlength: HeaderLength) -> Result<Headers, Error> {
let res = Headers { headers: decode_headers(&mut Header::get_vec(buffer, vlength))? };
Ok(res)
}
fn get_vec(buffer: DataBuffer, vlength: HeaderLength) -> Vec<u8> {
buffer.drain(..vlength as usize).collect()
}
}
/// Finds a header by name.
pub fn find_header<'a>(headers: &'a Vec<(String, Header)>, name: &str) -> &'a Header {
let res = headers.iter().filter(|x| name == x.0 ).collect::<Vec<_>>();
let val = &res[0].1;
val
}
/// Decodes the BOAWP frame headers.
///
/// The frame headers are a variable length sequence of octets (bytes) which follow
/// a TLV (type-length-value) approach for encoding data.
///
/// 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: DataBuffer) -> Result<Vec<(String, Header)>, Error> {
let mut buffer = buf;
let mut headers = Vec::with_capacity(buffer.len());
match buffer.len() {
1 => return Err(Error::new(ErrorKind::InvalidData, "Invalid headers length '1'")),
2 => return Err(Error::new(ErrorKind::InvalidData, "Invalid headers length '2'")),
3 => return Err(Error::new(ErrorKind::InvalidData, "Invalid headers length '3'")),
_ => {},
}
while buffer.len() > 3 {
let nlength = buffer.remove(0) as u8;
let nvalue = match nlength {
0 => {
return Err(Error::new(ErrorKind::InvalidData, "Invalid header name length"))
}
x if x as usize > buffer.len() => {
return Err(Error::new(ErrorKind::InvalidData, "Invalid header name length"))
}
x if buffer.len() - (x as usize) == 0 => {
return Err(Error::new(ErrorKind::InvalidData, "Invalid header name value '0'"));
}
x if buffer.len() - (x as usize) == 1 => {
return Err(Error::new(ErrorKind::InvalidData, "Invalid header name value '1'"));
}
_ => Header::get_vec(&mut buffer, nlength)
};
let nvalue_ascii = nvalue.iter().filter(|x| x.is_ascii_graphic()).collect::<Vec<_>>().len() as u8;
let vtype = buffer.remove(0) as char;
let vlength = buffer.remove(0) as u8;
if vlength as usize > buffer.len() {
return Err(Error::new(ErrorKind::InvalidData, "Invalid header value length"));
}
let nvalue_str = match nlength {
1 if header_names(nvalue[0]).is_empty() => {
return Err(Error::new(
ErrorKind::InvalidData,
"Unknown header name value",
))
}
1 => header_names(nvalue[0]).to_string(),
_ if nvalue_ascii != nlength => {
return Err(Error::new(
ErrorKind::InvalidData,
"Invalid header name ASCII encoding",
))
}
_ => unsafe { from_utf8_unchecked(&nvalue).to_string() },
};
match vtype {
'n' | 't' | 'f' if vlength > 0 => {
return Err(Error::new(
ErrorKind::InvalidData,
format!(
"Invalid header value length {} for type {}",
vlength, vtype as char
),
))
}
_ => {}
}
if nlength == 1 && nvalue[0] == 32 {
Header::get_vec(&mut buffer, vlength); // noop header, discard data
} else {
let hvalue = match vtype {
'n' => Header::Null,
't' => Header::Boolean(true),
'f' => Header::Boolean(false),
'i' => Header::Integer(Header::get_integer(&mut buffer, vlength)?),
's' => Header::String(Header::get_string(&mut buffer, vlength)?),
'b' => Header::Binary(Header::get_vec(&mut buffer, vlength)),
'h' => Header::Header(Header::get_headers(&mut buffer, vlength)?),
_ => return Err(Error::new(ErrorKind::InvalidData, "Unknown header value type")),
};
headers.push((nvalue_str, hvalue));
}
}
Ok(headers)
}
/// Decodes a BOAWP fixed header.
///
/// The fixed header is 8 octets (bytes), which includes an a null octet, an 8-bit command, a
/// headers length as an unsigned 16-bit integer, and a body length as an unsigned
/// 32-bit integer.
///
/// Valid frames must use a registered command maintained in the [BOAWP registry](https://git.boawp.org/boawp/boawp-registry).
///
/// 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(null: u8, cmd: u8, hlength: u16, blength: u32) -> Result<Fixed, Error> {
let fixed = Fixed {
null,
cmd: cmd as char,
hlength,
blength,
command: commands(cmd).to_string(),
};
match fixed {
f if commands(f.cmd as u8).is_empty() => Err(Error::new(ErrorKind::InvalidData, "Unknown command")),
Fixed { null: 0, cmd: '\n', hlength: 0, blength: 0, .. } => Ok(fixed),
Fixed { cmd: '\n', .. } => Err(Error::new(ErrorKind::InvalidData, "Invalid NOOP frame")),
Fixed { null: 0, .. } => Ok(fixed),
Fixed { .. } => Err(Error::new(ErrorKind::InvalidData, "Invalid NULL octet")),
}
}
/// Decodes a BOAWP protocol init string.
///
/// The init string is 4 octets (bytes) and must be exactly `"B0A\n"`.
pub fn decode_init(buffer: [u8; 4]) -> Result<Init, Error> {
let init = Init {
name: buffer[0] as char,
version: buffer[1] as char,
status: buffer[2] as char,
lf: buffer[3] as char,
};
if let Init { name: 'B', version: '0', status: 'A', lf: '\n', .. } = init {
Ok(init)
} else {
Err(Error::new(ErrorKind::InvalidData, "Invalid protocol init string"))
}
}
/// 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 mut buffer = [0; 4];
reader.read(&mut buffer)?;
let init = decode_init(buffer)?;
// 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)?;
// 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 {
Integer::Zero() => vec![],
Integer::One(i) => i.to_be_bytes().to_vec(),
Integer::Two(i) => i.to_be_bytes().to_vec(),
Integer::Four(i) => i.to_be_bytes().to_vec(),
Integer::Eight(i) => i.to_be_bytes().to_vec(),
Integer::Sixteen(i) => i.to_be_bytes().to_vec(),
Integer::BigNum(i) => i.to_vec(),
};
if let true = int.len() > 255 { return Err(Error::new(ErrorKind::InvalidData, "Invalid integer value length")) }
res.push(int.len() as u8);
res.append(&mut int);
Ok(res)
}
fn encode_header<'a>(z: &Headers) -> BufferVector<'a> {
let mut res: Vec<u8> = vec!['h' as u8];
let mut header = encode_headers(z)?;
if let true = header.len() > 255 { return Err(Error::new(ErrorKind::InvalidData, "Invalid header value length")) }
res.push(header.len() as u8);
res.append(&mut header);
Ok(res)
}
fn encode_binary<'a>(z: &Vec<u8>) -> BufferVector<'a> {
if let true = z.len() > 255 { return Err(Error::new(ErrorKind::InvalidData, "Invalid binary value length")) }
let mut res: Vec<u8> = vec!['b' as u8, z.len() as u8];
res.append(&mut z.to_vec());
Ok(res)
}
fn encode_string<'a>(z: &String) -> BufferVector<'a> {
if let true = z.len() > 255 { return Err(Error::new(ErrorKind::InvalidData, "Invalid string value length")) }
let mut res: Vec<u8> = vec!['s' as u8, z.len() as u8];
res.append(&mut z.as_bytes().to_vec());
Ok(res)
}
pub fn encode_headers<'a>(headers: &Headers) -> BufferVector<'a> {
let res: Vec<_> = headers.headers.iter()
.map(|(x,y)| {
let hlen: u8 = match x {
x if x.len() > 255 => return Err(Error::new(ErrorKind::InvalidData, "Invalid header name length")),
_ => x.len() as u8,
};
let hname = header_names_rev(x);
let mut header: Vec<u8> = if hname == 0 {
let mut z = x.as_bytes().to_vec();
z.insert(0, hlen);
z
} else {
vec![1, hname]
};
let mut value = match y {
Header::Null => vec!['n' as u8, 0],
Header::Boolean(true) => vec!['t' as u8, 0],
Header::Boolean(false) => vec!['f' as u8, 0],
Header::Integer(z) => encode_integer(z)?,
Header::Header(z) => encode_header(z)?,
Header::Binary(z) => encode_binary(z)?,
Header::String(z) => encode_string(z)?,
};
header.append(&mut value);
Ok(header)
})
.map(|x| {
x.unwrap()
}).into_iter().flatten().collect();
Ok(res)
}
pub fn encode_init<'a>(init: &str) -> BufferVector<'a> {
if let "B0A\n" = init {
Ok(vec!['B' as u8, '0' as u8, 'A' as u8, '\n' as u8])
} else {
Err(Error::new(ErrorKind::InvalidData, "Invalid protocol init string"))
}
}
pub fn encode<'a>(init_str: &str, command_char: char, headers_vec: Headers, body_vec: Body) -> BufferVector<'a> {
// protocol init
let mut init = encode_init(init_str)?;
// command
let mut command = match command_char {
x if commands(x as u8).is_empty() => return Err(Error::new(ErrorKind::InvalidData, "Unknown command")),
x if x == '\n' && (headers_vec.headers.len() != 0 || body_vec.body.len() != 0) => return Err(Error::new(ErrorKind::InvalidData, "Invalid NOOP frame")),
_ => vec![0, command_char as u8],
};
// headers
let mut headers = encode_headers(&headers_vec)?;
let hlength = headers.len() as u16;
let mut headers_length = hlength.to_be_bytes().to_vec();
// body
let mut body = body_vec.body;
let blength = body.len() as u32;
let mut body_length = blength.to_be_bytes().to_vec();
let mut res: Vec<u8> = Vec::with_capacity(init.len() + command.len() + 2 + 4 + headers.len() + body.len());
res.append(&mut init);
res.append(&mut command);
res.append(&mut headers_length);
res.append(&mut body_length);
res.append(&mut headers);
res.append(&mut body);
Ok(res)
}
// TESTS
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn _get_static_commands() {
assert!(commands(10).len() > 0);
assert!(commands(33).len() > 0);
assert!(commands(43).len() > 0);
}
#[test]
fn _get_static_header_names() {
assert!(header_names(32).len() > 0);
assert!(header_names(65).len() > 0);
}
fn _decode_init() {
let x: [u8; 4] = [66, 48, 65, 10];
let init = decode_init(x).unwrap();
assert_eq!(init.name, 'B');
assert_eq!(init.version, '0');
assert_eq!(init.status, 'A');
assert_eq!(init.lf, '\n');
}
#[test]
fn _decode_init_error1() {
let x: [u8; 4] = [65, 48, 65, 10];
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 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 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 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 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 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 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 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 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 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 _get_vec() {
let mut x = vec![1, 2, 3, 4];
let value = Header::get_vec(&mut x, 4);
assert_eq!(value, [1, 2, 3, 4]);
assert_eq!(x, []);
}
#[test]
fn _get_string() {
let mut x = vec![66, 79, 65, 87, 80];
let value = Header::get_string(&mut x, 5).unwrap();
assert_eq!(value, "BOAWP");
assert_eq!(x, []);
}
#[test]
fn _get_string_error() {
let mut x = vec![255, 255];
let value = Header::get_string(&mut x, 2);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid UTF-8 string");
}
#[test]
fn _get_integer0() {
let mut x = vec![];
let value = Header::get_integer(&mut x, 0).unwrap();
assert_eq!(value, Integer::Zero());
assert_eq!(x, []);
}
#[test]
fn _get_integer1() {
let mut x = vec![127];
let value = Header::get_integer(&mut x, 1).unwrap();
assert_eq!(value, Integer::One(127));
assert_eq!(x, []);
}
#[test]
fn _get_integer2() {
let mut x = vec![127, 127];
let value = Header::get_integer(&mut x, 2).unwrap();
assert_eq!(value, Integer::Two(32639));
assert_eq!(x, []);
}
#[test]
fn _get_integer4() {
let mut x = vec![127, 127, 127, 127];
let value = Header::get_integer(&mut x, 4).unwrap();
assert_eq!(value, Integer::Four(2139062143));
assert_eq!(x, []);
}
#[test]
fn _get_integer8() {
let mut x = vec![127, 127, 127, 127, 127, 127, 127, 127];
let value = Header::get_integer(&mut x, 8).unwrap();
assert_eq!(value, Integer::Eight(9187201950435737471));
assert_eq!(x, []);
}
#[test]
fn _get_integer16() {
let mut x = vec![127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127];
let value = Header::get_integer(&mut x, 16).unwrap();
assert_eq!(value, Integer::Sixteen(169473963133173273960190490760135540607));
assert_eq!(x, []);
}
#[test]
fn _get_integer_bignum() {
let mut x = vec![127, 127, 127, 127, 127, 127, 127, 127, 127, 127];
let value = Header::get_integer(&mut x, 10).unwrap();
assert_eq!(value, Integer::BigNum(vec![127, 127, 127, 127, 127, 127, 127, 127, 127, 127]));
assert_eq!(x, []);
}
#[test]
fn _decode_headers() {
let mut x = vec![1, 65, 115, 4, 72, 84, 84, 80, 1, 66, 105, 8, 255, 255, 255, 255, 255, 255, 127, 255, 1, 67, 110, 0, 1, 68, 116, 0, 1, 69, 102, 0, 1, 70, 115, 4, 97, 98, 99, 100, 9, 114, 101, 99, 117, 114, 115, 105, 118, 101, 104, 16, 1, 72, 115, 4, 101, 102, 103, 104, 1, 73, 115, 4, 116, 101, 115, 116, 4, 116, 101, 115, 116, 115, 0, 9, 114, 101, 99, 117, 114, 115, 105, 118, 101, 104, 16, 5, 104, 101, 108, 108, 111, 110, 0, 5, 119, 111, 114, 108, 100, 110, 0, 9, 109, 121, 45, 99, 117, 115, 116, 111, 109, 115, 4, 116, 101, 115, 116, 4, 97, 108, 101, 120, 110, 0, 11, 98, 105, 110, 97, 114, 121, 45, 116, 101, 120, 116, 98, 4, 115, 114, 113, 112];
let value = decode_headers(&mut x).unwrap();
assert_eq!(value[0], ("protocol".to_string(), Header::String("HTTP".to_string())));
assert_eq!(value[1], ("max-headers".to_string(), Header::Integer(Integer::Eight(-32769))));
assert_eq!(value[2], ("max-body".to_string(), Header::Null));
assert_eq!(value[3], ("max-value".to_string(), Header::Boolean(true)));
assert_eq!(value[4], ("max-int".to_string(), Header::Boolean(false)));
assert_eq!(value[5], ("null".to_string(), Header::String("abcd".to_string())));
let recurs1 = Headers { headers: vec![("false".to_string(), Header::String("efgh".to_string())), ("accept-version".to_string(), Header::String("test".to_string()))] };
assert_eq!(value[6], ("recursive".to_string(), Header::Header(recurs1)));
assert_eq!(value[7], ("test".to_string(), Header::String("".to_string())));
let recurs2 = Headers { headers: vec![("hello".to_string(), Header::Null), ("world".to_string(), Header::Null)] };
assert_eq!(value[8], ("recursive".to_string(), Header::Header(recurs2)));
assert_eq!(value[9], ("my-custom".to_string(), Header::String("test".to_string())));
assert_eq!(value[10], ("alex".to_string(), Header::Null));
assert_eq!(value[11], ("binary-text".to_string(), Header::Binary(vec![115, 114, 113, 112])));
}
#[test]
fn _decode_headers_error1() {
let mut x = vec![1];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid headers length '1'");
}
#[test]
fn _decode_headers_error2() {
let mut x = vec![1, 2];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid headers length '2'");
}
#[test]
fn _decode_headers_error3() {
let mut x = vec![1, 2, 3];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid headers length '3'");
}
#[test]
fn _decode_headers_error4() {
let mut x = vec![0, 65, 65, 0];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header name length");
}
#[test]
fn _decode_headers_error5() {
let mut x = vec![1, 0, 0, 0];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Unknown header name value");
}
#[test]
fn _decode_headers_error6() {
let mut x = vec![2, 255, 255, 0, 0];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header name ASCII encoding");
}
#[test]
fn _decode_headers_error6b() {
let mut x = vec![2, 0, 32, 0, 0];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header name ASCII encoding");
}
#[test]
fn _decode_headers_error7() {
let mut x = vec![1, 65, 110, 1, 22];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header value length 1 for type n");
}
#[test]
fn _decode_headers_error8() {
let mut x = vec![1, 65, 116, 1, 22];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header value length 1 for type t");
}
#[test]
fn _decode_headers_error9() {
let mut x = vec![1, 65, 102, 1, 22];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header value length 1 for type f");
}
#[test]
fn _decode_headers_error10() {
let mut x = vec![1, 65, 0, 0];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Unknown header value type");
}
#[test]
fn _decode_headers_error11() {
let mut x = vec![5, 65, 104, 3];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header name length");
}
#[test]
fn _decode_headers_error12() {
let mut x = vec![2, 97, 98, 98];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header name value '1'");
}
#[test]
fn _decode_headers_error13() {
let mut x = vec![3, 97, 98, 98];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header name value '0'");
}
#[test]
fn _decode_headers_error14() {
let mut x = vec![3, 97, 98, 98, 104, 5];
let value = decode_headers(&mut x);
assert!(value.is_err());
assert_eq!(value.unwrap_err().into_inner().unwrap().to_string(), "Invalid header value length");
}
}