Hi,
I found this tutorial while looking for nom tutorials. And Rust tutorials. This one seems to be the most up-to-date and well-written, and is essentially my first try at Rust. So thank you!
I had tried the tutorial on my WSL2 install (Ubuntu) on my Windows machine. But the parser fails at runtime, because of this weirdness in /proc/mounts (pasted verbatim):
C:\134 /mnt/c 9p rw,dirsync,noatime,aname=drvfs;path=C:\;uid=1000;gid=1000;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8 0 0
You may understand why this fails at first glance, but I didn't, so I needed to figure it out (which makes for an even better tutorial, IMO).
This is how I solved it.
Like our escaped_space, we need a new function to handle \134 (it's a backslash, which is totally not confusing at all). I think it should display as just C:\:
fn windows_backslash(i: &str) -> nom::IResult<&str, &str> {
nom::combinator::value("\\", nom::bytes::complete::tag("134"))(i)
}
I added this to the tuple passed into nom::branch::alt():
nom::branch::alt((
escaped_backslash,
windows_backslash,
escaped_space
)),
This seemed to work OK, until I had to parse the mount options, which failed because \; is invalid (see paste from /proc/mounts above). I added yet another parser, and added this to the nom::branch::alt call:
fn windows_options_backslash(i: &str) -> nom::IResult<&str, &str> {
nom::combinator::value("\\;", nom::bytes::complete::tag(";"))(i)
}
and
nom::branch::alt((
escaped_backslash,
windows_backslash,
escaped_space,
windows_options_backslash,
)),
(I was not sure what to name either of these functions.)
At any rate, the tests I've written against the /proc/mounts entry pass (but I haven't had a chance to actually run it on my windows box yet). Here's the one for parse_line() with different data:
#[test]
fn test_parse_line_wsl2() {
let mount3 = Mount {
device: "C:\\".to_string(),
mount_point: "/mnt/c".to_string(),
file_system_type: "9p".to_string(),
options: vec![
"rw".to_string(),
"dirsync".to_string(),
"noatime".to_string(),
"aname=drvfs;path=C:\\;uid=1000;gid=1000;symlinkroot=/mnt/".to_string(),
"mmap".to_string(),
"access=client".to_string(),
"msize=65536".to_string(),
"trans=fd".to_string(),
"rfd=8".to_string(),
"wfd=8".to_string(),
],
};
let (_, mount4) =
parse_line("C:\\134 /mnt/c 9p rw,dirsync,noatime,aname=drvfs;path=C:\\;uid=1000;gid=1000;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8 0 0").unwrap();
assert_eq!(mount3.device, mount4.device);
assert_eq!(mount3.mount_point, mount4.mount_point);
assert_eq!(mount3.file_system_type, mount4.file_system_type);
assert_eq!(mount3.options, mount4.options);
Note: I found the following causes the my test to break, because it's not returning the correct type of Err result (it expects one from tag(), not char(), just like test_escaped_space()):
fn windows_options_backslash(i: &str) -> nom::IResult<&str, &str> {
value("\\;", char(';'))(i)
}
The compiler didn't complain about this, which I found unusual, since it usually complains about everything. Assuming we're not deleting this parser, what would you have done? Update the unit test, write a new trait, etc.? I don't know what's idiomatic (yet).
I'd love if you could show how you may have tackled this problem. If you like, I can send a PR with changes for this environment, and we could also discuss the implementation that way. Or not!
Anyway, thanks again for this tutorial.
Hi,
I found this tutorial while looking for
nomtutorials. And Rust tutorials. This one seems to be the most up-to-date and well-written, and is essentially my first try at Rust. So thank you!I had tried the tutorial on my WSL2 install (Ubuntu) on my Windows machine. But the parser fails at runtime, because of this weirdness in
/proc/mounts(pasted verbatim):You may understand why this fails at first glance, but I didn't, so I needed to figure it out (which makes for an even better tutorial, IMO).
This is how I solved it.
Like our
escaped_space, we need a new function to handle\134(it's a backslash, which is totally not confusing at all). I think it should display as justC:\:I added this to the tuple passed into
nom::branch::alt():This seemed to work OK, until I had to parse the mount options, which failed because
\;is invalid (see paste from/proc/mountsabove). I added yet another parser, and added this to thenom::branch::altcall:and
(I was not sure what to name either of these functions.)
At any rate, the tests I've written against the
/proc/mountsentry pass (but I haven't had a chance to actually run it on my windows box yet). Here's the one forparse_line()with different data:Note: I found the following causes the my test to break, because it's not returning the correct type of
Errresult (it expects one fromtag(), notchar(), just liketest_escaped_space()):The compiler didn't complain about this, which I found unusual, since it usually complains about everything. Assuming we're not deleting this parser, what would you have done? Update the unit test, write a new trait, etc.? I don't know what's idiomatic (yet).
I'd love if you could show how you may have tackled this problem. If you like, I can send a PR with changes for this environment, and we could also discuss the implementation that way. Or not!
Anyway, thanks again for this tutorial.