nparse 0.0.10

Parser in rust for specific use-cases
Documentation
use std::io::{BufRead, BufReader};

use nom::{
    character::complete::{anychar, char},
    combinator::{eof, recognize},
    multi::{many0_count, many_till},
    sequence::pair,
    IResult,
};
use serde_json::{json, Value};
fn parse_line(i: &str) -> IResult<&str, (usize, &str)> {
    pair(many0_count(char(' ')), recognize(many_till(anychar, eof)))(i)
}

pub fn parse_multiline_kv_str(s: &str) -> Result<Value, String> {
    let mut obj = json!({});

    let mut keys = vec![];

    for line in BufReader::new(s.as_bytes()).lines().flatten() {
        if let Ok((_, (sp, content))) = parse_line(&line) {
            loop {
                match keys.last() {
                    Some(&(a, _)) if a >= sp => {
                        keys.pop().unwrap();
                    }
                    _ => break,
                }
            }

            let mut colon_index = 0;
            let mut content = content.to_string();

            for c in content.chars() {
                if c == ':' {
                    break;
                }
                colon_index += 1;
            }

            if colon_index < content.len() {
                let mut key = content.clone();
                content = key.split_off(colon_index + 1);
                keys.push((sp, key));
            }

            let mut splited_keys = keys.iter().flat_map(|x| x.1.split(':').next());

            let mut entry = obj
                .as_object_mut()
                .unwrap()
                .entry(splited_keys.next().unwrap());

            for key in splited_keys {
                let obj = entry.or_insert_with(|| json!({}));
                match obj {
                    Value::Array(ar) => {
                        if ar.first().map(|x| x.is_object()) != Some(true) {
                            ar.insert(0, json!({}));
                        }
                        entry = ar.first_mut().unwrap().as_object_mut().unwrap().entry(key);
                    }
                    Value::Object(map) => {
                        entry = map.entry(key);
                    }
                    Value::String(_) => {
                        *obj = json!([{}, obj]);
                        entry = obj
                            .as_array_mut()
                            .unwrap()
                            .first_mut()
                            .unwrap()
                            .as_object_mut()
                            .unwrap()
                            .entry(key);
                    }
                    _ => {
                        unreachable!()
                    }
                }
            }

            let obj = entry.or_insert_with(|| Value::Null);

            match obj.clone() {
                Value::Array(mut ar) => {
                    ar.push(json!(content.trim()));
                }
                Value::Object(map) => {
                    *obj = json!([map, content.trim()]);
                }
                Value::String(st) => {
                    *obj = json!([st, content.trim()]);
                }
                Value::Null => {
                    *obj = json!(content.trim());
                }
                _ => {
                    unreachable!()
                }
            }
        }
    }

    Ok(obj)
}