#![cfg(feature = "experimental-write")]
extern crate fixcol;
use std::io::{Error as IoError, ErrorKind, Write};
use fixcol::error::Error;
use fixcol::{WriteFixed, WriteFixedAll};
struct FakeBuffer {
max_size: usize,
data_size: usize,
data: Vec<u8>,
}
impl FakeBuffer {
pub fn new(size: usize) -> Self {
Self {
max_size: size,
data_size: 0,
data: Vec::new(),
}
}
pub fn as_slice(&self) -> &[u8] {
&self.data.as_slice()
}
pub fn as_string(&self) -> Option<String> {
std::str::from_utf8(&self.as_slice())
.ok()
.map(|x| x.to_string())
}
}
impl Write for FakeBuffer {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
if self.data_size + buf.len() <= self.max_size {
let written = self.data.write(buf).unwrap();
self.data_size += written;
Ok(written)
} else {
let err = IoError::new(ErrorKind::WriteZero, "Out of space");
Err(err)
}
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
const EXPECTED_STRUCT_TEXT: &'static str = r#"91 115
221159
92 0
151171
"#;
#[derive(Debug, Eq, PartialEq, WriteFixed)]
struct Point {
#[fixcol(width = 3)]
x: u8,
#[fixcol(width = 3)]
y: u8,
}
impl Point {
pub fn new(x: u8, y: u8) -> Self {
Self { x, y }
}
pub fn sample() -> Vec<Self> {
vec![
Point::new(91, 115),
Point::new(221, 159),
Point::new(92, 0),
Point::new(151, 171),
]
}
}
#[test]
fn struct_normal_buffer_control() {
let points = Point::sample();
let mut buf: Vec<u8> = Vec::new();
let res = points.write_fixed_all(&mut buf);
let text = std::str::from_utf8(buf.as_slice()).unwrap().to_string();
assert!(res.is_ok());
assert_eq!(text, EXPECTED_STRUCT_TEXT);
}
#[test]
fn struct_adequate_size_control() {
let points = Point::sample();
let mut buf = FakeBuffer::new(50);
let res = points.write_fixed_all(&mut buf);
let text = buf.as_string().unwrap();
assert!(res.is_ok());
assert_eq!(text, EXPECTED_STRUCT_TEXT);
}
#[test]
fn struct_out_of_space_test() {
let points = Point::sample();
let mut buf = FakeBuffer::new(20);
let res = points.write_fixed_all(&mut buf);
assert!(res.is_err());
match res.unwrap_err() {
Error::DataError(_) => panic!("Should have had I/O Error"),
Error::IoError(e) => {
assert_eq!(e.to_string(), "Out of space");
assert_eq!(e.kind(), ErrorKind::WriteZero);
}
}
}
#[derive(Debug, Eq, PartialEq, WriteFixed)]
#[fixcol(key_width = 1)]
enum Datum {
#[fixcol(key = "S")]
Scalar(#[fixcol(width = 10, align = "right")] u16),
#[fixcol(key = "P")]
Pair {
#[fixcol(width = 5)]
x: u16,
#[fixcol(width = 5)]
y: u16,
},
#[fixcol(key = "U")]
Unit,
}
impl Datum {
pub fn sample() -> Vec<Self> {
vec![
Datum::Pair { x: 53542, y: 72 },
Datum::Unit,
Datum::Unit,
Datum::Scalar(1234),
]
}
}
const EXPECTED_ENUM_TEXT: &'static str = r#"P5354272
U
U
S 1234
"#;
#[test]
fn enum_normal_buffer_control() {
let data = Datum::sample();
let mut buf: Vec<u8> = Vec::new();
let res = data.write_fixed_all(&mut buf);
let text = std::str::from_utf8(buf.as_slice()).unwrap().to_string();
assert!(res.is_ok());
assert_eq!(text, EXPECTED_ENUM_TEXT);
}
#[test]
fn enum_adequate_size_control() {
let data = Datum::sample();
let mut buf = FakeBuffer::new(50);
let res = data.write_fixed_all(&mut buf);
let text = buf.as_string().unwrap();
assert!(res.is_ok());
assert_eq!(text, EXPECTED_ENUM_TEXT);
}
#[test]
fn out_of_space_in_struct_variant() {
let data = Datum::sample();
let mut buf = FakeBuffer::new(7);
let res = data.write_fixed_all(&mut buf);
assert!(res.is_err());
match res.unwrap_err() {
Error::DataError(_) => panic!("Should have had I/O Error"),
Error::IoError(e) => {
assert_eq!(e.to_string(), "Out of space");
assert_eq!(e.kind(), ErrorKind::WriteZero);
}
}
let expected = "P53542";
assert_eq!(buf.as_string().unwrap(), expected);
}
#[test]
fn out_of_space_in_tuple_variant() {
let data = Datum::sample();
let mut buf = FakeBuffer::new(15);
let res = data.write_fixed_all(&mut buf);
assert!(res.is_err());
match res.unwrap_err() {
Error::DataError(_) => panic!("Should have had I/O Error"),
Error::IoError(e) => {
assert_eq!(e.to_string(), "Out of space");
assert_eq!(e.kind(), ErrorKind::WriteZero);
}
}
let expected = "P5354272 \nU\nU";
assert_eq!(buf.as_string().unwrap(), expected);
}
#[test]
fn out_of_space_in_unit_variant() {
let data = Datum::sample();
let mut buf = FakeBuffer::new(14);
let res = data.write_fixed_all(&mut buf);
assert!(res.is_err());
match res.unwrap_err() {
Error::DataError(_) => panic!("Should have had I/O Error"),
Error::IoError(e) => {
assert_eq!(e.to_string(), "Out of space");
assert_eq!(e.kind(), ErrorKind::WriteZero);
}
}
let expected = "P5354272 \nU\n";
assert_eq!(buf.as_string().unwrap(), expected);
}