mod ty;
pub use self::ty::write_type;
use std::io::{self, Write};
use byteorder::{LittleEndian, WriteBytesExt};
use crate::lazy::record::value::{Array, Float, Int16, Int32, Int8, Type, Value};
pub fn write_value<W>(writer: &mut W, value: Option<Value>) -> io::Result<()>
where
W: Write,
{
match value {
None => write_missing(writer),
Some(Value::Int8(v)) => write_int8(writer, v),
Some(Value::Array(Array::Int8(v))) => write_int8_array(writer, &v),
Some(Value::Int16(v)) => write_int16(writer, v),
Some(Value::Array(Array::Int16(v))) => write_int16_array(writer, &v),
Some(Value::Int32(v)) => write_int32(writer, v),
Some(Value::Array(Array::Int32(v))) => write_int32_array(writer, &v),
Some(Value::Float(v)) => write_float(writer, v),
Some(Value::Array(Array::Float(v))) => write_float_array(writer, &v),
Some(Value::String(v)) => write_string(writer, v),
}
}
fn write_missing<W>(writer: &mut W) -> io::Result<()>
where
W: Write,
{
write_type(writer, None)
}
fn write_int8<W>(writer: &mut W, value: Option<Int8>) -> io::Result<()>
where
W: Write,
{
match value {
None => {
write_type(writer, Some(Type::Int8(0)))?;
}
Some(v) => {
write_type(writer, Some(Type::Int8(1)))?;
writer.write_i8(i8::from(v))?;
}
}
Ok(())
}
fn write_int8_array<W>(writer: &mut W, values: &[i8]) -> io::Result<()>
where
W: Write,
{
write_type(writer, Some(Type::Int8(values.len())))?;
for &value in values {
writer.write_i8(value)?;
}
Ok(())
}
fn write_int16<W>(writer: &mut W, value: Option<Int16>) -> io::Result<()>
where
W: Write,
{
match value {
None => {
write_type(writer, Some(Type::Int16(0)))?;
}
Some(v) => {
write_type(writer, Some(Type::Int16(1)))?;
writer.write_i16::<LittleEndian>(i16::from(v))?;
}
}
Ok(())
}
fn write_int16_array<W>(writer: &mut W, values: &[i16]) -> io::Result<()>
where
W: Write,
{
write_type(writer, Some(Type::Int16(values.len())))?;
for &value in values {
writer.write_i16::<LittleEndian>(value)?;
}
Ok(())
}
fn write_int32<W>(writer: &mut W, value: Option<Int32>) -> io::Result<()>
where
W: Write,
{
match value {
None => {
write_type(writer, Some(Type::Int32(0)))?;
}
Some(v) => {
write_type(writer, Some(Type::Int32(1)))?;
writer.write_i32::<LittleEndian>(i32::from(v))?;
}
}
Ok(())
}
fn write_int32_array<W>(writer: &mut W, values: &[i32]) -> io::Result<()>
where
W: Write,
{
write_type(writer, Some(Type::Int32(values.len())))?;
for &value in values {
writer.write_i32::<LittleEndian>(value)?;
}
Ok(())
}
fn write_float<W>(writer: &mut W, value: Option<Float>) -> io::Result<()>
where
W: Write,
{
match value {
None => {
write_type(writer, Some(Type::Float(0)))?;
}
Some(v) => {
write_type(writer, Some(Type::Float(1)))?;
writer.write_f32::<LittleEndian>(f32::from(v))?;
}
}
Ok(())
}
fn write_float_array<W>(writer: &mut W, values: &[f32]) -> io::Result<()>
where
W: Write,
{
write_type(writer, Some(Type::Float(values.len())))?;
for &value in values {
writer.write_f32::<LittleEndian>(value)?;
}
Ok(())
}
fn write_string<W>(writer: &mut W, value: Option<String>) -> io::Result<()>
where
W: Write,
{
match value {
None => {
write_type(writer, Some(Type::String(0)))?;
}
Some(s) => {
write_type(writer, Some(Type::String(s.len())))?;
writer.write_all(s.as_bytes())?;
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_write_value() -> io::Result<()> {
let mut buf = Vec::new();
write_value(&mut buf, None)?;
assert_eq!(buf, [0x00]);
buf.clear();
write_value(&mut buf, Some(Value::Int8(None)))?;
assert_eq!(buf, [0x01]);
buf.clear();
write_value(&mut buf, Some(Value::Int8(Some(Int8::Value(5)))))?;
assert_eq!(buf, [0x11, 0x05]);
buf.clear();
write_value(&mut buf, Some(Value::Array(Array::Int8(vec![5, 8, 13]))))?;
assert_eq!(buf, [0x31, 0x05, 0x08, 0x0d]);
buf.clear();
write_value(&mut buf, Some(Value::Int16(None)))?;
assert_eq!(buf, [0x02]);
buf.clear();
write_value(&mut buf, Some(Value::Int16(Some(Int16::Value(377)))))?;
assert_eq!(buf, [0x12, 0x79, 0x01]);
buf.clear();
write_value(
&mut buf,
Some(Value::Array(Array::Int16(vec![377, 610, 987]))),
)?;
assert_eq!(buf, [0x32, 0x79, 0x01, 0x62, 0x02, 0xdb, 0x03]);
buf.clear();
write_value(&mut buf, Some(Value::Int32(None)))?;
assert_eq!(buf, [0x03]);
buf.clear();
write_value(&mut buf, Some(Value::Int32(Some(Int32::Value(75025)))))?;
assert_eq!(buf, [0x13, 0x11, 0x25, 0x01, 0x00]);
buf.clear();
write_value(
&mut buf,
Some(Value::Array(Array::Int32(vec![75025, 121393, 196418]))),
)?;
assert_eq!(
buf,
[0x33, 0x11, 0x25, 0x01, 0x00, 0x31, 0xda, 0x01, 0x00, 0x42, 0xff, 0x02, 0x00]
);
buf.clear();
write_value(&mut buf, Some(Value::Float(Some(Float::Value(0.0)))))?;
assert_eq!(buf, [0x15, 0x00, 0x00, 0x00, 0x00]);
buf.clear();
write_value(&mut buf, Some(Value::Array(Array::Float(vec![0.0, 0.5]))))?;
assert_eq!(buf, [0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f]);
buf.clear();
write_value(&mut buf, Some(Value::String(None)))?;
assert_eq!(buf, [0x07]);
buf.clear();
write_value(&mut buf, Some(Value::String(Some(String::from("n")))))?;
assert_eq!(buf, [0x17, 0x6e]);
buf.clear();
write_value(&mut buf, Some(Value::String(Some(String::from("ndls")))))?;
assert_eq!(buf, [0x47, 0x6e, 0x64, 0x6c, 0x73]);
Ok(())
}
}