Skip to content

Instantly share code, notes, and snippets.

@Porges
Last active August 22, 2020 22:17
Show Gist options
  • Save Porges/d8761073eb7b7eb98e3448b7a6cc551f to your computer and use it in GitHub Desktop.
Save Porges/d8761073eb7b7eb98e3448b7a6cc551f to your computer and use it in GitHub Desktop.
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedGrid<T, const M: usize, const N: usize> {
cells: [[Option<T>; N]; M],
}
impl<'de, T: Deserialize<'de> + Copy, const M: usize, const N: usize> Deserialize<'de>
for FixedGrid<T, M, N>
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let vec = <Vec<Option<T>> as serde::Deserialize>::deserialize(deserializer)?;
if vec.len() != N * M {
let expected = format!("{}", N * M);
Err(serde::de::Error::invalid_length(
vec.len(),
&expected.as_str(),
))
} else {
let mut cells = [[None; N]; M];
for i in 0..M {
for j in 0..N {
cells[i][j] = vec[i * N + j]
}
}
Ok(FixedGrid { cells })
}
}
}
impl<T: Serialize + Clone, const M: usize, const N: usize> Serialize for FixedGrid<T, M, N> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut vec = Vec::new();
vec.reserve(N*M);
for i in 0..M {
for j in 0..N {
vec.push(&self.cells[i][j])
}
}
vec.serialize(serializer)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn can_roundtrip_fixedgrid() {
let fixed = FixedGrid {
cells: [
[Some("a"), Some("b"), Some("c")],
[None, Some("e"), Some("f")],
],
};
let result = serde_json::to_string(&fixed).unwrap();
assert_eq!(result, r#"["a","b","c",null,"e","f"]"#);
let parsed: FixedGrid<&str, 2, 3> = serde_json::from_str(&result).unwrap();
assert_eq!(parsed, fixed);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment