2 unstable releases
0.2.0 | Aug 26, 2024 |
---|---|
0.1.0 | Jun 26, 2022 |
#1184 in Parser implementations
Used in 3 crates
(2 directly)
5KB
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:
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.
use header_parsing::parse_header;
use std::io::{BufRead, BufReader, Read};
enum Error {
SubheaderWithoutHeader,
... // Custom error types
}
fn parse<R: Read>(reader: R) -> Result<Map, Error> {
// a Vec<String>
let mut current_path = Vec::new();
// probably some map, like be a HashMap<Vec<String>, 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)
}