fmtview 0.2.1

Fast terminal formatter and viewer for JSON, JSONL, XML-compatible markup, and formatted diffs
Documentation
use super::super::HIGHLIGHT_CHECKPOINT_INTERVAL_BYTES;
use super::xml::XmlPairState;

#[derive(Debug, Default)]
pub(in crate::viewer) struct HighlightCheckpointIndex {
    pub(in crate::viewer) json_value_strings: Vec<XmlHighlightCheckpoint>,
    pub(in crate::viewer) xml_lines: Vec<XmlHighlightCheckpoint>,
}

#[derive(Debug, Clone)]
pub(in crate::viewer) struct XmlHighlightCheckpoint {
    pub(in crate::viewer) byte: usize,
    pub(in crate::viewer) state: XmlPairState,
}

impl HighlightCheckpointIndex {
    pub(in crate::viewer) fn json_value_before(
        &self,
        byte: usize,
    ) -> Option<XmlHighlightCheckpoint> {
        checkpoint_before(&self.json_value_strings, byte)
    }

    pub(in crate::viewer) fn xml_line_before(&self, byte: usize) -> Option<XmlHighlightCheckpoint> {
        checkpoint_before(&self.xml_lines, byte)
    }

    pub(in crate::viewer) fn remember_json_value(&mut self, byte: usize, state: &XmlPairState) {
        remember_xml_checkpoint(&mut self.json_value_strings, byte, state);
    }

    pub(in crate::viewer) fn remember_xml_line(&mut self, byte: usize, state: &XmlPairState) {
        remember_xml_checkpoint(&mut self.xml_lines, byte, state);
    }
}

pub(in crate::viewer) fn checkpoint_before(
    checkpoints: &[XmlHighlightCheckpoint],
    byte: usize,
) -> Option<XmlHighlightCheckpoint> {
    checkpoints
        .iter()
        .rev()
        .find(|checkpoint| checkpoint.byte <= byte)
        .cloned()
}

pub(in crate::viewer) fn remember_xml_checkpoint(
    checkpoints: &mut Vec<XmlHighlightCheckpoint>,
    byte: usize,
    state: &XmlPairState,
) {
    let next_byte = checkpoints
        .last()
        .map(|checkpoint| {
            checkpoint
                .byte
                .saturating_add(HIGHLIGHT_CHECKPOINT_INTERVAL_BYTES)
        })
        .unwrap_or(HIGHLIGHT_CHECKPOINT_INTERVAL_BYTES);
    if byte < next_byte {
        return;
    }

    match checkpoints.binary_search_by_key(&byte, |checkpoint| checkpoint.byte) {
        Ok(_) => {}
        Err(position) => checkpoints.insert(
            position,
            XmlHighlightCheckpoint {
                byte,
                state: state.clone(),
            },
        ),
    }
}