parse_zpool_status_field: handle tabs without copying input
This commit is contained in:
parent
b29cbc414d
commit
3352ee5656
|
@ -3,7 +3,8 @@ use serde_json::{json, Value};
|
||||||
use ::serde::{Deserialize, Serialize};
|
use ::serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::tools::nom::{
|
use crate::tools::nom::{
|
||||||
parse_complete, parse_failure, multispace0, multispace1, notspace1, parse_u64, IResult,
|
parse_complete, parse_error, parse_failure,
|
||||||
|
multispace0, multispace1, notspace1, parse_u64, IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
|
@ -101,6 +102,30 @@ fn parse_zpool_status_tree(i: &str) -> IResult<&str, Vec<ZFSPoolVDevState>> {
|
||||||
many1(parse_zpool_status_vdev)(i)
|
many1(parse_zpool_status_vdev)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn space_indented_line(indent: usize) -> impl Fn(&str) -> IResult<&str, &str> {
|
||||||
|
move |i| {
|
||||||
|
let mut len = 0;
|
||||||
|
let mut n = i;
|
||||||
|
loop {
|
||||||
|
if n.starts_with('\t') {
|
||||||
|
len += 8;
|
||||||
|
n = &n[1..];
|
||||||
|
} else if n.starts_with(' ') {
|
||||||
|
len += 1;
|
||||||
|
n = &n[1..];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if len >= indent { break; }
|
||||||
|
};
|
||||||
|
if len != indent {
|
||||||
|
return Err(parse_error(i, "not correctly indented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
take_while1(|c| c != '\n')(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_zpool_status_field(i: &str) -> IResult<&str, (String, String)> {
|
fn parse_zpool_status_field(i: &str) -> IResult<&str, (String, String)> {
|
||||||
let (i, prefix) = take_while1(|c| c != ':')(i)?;
|
let (i, prefix) = take_while1(|c| c != ':')(i)?;
|
||||||
let (i, _) = tag(":")(i)?;
|
let (i, _) = tag(":")(i)?;
|
||||||
|
@ -111,9 +136,11 @@ fn parse_zpool_status_field(i: &str) -> IResult<&str, (String, String)> {
|
||||||
|
|
||||||
let field = prefix.trim().to_string();
|
let field = prefix.trim().to_string();
|
||||||
|
|
||||||
let indent = (0..prefix.len()+2).fold(String::new(), |mut acc, _| { acc.push(' '); acc });
|
let prefix_len = expand_tab_length(prefix);
|
||||||
|
|
||||||
let parse_continuation = opt(preceded(tag(indent.as_str()), take_while1(|c| c != '\n')));
|
let indent: usize = prefix_len + 2;
|
||||||
|
|
||||||
|
let parse_continuation = opt(space_indented_line(indent));
|
||||||
|
|
||||||
let mut value = value.to_string();
|
let mut value = value.to_string();
|
||||||
|
|
||||||
|
@ -148,7 +175,6 @@ pub fn parse_zpool_status_config_tree(i: &str) -> Result<Vec<ZFSPoolVDevState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_zpool_status(input: &str) -> Result<Vec<(String, String)>, Error> {
|
fn parse_zpool_status(input: &str) -> Result<Vec<(String, String)>, Error> {
|
||||||
let input = input.replace('\t', " "); // important!
|
|
||||||
parse_complete("zfs status output", &input, many0(parse_zpool_status_field))
|
parse_complete("zfs status output", &input, many0(parse_zpool_status_field))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue