1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
use nom::branch::alt;
use nom::bytes::complete::{tag, take_while};
use nom::character::complete::{alpha1, char, space1, u32, u64};
use nom::combinator::{all_consuming, value};
use nom::sequence::tuple;
use nom::IResult;
use bch_bindgen::c::bpos;
use crate::commands::debug::{DebugCommand, DumpCommand, UpdateCommand};
fn parse_bpos(input: &str) -> IResult<&str, bpos> {
let (input, (inode, _, offset, _, snapshot)) = tuple((
u64,
char(':'),
u64,
char(':'),
alt((u32, value(u32::MAX, tag("U32_MAX")))),
))(input)?;
Ok((
input,
bpos {
inode,
offset,
snapshot,
},
))
}
fn parse_dump_cmd(input: &str) -> IResult<&str, DebugCommand> {
let (input, (_, btree, _, bpos)) =
all_consuming(tuple((space1, alpha1, space1, parse_bpos)))(input)?;
Ok((
input,
DebugCommand::Dump(DumpCommand {
btree: btree.to_string(),
bpos,
}),
))
}
fn bkey_name(input: &str) -> IResult<&str, &str> {
take_while(|c: char| c.is_alphabetic() || c == '_')(input)
}
fn field_name(input: &str) -> IResult<&str, &str> {
take_while(|c: char| c.is_alphabetic() || c == '_' || c == '.')(input)
}
fn parse_update_cmd(input: &str) -> IResult<&str, DebugCommand> {
let (input, (_, btree, _, bpos, _, bkey, _, field, _, value)) = all_consuming(tuple((
space1,
alpha1,
space1,
parse_bpos,
space1,
bkey_name,
char('.'),
field_name,
char('='),
u64,
)))(input)?;
Ok((
input,
DebugCommand::Update(UpdateCommand {
btree: btree.to_string(),
bpos,
bkey: bkey.to_string(),
field: field.to_string(),
value,
}),
))
}
fn parse_command_inner(input: &str) -> IResult<&str, DebugCommand> {
let (input, cmd) = alt((tag("dump"), tag("update")))(input)?;
match cmd {
"dump" => parse_dump_cmd(input),
"update" => parse_update_cmd(input),
_ => unreachable!(),
}
}
pub fn parse_command(input: &str) -> anyhow::Result<DebugCommand> {
match parse_command_inner(input) {
Ok((_, c)) => Ok(c),
Err(e) => Err(anyhow::anyhow!("{e}")),
}
}
|