Skip to content

Commit

Permalink
feat: add 3d points to serde
Browse files Browse the repository at this point in the history
  • Loading branch information
kade-robertson committed Oct 15, 2023
1 parent b5a5533 commit b03f1d3
Showing 1 changed file with 141 additions and 22 deletions.
163 changes: 141 additions & 22 deletions src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,36 +78,155 @@ impl<'de, T: ExtendedNumOps + Deserialize<'de>> Deserialize<'de> for Point<2, T>
}
}

struct Point3DVisitor<T>(PhantomData<T>);

impl<'de, T: ExtendedNumOps + Deserialize<'de>> Visitor<'de> for Point3DVisitor<T> {
type Value = Point<3, T>;

fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "a 3-dimensional point")
}

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut x_value: Option<T> = None;
let mut y_value: Option<T> = None;
let mut z_value: Option<T> = None;

loop {
if let Ok(maybe_entry) = map.next_entry::<String, T>() {
if let Some((key, value)) = maybe_entry {
match key.as_str() {
"x" => x_value = Some(value),
"y" => y_value = Some(value),
"z" => z_value = Some(value),
_ => {}
}
} else {
break;
}
}
}

match (x_value, y_value, z_value) {
(Some(x), Some(y), Some(z)) => Ok(Point { vec: [x, y, z] }),
(None, Some(_), Some(_)) => Err(de::Error::missing_field("x")),
(Some(_), None, Some(_)) => Err(de::Error::missing_field("y")),
(Some(_), Some(_), None) => Err(de::Error::missing_field("z")),
(None, None, Some(_)) => Err(de::Error::missing_field("x AND y")),
(None, Some(_), None) => Err(de::Error::missing_field("x AND z")),
(Some(_), None, None) => Err(de::Error::missing_field("y AND z")),
_ => Err(de::Error::missing_field("x AND y AND z")),
}
}
}

impl<'de, T: ExtendedNumOps + Deserialize<'de>> Deserialize<'de> for Point<3, T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(Point3DVisitor(PhantomData))
}
}

#[cfg(test)]
mod tests {
use crate::Point;
use serde_json::{from_value, json};

#[test]
fn err_map_no_x_or_y() {
let json_data = json!({ "other": "properties", "even_nums": 9 });
let point = from_value::<Point<2, f64>>(json_data);
assert!(point.is_err());
}
mod point2d {
use super::*;

#[test]
fn err_map_no_x() {
let json_data = json!({ "other": "properties", "even_nums": 9, "y": 5 });
let point = from_value::<Point<2, f64>>(json_data);
assert!(point.is_err());
}
#[test]
fn err_map_no_x_or_y() {
let json_data = json!({ "other": "properties", "even_nums": 9 });
let point = from_value::<Point<2, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn err_map_no_x() {
let json_data = json!({ "other": "properties", "even_nums": 9, "y": 5 });
let point = from_value::<Point<2, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn err_map_no_y() {
let json_data = json!({ "other": "properties", "even_nums": 9, "x": 5 });
let point = from_value::<Point<2, f64>>(json_data);
assert!(point.is_err());
#[test]
fn err_map_no_y() {
let json_data = json!({ "other": "properties", "even_nums": 9, "x": 5 });
let point = from_value::<Point<2, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn ok_x_and_y() {
let json_data = json!({ "other": "properties", "even_nums": 9, "x": 5, "y": 5 });
let point = from_value::<Point<2, f64>>(json_data);
assert!(point.is_ok());
}
}

#[test]
fn ok_x_and_y() {
let json_data = json!({ "other": "properties", "even_nums": 9, "x": 5, "y": 5 });
let point = from_value::<Point<2, f64>>(json_data);
assert!(point.is_ok());
mod point3d {
use super::*;

#[test]
fn err_map_no_x_or_y_or_z() {
let json_data = json!({ "other": "properties", "even_nums": 9 });
let point = from_value::<Point<3, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn err_map_no_x_or_y() {
let json_data = json!({ "other": "properties", "even_nums": 9, "z": 5 });
let point = from_value::<Point<3, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn err_map_no_x_or_z() {
let json_data = json!({ "other": "properties", "even_nums": 9, "y": 5 });
let point = from_value::<Point<3, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn err_map_no_y_or_z() {
let json_data = json!({ "other": "properties", "even_nums": 9, "x": 5 });
let point = from_value::<Point<3, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn err_map_no_x() {
let json_data = json!({ "other": "properties", "even_nums": 9, "y": 5, "z": 5 });
let point = from_value::<Point<3, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn err_map_no_y() {
let json_data = json!({ "other": "properties", "even_nums": 9, "x": 5, "z": 5 });
let point = from_value::<Point<3, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn err_map_no_z() {
let json_data = json!({ "other": "properties", "even_nums": 9, "x": 5, "y": 5 });
let point = from_value::<Point<3, f64>>(json_data);
assert!(point.is_err());
}

#[test]
fn ok_x_and_y_and_z() {
let json_data =
json!({ "other": "properties", "even_nums": 9, "x": 5, "y": 5, "z": 5 });
let point = from_value::<Point<3, f64>>(json_data);
assert!(point.is_ok());
}
}
}

0 comments on commit b03f1d3

Please sign in to comment.