replacinator 0.1.0

Replace the internals of a string slice, useful for in-situ parsing
Documentation
use std::{fs::File, io::Read};

use replacinator::Replacinator;

#[derive(Debug)]
struct JsonArray<'a> {
    values: Vec<&'a mut str>,
}

fn main() {
    let mut buf = String::new();
    let _ = File::open("examples/test.json")
        .unwrap()
        .read_to_string(&mut buf)
        .unwrap();

    let json_values = Replacinator::new_in(&mut buf, parse_json_array);
    dbg!(json_values);
    println!("Buffer is now: {}", buf);
}

fn parse_json_array<'a>(src: &mut Replacinator<'a>) -> JsonArray<'a> {
    let mut values = Vec::new();
    assert_eq!(src.skip_char(), Some('['));
    loop {
        match src.skip_char() {
            Some('"') => {
                // Reset the replacinator to the beginning of this string
                let _ = src.get_begin();
                loop {
                    match src
                        .read_char()
                        .expect("JSON value should not end in the middle of a string")
                    {
                        '\\' => match src
                            .read_char()
                            .expect("JSON value should not end in the middle of an escape sequence")
                        {
                            '"' => src.write_char('"'),
                            '\\' => src.write_char('\\'),
                            '/' => src.write_char('/'),
                            'b' => src.write_char('\x08'),
                            'f' => src.write_char('\x0c'),
                            'n' => src.write_char('\n'),
                            'r' => src.write_char('\r'),
                            't' => src.write_char('\t'),
                            'u' => {
                                let mut res = 0;
                                for _ in 0..4 {
                                    let v = src
                                        .read_char()
                                        .expect("String ended in unicode")
                                        .to_digit(16)
                                        .expect("Invalid hex digit in escape");
                                    res = res * 16 + v;
                                }
                                src.write_char(
                                    std::char::from_u32(res).expect("Valid character code"),
                                )
                            }
                            other => panic!("Invalid escape {:?}", other),
                        },
                        '"' => {
                            values.push(src.get_begin());
                            src.write_char('"');
                            break;
                        }
                        other => src.write_char(other),
                    }
                }
            }
            Some(']') => break,
            Some(' ') | Some('\n') | Some('\t') => (),
            res => panic!(
                r#"JSON array should be continued with '"' or ']', got {:?}"#,
                res
            ),
        }
    }
    JsonArray { values }
}