use crate::error::Result;
use crate::language::{Bytes, Insn, Map, Value};
use Insn::*;
use Value::*;
pub trait WriteInsn {
fn write(&mut self, insn: Insn) -> Result<()>;
fn write_all(&mut self, insns: &[Insn]) -> Result<()> {
for i in insns {
self.write(*i)?;
}
Ok(())
}
}
impl<'a> WriteInsn for &'a mut Vec<Insn> {
fn write(&mut self, insn: Insn) -> Result<()> {
self.push(insn);
Ok(())
}
}
pub struct Serializer<W> {
writer: W,
}
impl<W> Serializer<W> {
pub fn new(writer: W) -> Self {
Serializer { writer }
}
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W: WriteInsn> WriteInsn for Serializer<W> {
fn write(&mut self, insn: Insn) -> Result<()> {
self.writer.write(insn)
}
}
impl<W: WriteInsn> Serializer<W> {
pub fn serialize(&mut self, v: &Value) -> Result<()> {
match *v {
Int(n) => self.serialize_int(n),
Uint(n) => self.serialize_uint(n),
Float(f) => self.serialize_float(f),
String(ref s) => self.serialize_string(s),
Object(ref map) => self.serialize_object(map),
Array(ref arr) => self.serialize_array(arr),
Bool(b) => self.serialize_bool(b),
Nil => self.serialize_nil(),
}
}
fn serialize_int(&mut self, n: i64) -> Result<()> {
let mut n = n as u64;
self.write(Inew)?;
let mut shift: usize = 0;
while n != 0 {
if n % 2 == 1 {
self.write_all(&[Inew, Iinc])?;
for _ in 1..=shift {
self.write(Ishl)?;
}
self.write(Iadd)?;
}
n >>= 1;
shift += 1;
}
Ok(())
}
fn serialize_uint(&mut self, n: u64) -> Result<()> {
self.serialize_int(n as i64)?;
self.write(Itou)
}
fn serialize_float(&mut self, f: f64) -> Result<()> {
if f.is_nan() {
self.write(Fnan)
} else if f.is_infinite() {
self.write(Finf)?;
if f.is_sign_negative() {
self.write(Fneg)?;
}
Ok(())
} else {
self.serialize_int(f.to_bits() as i64)?;
self.write(Itof)
}
}
fn serialize_string(&mut self, s: &Bytes) -> Result<()> {
self.write(Snew)?;
for c in s {
self.serialize_int(*c as i64)?;
self.write(Sadd)?;
}
Ok(())
}
fn serialize_object(&mut self, map: &Map) -> Result<()> {
self.write(Onew)?;
for (k, v) in map {
self.serialize_string(k)?;
self.serialize(v)?;
self.write(Oadd)?;
}
Ok(())
}
fn serialize_array(&mut self, arr: &Vec<Value>) -> Result<()> {
self.write(Anew)?;
for i in arr {
self.serialize(i)?;
self.write(Aadd)?;
}
Ok(())
}
fn serialize_bool(&mut self, b: bool) -> Result<()> {
self.write(Bnew)?;
if b {
self.write(Bneg)?;
}
Ok(())
}
fn serialize_nil(&mut self) -> Result<()> {
self.write(Nnew)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::vm;
use crate::{array, object};
#[test]
fn serializer_int() {
assert_eq!(to_insn_vec(&Int(0)), vec![Inew]);
assert_eq!(to_insn_vec(&Int(1)), vec![Inew, Inew, Iinc, Iadd]);
assert_eq!(to_insn_vec(&Int(2)), vec![Inew, Inew, Iinc, Ishl, Iadd]);
assert_eq!(
to_insn_vec(&Int(3)),
vec![Inew, Inew, Iinc, Iadd, Inew, Iinc, Ishl, Iadd]
);
assert_eq!(
to_insn_vec(&Int(0b1010101)),
vec![
Inew, Inew, Iinc, Iadd, Inew, Iinc, Ishl, Ishl, Iadd, Inew, Iinc, Ishl, Ishl, Ishl, Ishl, Iadd, Inew, Iinc, Ishl, Ishl, Ishl, Ishl, Ishl, Ishl, Iadd, ]
);
assert_identical(Int(1234567890));
assert_identical(Int(-1234567890));
}
#[test]
fn serializer_uint() {
assert_identical(Uint(0));
assert_identical(Uint(1));
assert_identical(Uint(5));
assert_identical(Uint(0xffff_ffff_ffff_ffff));
}
#[test]
fn serializer_float() {
assert_eq!(to_insn_vec(&Float(f64::NAN)), vec![Fnan]);
assert_eq!(to_insn_vec(&Float(f64::INFINITY)), vec![Finf]);
assert_eq!(to_insn_vec(&Float(f64::NEG_INFINITY)), vec![Finf, Fneg]);
assert_identical(Float(0.0));
assert_identical(Float(1.0));
assert_identical(Float(123.45e-67));
assert_identical(Float(8.9102e34));
}
#[test]
fn serializer_string() {
assert_identical(String(Vec::new()));
assert_identical(String(b"a".to_vec()));
assert_identical(String(b"ab".to_vec()));
assert_identical(String(
b"qawsedrftgyhujikolp;zasxdcfvgbhnjmk,l.;qaswderftgyhujikolp;".to_vec(),
));
}
#[test]
fn serializer_object() {
assert_identical(object![]);
assert_identical(object![key: Int(123)]);
assert_identical(object![key: Int(123), another_key: Float(1.23)]);
assert_identical(object![
key: Int(123),
another_key: Float(1.23),
nested_object: object![nested_key: String(b"value".to_vec())],
]);
}
#[test]
fn serializer_array() {
assert_identical(array![]);
assert_identical(array![Int(1)]);
assert_identical(array![Int(1), String(b"2".to_vec())]);
assert_identical(array![
Int(1),
String(b"2".to_vec()),
array![Uint(3), String(b"nested".to_vec())],
]);
}
#[test]
fn serializer_bool() {
assert_identical(Bool(false));
assert_identical(Bool(true));
}
#[test]
fn serializer_nil() {
assert_identical(Nil);
}
fn to_insn_vec(value: &Value) -> Vec<Insn> {
let mut insns = Vec::new();
Serializer::new(&mut insns).serialize(&value).unwrap();
insns
}
fn assert_identical(value: Value) {
let mut vm = vm::VM::new();
vm.execute_all(vm::SliceTokenReader::new(&to_insn_vec(&value)))
.expect("execution error");
let result = vm.peek_top().expect("stack is empty");
assert_eq!(&value, result);
}
}