promkit-widgets 0.7.0

Widgets for promkit
Documentation
use std::{fmt, io::Read};

use serde::{
    Deserialize,
    de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor},
};

use super::jsonz::{ContainerNode, ContainerType, JsonNode, Row};

struct ParsedRows(Vec<Row>);

impl<'de> Deserialize<'de> for ParsedRows {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let mut rows = Vec::new();
        RowsSeed {
            rows: &mut rows,
            depth: 0,
            key: None,
        }
        .deserialize(deserializer)?;
        Ok(Self(rows))
    }
}

struct RowsSeed<'a> {
    rows: &'a mut Vec<Row>,
    depth: usize,
    key: Option<String>,
}

impl<'de> DeserializeSeed<'de> for RowsSeed<'_> {
    type Value = usize;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_any(RowsVisitor {
            rows: self.rows,
            depth: self.depth,
            key: self.key,
        })
    }
}

struct RowsVisitor<'a> {
    rows: &'a mut Vec<Row>,
    depth: usize,
    key: Option<String>,
}

impl RowsVisitor<'_> {
    fn push(self, node: JsonNode) -> usize {
        self.rows.push(Row {
            depth: self.depth,
            key: self.key,
            node,
        });
        self.rows.len() - 1
    }
}

impl<'de> Visitor<'de> for RowsVisitor<'_> {
    type Value = usize;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a JSON value")
    }

    fn visit_unit<E>(self) -> Result<Self::Value, E> {
        Ok(self.push(JsonNode::Null))
    }

    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
        Ok(self.push(JsonNode::Boolean(value)))
    }

    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
        Ok(self.push(JsonNode::Number(value.into())))
    }

    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
        Ok(self.push(JsonNode::Number(value.into())))
    }

    fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        let number = serde_json::Number::from_f64(value)
            .ok_or_else(|| E::custom("non-finite float is not valid JSON"))?;
        Ok(self.push(JsonNode::Number(number)))
    }

    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        self.visit_string(value.to_owned())
    }

    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        self.visit_string(value.to_owned())
    }

    fn visit_string<E>(self, value: String) -> Result<Self::Value, E> {
        Ok(self.push(JsonNode::String(value)))
    }

    fn visit_seq<A>(self, mut sequence: A) -> Result<Self::Value, A::Error>
    where
        A: SeqAccess<'de>,
    {
        let Self { rows, depth, key } = self;
        let open_index = rows.len();
        rows.push(Row {
            depth,
            key,
            node: JsonNode::Container(ContainerNode::Open {
                typ: ContainerType::Array,
                collapsed: false,
                close_index: 0,
            }),
        });

        let mut is_empty = true;
        while sequence
            .next_element_seed(RowsSeed {
                rows: &mut *rows,
                depth: depth + 1,
                key: None,
            })?
            .is_some()
        {
            is_empty = false;
        }

        if is_empty {
            rows[open_index].node = JsonNode::Container(ContainerNode::Empty {
                typ: ContainerType::Array,
            });
            return Ok(open_index);
        }

        let close_index = rows.len();
        rows.push(Row {
            depth,
            key: None,
            node: JsonNode::Container(ContainerNode::Close {
                typ: ContainerType::Array,
                collapsed: false,
                open_index,
            }),
        });
        rows[open_index].node = JsonNode::Container(ContainerNode::Open {
            typ: ContainerType::Array,
            collapsed: false,
            close_index,
        });
        Ok(open_index)
    }

    fn visit_map<A>(self, mut mapping: A) -> Result<Self::Value, A::Error>
    where
        A: MapAccess<'de>,
    {
        let Self { rows, depth, key } = self;
        let open_index = rows.len();
        rows.push(Row {
            depth,
            key,
            node: JsonNode::Container(ContainerNode::Open {
                typ: ContainerType::Object,
                collapsed: false,
                close_index: 0,
            }),
        });

        let mut is_empty = true;
        while let Some(key) = mapping.next_key::<String>()? {
            mapping.next_value_seed(RowsSeed {
                rows: &mut *rows,
                depth: depth + 1,
                key: Some(key),
            })?;
            is_empty = false;
        }

        if is_empty {
            rows[open_index].node = JsonNode::Container(ContainerNode::Empty {
                typ: ContainerType::Object,
            });
            return Ok(open_index);
        }

        let close_index = rows.len();
        rows.push(Row {
            depth,
            key: None,
            node: JsonNode::Container(ContainerNode::Close {
                typ: ContainerType::Object,
                collapsed: false,
                open_index,
            }),
        });
        rows[open_index].node = JsonNode::Container(ContainerNode::Open {
            typ: ContainerType::Object,
            collapsed: false,
            close_index,
        });
        Ok(open_index)
    }
}

pub fn from_str(input: &str) -> Result<Vec<Row>, serde_json::Error> {
    collect(serde_json::Deserializer::from_str(input).into_iter::<ParsedRows>())
}

pub fn from_reader<R: Read>(reader: R) -> Result<Vec<Row>, serde_json::Error> {
    collect(serde_json::Deserializer::from_reader(reader).into_iter::<ParsedRows>())
}

fn collect<I>(documents: I) -> Result<Vec<Row>, serde_json::Error>
where
    I: IntoIterator<Item = Result<ParsedRows, serde_json::Error>>,
{
    let mut documents = documents.into_iter();
    let Some(first) = documents.next() else {
        return Ok(Vec::new());
    };
    let mut rows = first?.0;

    for document in documents {
        let mut document_rows = document?.0;
        let offset = rows.len();
        for row in &mut document_rows {
            rebase_container_indices(&mut row.node, offset);
        }
        rows.extend(document_rows);
    }
    Ok(rows)
}

fn rebase_container_indices(node: &mut JsonNode, offset: usize) {
    match node {
        JsonNode::Container(ContainerNode::Open { close_index, .. }) => {
            *close_index += offset;
        }
        JsonNode::Container(ContainerNode::Close { open_index, .. }) => {
            *open_index += offset;
        }
        _ => {}
    }
}