extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate zlo;
use serde::Deserializer;
use serde::Serializer;
use zlo::Infinite;
use zlo::serialize;
use std::fmt;
#[derive(Serialize, Deserialize)]
pub struct TinyUserInput {
view_angles: [f32; 3],
#[serde(serialize_with = "serialize_axis", deserialize_with = "deserialize_axis")]
stick_0: [f32; 2],
#[serde(serialize_with = "serialize_axis", deserialize_with = "deserialize_axis")]
stick_1: [f32; 2],
}
#[derive(Serialize, Deserialize)]
pub struct NotTinyUserInput {
view_angles: [f32; 3],
stick_0: [f32; 2],
stick_1: [f32; 2],
}
fn f32_to_i8(x: f32) -> i8 {
use std::i8::{MIN, MAX};
assert!(x >= -1.0 && x <= 1.0, "x out of bounds");
(x * (if x < 0.0 { MIN } else { MAX }) as f32) as i8
}
fn i8_to_f32(x: i8) -> f32 {
use std::i8::{MIN, MAX};
x as f32 * if x < 0 { 1.0 / MIN as f32 } else { 1.0 / MAX as f32 }
}
fn serialize_axis<S>(axis: &[f32; 2], serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
use serde::ser::SerializeSeq;
let mut seq = serializer.serialize_seq(Some(2))?;
seq.serialize_element(&f32_to_i8(axis[0]))?;
seq.serialize_element(&f32_to_i8(axis[1]))?;
seq.end()
}
fn deserialize_axis<'de, D>(deserializer: D) -> Result<[f32; 2], D::Error>
where D: Deserializer<'de>
{
use serde::de::Visitor;
use serde::de::SeqAccess;
use serde::de::Error;
struct AxisVisitor;
impl<'de> Visitor<'de> for AxisVisitor {
type Value = [f32; 2];
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an array of two ints")
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: SeqAccess<'de>
{
let a: i8 = visitor.next_element()?.ok_or(V::Error::invalid_length(0, &"2"))?;
let b: i8 = visitor.next_element()?.ok_or(V::Error::invalid_length(1, &"2"))?;
Ok([i8_to_f32(a), i8_to_f32(b)])
}
}
deserializer.deserialize_seq(AxisVisitor)
}
fn main() {
let view_angles = [0.0; 3];
let stick_0 = [1.0, 0.3];
let stick_1 = [0.0, 0.9];
let tiny = TinyUserInput { view_angles, stick_0, stick_1 };
let not_tiny = NotTinyUserInput { view_angles, stick_0, stick_1 };
let a = serialize(&tiny, Infinite).unwrap();
let b = serialize(¬_tiny, Infinite).unwrap();
assert_eq!(a.len(), 8);
assert_eq!(b.len(), 13);
}