serializer.rs

2.3 kB · rust · 65 lines

1use super::Cell2d;2use crate::core::errors::{value_error, Result};3use crate::core::json;4use crate::core::tensor::Tensor;5use crate::math::dim::serializer::{6    byte_grid, color_grid, count_grid, parse, tag_layer, types_field,7};89/// Returns the cell's types as rows of bytes.10fn to_lists(cell: &Cell2d) -> Vec<Vec<u8>> {11    let (h, w) = (cell.height(), cell.width());12    (0..h)13        .map(|y| (0..w).map(|x| cell.types().get(&[y, x])).collect())14        .collect()15}1617/// Builds a cell from rows of bytes, or an error when the rows are empty or ragged.18fn from_lists(lists: &[Vec<u8>]) -> Result<Cell2d> {19    if lists.is_empty() {20        return value_error("cannot build a cell from an empty list.");21    }22    let (h, w) = (lists.len(), lists[0].len());23    if lists.iter().any(|row| row.len() != w) {24        return value_error("all rows must have the same length.");25    }26    let data: Vec<u8> = lists.iter().flatten().copied().collect();27    Ok(Cell2d::new(Tensor::of(data, vec![h, w])))28}2930/// Serializes the cell to a JSON string of its types, with colors and tags when present.31pub fn to_json(cell: &Cell2d) -> String {32    let mut data = json!({33        "v": 1,34        "width": cell.width(),35        "height": cell.height(),36        "types": to_lists(cell),37    });38    if let Some(colors) = &cell.cell.colors {39        data["colors"] = json!(colors.chunks(cell.width()).collect::<Vec<_>>());40    }41    if let Some(tags) = &cell.cell.tags {42        let (h, w) = (cell.height(), cell.width());43        let nested: Vec<Vec<i64>> = (0..h)44            .map(|r| (0..w).map(|c| tags.at(r * w + c)).collect())45            .collect();46        data["tags"] = json!(nested);47    }48    data.to_string()49}5051/// Restores a cell from its JSON string, colors and tags included, or a parse error.52pub fn from_json(text: &str) -> Result<Cell2d> {53    let data = parse(text)?;54    let lists = byte_grid(types_field(&data)?)?;55    let mut cell = from_lists(&lists)?;56    if let Some(colors) = data.get("colors") {57        let nested = color_grid(colors)?;58        cell.cell.colors = Some(nested.into_iter().flatten().collect());59    }60    if let Some(tags) = data.get("tags") {61        let shape = vec![cell.height(), cell.width()];62        cell.cell.tags = Some(tag_layer(&count_grid(tags)?, shape)?);63    }64    Ok(cell)65}