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}