2023-08-04 23:28:38 +02:00
|
|
|
use nom::{
|
|
|
|
branch::alt,
|
|
|
|
bytes::complete::{tag, take_while, take_while1},
|
|
|
|
character::complete::char,
|
|
|
|
character::is_alphabetic,
|
|
|
|
error::ParseError,
|
|
|
|
sequence::{pair, separated_pair, terminated},
|
|
|
|
IResult,
|
|
|
|
};
|
|
|
|
|
2023-08-05 00:07:24 +02:00
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
2023-08-04 23:28:38 +02:00
|
|
|
pub struct Xattr {
|
|
|
|
pub namespace: Vec<u8>,
|
|
|
|
pub attr: Vec<u8>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse the `namespace.attr` (or just bare `attr`) xattr names, filling in the `user` namespace
|
|
|
|
/// when none is provided.
|
|
|
|
// pub fn parse_xattr<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], Xattr, E> {
|
|
|
|
// pair(
|
|
|
|
// alt((tag(""), terminated(take_while(is_alphabetic), tag(".")))),
|
|
|
|
// take_while(is_alphabetic),
|
|
|
|
// )(i)
|
|
|
|
// .map(|(i, (namespace, attr))| {
|
|
|
|
// (
|
|
|
|
// i,
|
|
|
|
// Xattr {
|
|
|
|
// namespace: if namespace.is_empty() {
|
|
|
|
// b"user.".into_iter().copied().collect()
|
|
|
|
// } else {
|
|
|
|
// namespace.iter().copied().collect()
|
|
|
|
// },
|
|
|
|
// attr: attr.iter().copied().collect(),
|
|
|
|
// },
|
|
|
|
// )
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
|
|
|
|
fn parse_xattr_complete(i: &[u8]) -> IResult<&[u8], Xattr> {
|
|
|
|
separated_pair(
|
|
|
|
take_while1(is_alphabetic),
|
|
|
|
char('.'),
|
|
|
|
take_while1(is_alphabetic),
|
|
|
|
)(i)
|
|
|
|
.map(|(i, (namespace, attr))| {
|
|
|
|
(
|
|
|
|
i,
|
|
|
|
Xattr {
|
|
|
|
namespace: namespace.iter().copied().collect(),
|
|
|
|
attr: attr.iter().copied().collect(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_xattr_bare(i: &[u8]) -> IResult<&[u8], Xattr> {
|
|
|
|
take_while1(is_alphabetic)(i).map(|(i, attr)| {
|
|
|
|
(
|
|
|
|
i,
|
|
|
|
Xattr {
|
|
|
|
namespace: b"user".to_vec(),
|
|
|
|
attr: attr.iter().copied().collect(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// pub fn parse_xattr(i: &[u8]) -> IResult<&[u8], Xattr> {
|
|
|
|
// pair(
|
|
|
|
// alt((tag(""), terminated(take_while(is_alphabetic), tag(".")))),
|
|
|
|
// take_while1(is_alphabetic),
|
|
|
|
// )(i)
|
|
|
|
// .map(|(i, (namespace, attr))| {
|
|
|
|
// (
|
|
|
|
// i,
|
|
|
|
// Xattr {
|
|
|
|
// namespace: if namespace.is_empty() {
|
|
|
|
// b"user".into_iter().copied().collect()
|
|
|
|
// } else {
|
|
|
|
// namespace.iter().copied().collect()
|
|
|
|
// },
|
|
|
|
// attr: attr.iter().copied().collect(),
|
|
|
|
// },
|
|
|
|
// )
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
|
|
|
|
pub fn parse_xattr(i: &[u8]) -> IResult<&[u8], Xattr> {
|
|
|
|
alt((parse_xattr_complete, parse_xattr_bare))(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_parse_xattr() {
|
|
|
|
assert!(parse_xattr(b"").is_err());
|
|
|
|
assert_eq!(
|
|
|
|
parse_xattr(b"abc"),
|
|
|
|
Ok((
|
|
|
|
b"".as_slice(),
|
|
|
|
Xattr {
|
|
|
|
namespace: b"user".to_vec(),
|
|
|
|
attr: b"abc".to_vec()
|
|
|
|
}
|
|
|
|
))
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
parse_xattr(b"system.abc"),
|
|
|
|
Ok((
|
|
|
|
b"".as_slice(),
|
|
|
|
Xattr {
|
|
|
|
namespace: b"system".to_vec(),
|
|
|
|
attr: b"abc".to_vec()
|
|
|
|
}
|
|
|
|
))
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
parse_xattr(b"blah.blah.blah"),
|
|
|
|
Ok((
|
|
|
|
b".blah".as_slice(),
|
|
|
|
Xattr {
|
|
|
|
namespace: b"blah".to_vec(),
|
|
|
|
attr: b"blah".to_vec()
|
|
|
|
}
|
|
|
|
))
|
|
|
|
);
|
|
|
|
}
|