magi-code 0.96.1

Repository-aware CLI coding agent for terminal work
Documentation
use super::*;

pub(super) fn parse_json_string_at(text: &str, start: usize) -> Option<(usize, String)> {
    let mut values = serde_json::Deserializer::from_str(&text[start..]).into_iter::<String>();
    let value = values.next()?.ok()?;
    let consumed = values.byte_offset();
    (consumed > 0).then_some((start + consumed, value))
}

pub(super) fn skip_json_whitespace(text: &str, mut index: usize) -> usize {
    while matches!(
        text.as_bytes().get(index),
        Some(b' ' | b'\t' | b'\r' | b'\n')
    ) {
        index += 1;
    }
    index
}

pub(super) fn skip_diff_prefixed_value_start(text: &str, key_start: usize, index: usize) -> usize {
    let line_start = text[..key_start].rfind('\n').map_or(0, |offset| offset + 1);
    let prefix = text
        .as_bytes()
        .get(line_start)
        .copied()
        .filter(|prefix| matches!(prefix, b'+' | b'-'));
    let mut value_start = skip_json_whitespace(text, index);
    while prefix == text.as_bytes().get(value_start).copied()
        && (value_start == 0 || text.as_bytes().get(value_start - 1) == Some(&b'\n'))
    {
        value_start = skip_json_whitespace(text, value_start + 1);
    }
    value_start
}

pub(super) fn json_string_boundary_map(token: &str, decoded: &str) -> Option<Vec<(usize, usize)>> {
    let raw = token.strip_prefix('"')?.strip_suffix('"')?;
    let mut boundaries = vec![(0, 1)];
    let mut raw_offset = 0;
    let mut decoded_offset = 0;
    while raw_offset < raw.len() {
        let consumed = if raw.as_bytes()[raw_offset] == b'\\' {
            json_escape_len(&raw[raw_offset..])?
        } else {
            raw[raw_offset..].chars().next()?.len_utf8()
        };
        let raw_end = raw_offset + consumed;
        let piece =
            serde_json::from_str::<String>(&format!("\"{}\"", &raw[raw_offset..raw_end])).ok()?;
        decoded_offset += piece.len();
        raw_offset = raw_end;
        boundaries.push((decoded_offset, raw_offset + 1));
    }
    (decoded_offset == decoded.len()).then_some(boundaries)
}

fn json_escape_len(text: &str) -> Option<usize> {
    match text.as_bytes().get(1).copied()? {
        b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => Some(2),
        b'u' => {
            let first = u16::from_str_radix(text.get(2..6)?, 16).ok()?;
            if (0xD800..=0xDBFF).contains(&first) {
                text.get(6..12)
                    .filter(|trail| trail.starts_with("\\u"))
                    .map(|_| 12)
            } else {
                Some(6)
            }
        }
        _ => None,
    }
}

pub(super) fn encode_json_string_fragment(text: &str) -> String {
    serde_json::to_string(text)
        .ok()
        .and_then(|encoded| {
            encoded
                .strip_prefix('"')
                .and_then(|inner| inner.strip_suffix('"'))
                .map(str::to_string)
        })
        .unwrap_or_else(|| "<redacted>".to_string())
}

pub(super) fn json_value_end(text: &str, start: usize) -> Option<usize> {
    if start >= text.len() {
        return None;
    }
    let mut values = serde_json::Deserializer::from_str(&text[start..]).into_iter::<Value>();
    if matches!(values.next(), Some(Ok(_))) && values.byte_offset() > 0 {
        return Some(start + values.byte_offset());
    }
    if matches!(text.as_bytes().get(start), Some(b'{' | b'[')) {
        return balanced_json_container_end(text, start).or(Some(text.len()));
    }
    let relative_end = text[start..]
        .char_indices()
        .find(|(_, character)| {
            character.is_whitespace() || matches!(character, ',' | ';' | '}' | ']')
        })
        .map_or(text.len() - start, |(offset, _)| offset);
    Some(start + relative_end.max(1))
}

fn balanced_json_container_end(text: &str, start: usize) -> Option<usize> {
    let mut stack = Vec::new();
    let mut in_string = false;
    let mut escaped = false;
    for (offset, character) in text[start..].char_indices() {
        if in_string {
            if escaped {
                escaped = false;
            } else if character == '\\' {
                escaped = true;
            } else if character == '"' {
                in_string = false;
            }
            continue;
        }
        match character {
            '"' => in_string = true,
            '{' => stack.push('}'),
            '[' => stack.push(']'),
            '}' | ']' => {
                if stack.pop() != Some(character) {
                    return None;
                }
                if stack.is_empty() {
                    return Some(start + offset + character.len_utf8());
                }
            }
            _ => {}
        }
    }
    None
}