# Header parsing This library is meant to help with parsing markdown inspired files, where headers are marked by a sequence of "#". The only function `parse_header` is meant to be used when parsing a file line by line. If the line starts with a "#", the function will return `Some` bool to indicate if it's a valid format, else it will return `None`. The only invalid format is when a header starts with more than one "#" more than the previous header. This makes using markdown as config files viable. ## Example config Headers and subheaders are stored as array. For example you could have a file like this: ```md A # Header 1 B ## Subheader 1 C ## Subheader 2 D # Header 2 E ## Subheader 1 F ## Subheader 2 G ``` The letters would belong to different headers: - `A` belongs to no subheader (`[]`) - `B` belongs to "Header 1" (`["Header 1"]`) - `C` belongs to "Subheader 1" of "Header 1" (`["Header 1", "Subheader 1"]`) - `D` belongs to "Subheader 2" of "Header 1" (`["Header 1", "Subheader 2"]`) - `E` belongs to "Header 2" (`["Header 2"]`) - `F` belongs to "Subheader 1" of "Header 2" (`["Header 2", "Subheader 1"]`) - `G` belongs to "Subheader 2" of "Header 2" (`["Header 2", "Subheader 2"]`) ## Usage You have to store the path of headers and subheader yourself. This way, you are allowed to handle the sections inbetween the headers as you want. ```rust use header_parsing::parse_header; use std::io::{BufRead, BufReader, Read}; enum Error { SubheaderWithoutHeader, ... // Custom error types } fn parse(reader: R) -> Result { // a Vec let mut current_path = Vec::new(); // probably some map, like be a HashMap, Value> let mut result = Map::new(); // the content inbetween the headers parsed into the wanted format let mut value = Value::new(); for line in BufReader::new(reader).lines() { if let Ok(line) = line { // if current line is a header if let Some(success) = parse_header(¤t_path, &line) { if let Ok(path_changes) = success { // add parsed value to previous subheader result.add(current_path.clone(), value); // start parsing next subsection value = Value::new(); // apply path changes path_changes.apply(&mut current_path); } else { return Err(Error::SubheaderWithoutHeader); } } } else { // parse the content inbetween headers value.add_and_parse_line(line)?; } } result.add(value); Ok(result) } ```