-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support dotted keys #73
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a brief look and the general direction seems right. The thing we need to think about is what we'd like to expose in the public API to make it easy to use and ergonomic.
#[derive(Eq, PartialEq, Clone, Debug, Hash)] | ||
pub(crate) struct Repr { | ||
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug, Hash)] | ||
pub struct Repr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it used in pub API?
@@ -8,15 +8,15 @@ pub struct Formatted<T> { | |||
|
|||
// String representation of a key or a value | |||
// together with a decoration. | |||
#[derive(Eq, PartialEq, Clone, Debug, Hash)] | |||
pub(crate) struct Repr { | |||
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug, Hash)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the derived ordering is "correct" here, it will first compare prefix, then suffixes, then raw_value
))) | ||
// From spec: | ||
// simple-key = quoted-key / unquoted-key | ||
// actual: key = unquoted-key / basic-string / literal-string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it was implemented using an older version of spec, so if it has changed, the comment is worth updating as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean the code should be updated? I added the comment to remind us the parser branches differently than the spec but the result is the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've adapted the spec in comments to the parser in some places, so sometimes it's not a direct copy-paste. From your comment change it's not clear whether they are equivalent, so it would be good to update the comment to clarify that.
/// Type for display walker to know where (during walk) to | ||
/// print dotted key. To get value, parse | ||
/// the key and descend table tree. | ||
DottedKeyMarker(Vec<SimpleKey>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't like that the internal implementation detail is leaking into the public API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we make Item opaque to the user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I'm not sure. Currently, it's possible to delete an item using table['key'] = Item::None
and I'd like to avoid unnecessary breaking changes unless there is a good reason for that. Again, let's think about what kind of API we'd like to expose the user (primarity cargo-edit), and go from that.
This comment has been minimized.
This comment has been minimized.
I'm not sure what the others' positions are on this. I thought @ordian wanted some time to figure out how we should do the public API for manipulating dotted keys. And some folks in cargo-edit wanted to try another toml library. So I'm not sure where we are. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR contains some uncommented code and unresolved TODOs. I'd like it to be resolved before it's merged.
Also not sure if it matches the newest spec
https://toml.io/en/v1.0.0-rc.3#keys
@@ -26,11 +27,36 @@ use std::str::FromStr; | |||
/// | |||
/// To parse a key use `FromStr` trait implementation: `"string".parse::<Key>()`. | |||
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Clone)] | |||
pub struct Key { | |||
pub struct SimpleKey { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about SingleKey
? Also the doccomments need to be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of going a different direction and having Key
and KeyPath
or something.
One thing benefit of "SimpleKey" is that this is the term the grammar uses
raw: InternalString, | ||
pub(crate) parts: Vec<SimpleKey>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to store raw
representation or is it always constructible from the parts?
} | ||
|
||
/// Returns the parsed key value. | ||
pub fn get(&self) -> InternalString { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the name InternalString
suggests it's not for public API, we can return a String
instead, but I'd prefer a IntoString
impl or something like that.
let keys_parts: Vec<_> = self.parts.iter().map(|k| k.raw.clone()).collect(); | ||
keys_parts.join(".") | ||
|
||
// same as raw()? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like it
/// Returns the key raw representation. | ||
pub fn raw(&self) -> &str { | ||
&self.raw | ||
} | ||
|
||
/// Get key path. | ||
pub fn get_key_path(&self) -> &[SimpleKey] { | ||
&self.parts | ||
} | ||
|
||
/// Get key path. | ||
pub fn get_string_path(&self) -> Vec<InternalString> { | ||
self.parts.iter().map(|r| r.key.clone()).collect() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced we need this.
/// Type for display walker to know where (during walk) to | ||
/// print dotted key. To get value, parse | ||
/// the key and descend table tree. | ||
DottedKeyMarker(Vec<SimpleKey>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is public API, if we do table['key'] = Item::DottedKeyMarker(vec!['a'.parse().unwrap(), 'b'.parse().unwrap()]);
what would it yield?
This part is the biggest concern with this PR.
Item::DottedKeyMarker(parsed_key.parts.clone()) | ||
)); | ||
TomlParser::descend_path(self, &path[..path.len() - 1], 0, true) | ||
.expect("the table path is valid; qed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, looking at this function it always return Ok
(or panics).
Looks like something was lost in a refactoring.
root["d.b.d"] = value(1); | ||
root["c.b.d"] = value(1); | ||
root["b.b.d"] = value(1); | ||
root["a.'c'.d"] = value(3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be good to also test something like
site."google.com" = true
When a dotted key
a.b.c
is created as a child of tableT
, we create a dotted key marker inT
and descend into child tables ofT
:a
,b
then create the dotted keya.b.c
. The dotted key marker contains the path to the real dotted key. The display walker will print the the dotted key when it finds the dotted key marker by descending into the child tables according to the path in the dotted key marker.Insert and remove works.
Also sorting works.