feat(api): Improve .get()/.entry() APIs to be more consistent with Rust conventions

BREAKING CHANGE: KdlNode::get* are now KdlNode::entry*. Additionally, KdlDocument::get_dash_vals has been renamed to KdlDocument::get_dash_args.
This commit is contained in:
Kat Marchán 2022-11-29 23:09:13 -08:00
parent c7b6b823e9
commit 3d8778a610
No known key found for this signature in database
GPG Key ID: AEB529C08A3C7E9E
2 changed files with 45 additions and 39 deletions

View File

@ -107,9 +107,7 @@ impl KdlDocument {
/// assert_eq!(doc.get_arg("foo"), Some(&1.into()));
/// ```
pub fn get_arg(&self, name: &str) -> Option<&KdlValue> {
self.get(name)
.and_then(|node| node.get(0))
.map(|e| e.value())
self.get(name).and_then(|node| node.get(0))
}
/// Gets the all node arguments (value) of the first child node with a
@ -147,9 +145,7 @@ impl KdlDocument {
/// child node with a matching name. This is a shorthand utility for cases
/// where a document is being used as a key/value store.
pub fn get_arg_mut(&mut self, name: &str) -> Option<&mut KdlValue> {
self.get_mut(name)
.and_then(|node| node.get_mut(0))
.map(|e| e.value_mut())
self.get_mut(name).and_then(|node| node.get_mut(0))
}
/// This utility makes it easy to interact with a KDL convention where
@ -170,18 +166,16 @@ impl KdlDocument {
/// ```rust
/// # use kdl::{KdlDocument, KdlValue};
/// # let doc: KdlDocument = "foo {\n - 1\n - 2\n - false\n}".parse().unwrap();
/// assert_eq!(doc.get_dash_vals("foo"), vec![&1.into(), &2.into(), &false.into()]);
/// assert_eq!(doc.get_dash_args("foo"), vec![&1.into(), &2.into(), &false.into()]);
/// ```
pub fn get_dash_vals(&self, name: &str) -> Vec<&KdlValue> {
pub fn get_dash_args(&self, name: &str) -> Vec<&KdlValue> {
self.get(name)
.and_then(|n| n.children())
.map(|doc| doc.nodes())
.unwrap_or_default()
.iter()
.filter(|e| e.name().value() == "-")
.map(|e| e.get(0))
.filter(|v| v.is_some())
.map(|v| v.unwrap().value())
.filter_map(|e| e.get(0))
.collect()
}
@ -386,7 +380,7 @@ final;";
assert_eq!(doc.leading, Some("".into()));
assert_eq!(doc.get_arg("foo"), Some(&1.into()));
assert_eq!(
doc.get_dash_vals("foo"),
doc.get_dash_args("foo"),
vec![&1.into(), &2.into(), &"three".into()]
);
@ -642,14 +636,14 @@ inline { time; to; live "our" "dreams"; "y;all"; }
);
// Some simple with/without type hints
check_span(r#"(a)"cool""#, is_node.get(0).unwrap().span(), &input);
check_span(r#"(a)"cool""#, is_node.entry(0).unwrap().span(), &input);
check_span(
r#"read=(int)5"#,
is_node.get("read").unwrap().span(),
is_node.entry("read").unwrap().span(),
&input,
);
check_span(r#"10.1"#, is_node.get(1).unwrap().span(), &input);
check_span(r#"(u32)0x45"#, is_node.get(2).unwrap().span(), &input);
check_span(r#"10.1"#, is_node.entry(1).unwrap().span(), &input);
check_span(r#"(u32)0x45"#, is_node.entry(2).unwrap().span(), &input);
// Now let's look at some messed up parts of that "and" node
let and_node = doc
@ -684,7 +678,7 @@ inline { time; to; live "our" "dreams"; "y;all"; }
);
// Oh hey don't forget to check that "x" entry
check_span(r#"x="""#, and_node.get("x").unwrap().span(), &input);
check_span(r#"x="""#, and_node.entry("x").unwrap().span(), &input);
// Now the "it" node, more straightforward
let it_node = and_node.children().unwrap().get("it").unwrap();
@ -693,10 +687,14 @@ inline { time; to; live "our" "dreams"; "y;all"; }
it_node.span(),
&input,
);
check_span(r#""has"="💯""#, it_node.get("has").unwrap().span(), &input);
check_span(
r#""has"="💯""#,
it_node.entry("has").unwrap().span(),
&input,
);
check_span(
r####"r##"the"##"####,
it_node.get(0).unwrap().span(),
it_node.entry(0).unwrap().span(),
&input,
);

View File

@ -184,13 +184,19 @@ impl KdlNode {
}
}
/// Fetches an entry by key. Number keys will look up arguments, strings
/// will look up properties.
pub fn get(&self, key: impl Into<NodeKey>) -> Option<&KdlEntry> {
self.get_impl(key.into())
/// Gets a value by key. Number keys will look up arguments, strings will
/// look up properties.
pub fn get(&self, key: impl Into<NodeKey>) -> Option<&KdlValue> {
self.entry_impl(key.into()).map(|e| &e.value)
}
fn get_impl(&self, key: NodeKey) -> Option<&KdlEntry> {
/// Fetches an entry by key. Number keys will look up arguments, strings
/// will look up properties.
pub fn entry(&self, key: impl Into<NodeKey>) -> Option<&KdlEntry> {
self.entry_impl(key.into())
}
fn entry_impl(&self, key: NodeKey) -> Option<&KdlEntry> {
match key {
NodeKey::Key(key) => {
let mut current = None;
@ -221,13 +227,19 @@ impl KdlNode {
}
}
/// Fetches a mutable referene to an entry by key. Number keys will look
/// Fetches a mutable referene to an value by key. Number keys will look
/// up arguments, strings will look up properties.
pub fn get_mut(&mut self, key: impl Into<NodeKey>) -> Option<&mut KdlEntry> {
self.get_mut_impl(key.into())
pub fn get_mut(&mut self, key: impl Into<NodeKey>) -> Option<&mut KdlValue> {
self.entry_mut_impl(key.into()).map(|e| &mut e.value)
}
fn get_mut_impl(&mut self, key: NodeKey) -> Option<&mut KdlEntry> {
/// Fetches a mutable referene to an entry by key. Number keys will look
/// up arguments, strings will look up properties.
pub fn entry_mut(&mut self, key: impl Into<NodeKey>) -> Option<&mut KdlEntry> {
self.entry_mut_impl(key.into())
}
fn entry_mut_impl(&mut self, key: NodeKey) -> Option<&mut KdlEntry> {
match key {
NodeKey::Key(key) => {
let mut current = None;
@ -280,7 +292,7 @@ impl KdlNode {
if entry.name.as_ref().map(|i| i.value()) != Some(key_val.value()) {
panic!("Property name mismatch");
}
if let Some(existing) = self.get_mut(key) {
if let Some(existing) = self.entry_mut(key) {
std::mem::swap(existing, &mut entry);
Some(entry)
} else {
@ -292,7 +304,7 @@ impl KdlNode {
if entry.name.is_some() {
panic!("Cannot insert property with name under a numerical key");
}
if let Some(existing) = self.get_mut(key) {
if let Some(existing) = self.entry_mut(key) {
std::mem::swap(existing, &mut entry);
Some(entry)
} else {
@ -441,15 +453,13 @@ impl Index<usize> for KdlNode {
type Output = KdlValue;
fn index(&self, index: usize) -> &Self::Output {
self.get(index).expect("Argument out of range.").value()
self.get(index).expect("Argument out of range.")
}
}
impl IndexMut<usize> for KdlNode {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.get_mut(index)
.expect("Argument out of range.")
.value_mut()
self.get_mut(index).expect("Argument out of range.")
}
}
@ -457,7 +467,7 @@ impl Index<&str> for KdlNode {
type Output = KdlValue;
fn index(&self, key: &str) -> &Self::Output {
self.get(key).expect("No such property.").value()
self.get(key).expect("No such property.")
}
}
@ -466,9 +476,7 @@ impl IndexMut<&str> for KdlNode {
if self.get(key).is_none() {
self.push((key, KdlValue::Null));
}
self.get_mut(key)
.expect("Something went wrong.")
.value_mut()
self.get_mut(key).expect("Something went wrong.")
}
}
@ -594,7 +602,7 @@ mod test {
assert_eq!(node.trailing(), Some(";\n"));
assert_eq!(node.ty(), Some(&"\"ty\"".parse()?));
assert_eq!(node.name(), &"\"node\"".parse()?);
assert_eq!(node.get(0), Some(&"0xDEADbeef".parse()?));
assert_eq!(node.entry(0), Some(&"0xDEADbeef".parse()?));
r#"
node "test" {