-
Notifications
You must be signed in to change notification settings - Fork 108
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
fix: Preserve dotted-key ordering #808
base: main
Are you sure you want to change the base?
Conversation
Pull Request Test Coverage Report for Build 11785987202Details
💛 - Coveralls |
Just to add a note about the additional changes, I've switched the Originally, I used
If the If the let doc = r#"foo.bar = 1
foo.baz.qwer = "a"
goodbye = { forever="no" }
foo.pub = 2
foo.baz.asdf = "b"
"#.parse<MutDocument>().unwrap();
let root = doc.as_table_mut();
root["foo"]["baz"]["zxcv"] = "CCC"
assert_data_eq!(doc.to_string(), r#"foo.bar = 1
foo.baz.qwer = "a"
foo.baz.asdf = "b"
foo.baz.zxcv = "CCC"
goodbye = { forever="no" }
foo.pub = 2
"#); where The only remaining problem is a somewhat odd one, that would not normally come up, which is to merge tables by iterating through the second table's keys manually like so: let mut origin_doc = r#"
foo = 1
bar = 2
"#.parse::<DocumentMut>().unwrap();
let mut additional_doc = r#"
baz = 3
qux = 4
"#.parse::<DocumentMut>().unwrap();
let origin_table = origin_doc.as_table_mut();
// if we use origin_table.extend(addition_doc.iter()) this does not occur
// it only occurs when we directly get the key from its parsed
additional_doc.iter().for_each(|(k, v)| {
// we get the actually `Key` here with its position
let (key, _) = additional_doc.get_key_value(k).unwrap();
origin_table.insert_formatted(key, v.clone());
});
// baz (with position=Some(0) from the second table) gets inserted before
// bar (with position=Some(1) from the first table)
assert_data_eq!(origin_doc.to_string(), r#"
foo = 1
baz = 3
bar = 2
qux = 4
"#); But as noted, the more canonical process of using |
not really sure if that comment should be a doc or not, maybe I should have just made it into a non-doc comment, but I just did what the linter said to instead, so hopefully that fixes it. |
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.
In fact, because of this, we could remove the ordering of the IndexMap completely now, and instead rely on the position value, thereby reducing the chances of future confusion.
Table
and InlineTable
have the semantics of an IndexMap
. We need to preserve the order of content as it gets inserted. We could set a position on insertion.
Also, I'm unsure about allowing key positions to be moved between tables because the position is dependent on the other values within the same table and you can't easily translate that from one table to the next.
Could you clean up the commits for how you would want me to review and merge this? My recommendation is to split up commits so that
|
This is a very common case and is one the motivating reasons for this crate. Grouping dotted keys, rather than treating a dotted key as something to add at the end, is a more natural behavior. We currently get it for free. We don't always guarantee a more natural way of doing things though. However, if we were to change it, it would likely be a breaking behavior change. |
Fixes #163
Based on @epage's WIP work from #165.
Admittedly not the most efficient solution as it adds another
Vec::sort_by_key
to theTable::append_values
andInlineTable::append_values
functions, sorting theVec
s after the values have just been inserted into them.The slightly more efficientI was incorrect about this, and have usedVec::sort_by_key
is not necessarily possible since it might move non-dotted keys all together, thus again breaking the original document's order.Vec::sort_by_key
insteadA better solution might be to insert the values into the values
Vec
s in the intended order, but this would be much more involved.Note:
This change failed some tests from the
edit
functionality, specifically,Table::{sort_values, sort_values_by}
and theInlineTable
versions. So, I created a targeted fix for that, where it just sets theKey.position
property to be the index in the iterator over its keys.The implication here is that any future changes that involve key re-orderings on Tables will have to modify
Key.position
value, instead of just their order in theitems: IndexMap
.In fact, because of this, we could remove the ordering of the
IndexMap
completely now, and instead rely on the position value, thereby reducing the chances of future confusion.Without a more comprehensive change like that, I have a feeling there might be an untested use case here somewhere, if something else I'm not aware of is modifying the
Key
order inTable.items
orInlineTable.items
, then this will now fail.