Skip to content
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

WIP: fix: Preserve dotted-key ordering #165

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ impl Display for InlineTable {
)?;
write!(f, "{}", self.preamble)?;

let children = self.get_values();
let mut children = self.get_values();
children.sort_by_key(|(k, _)| {
let last_index = k.len() - 1;
k[last_index].position().unwrap_or(usize::MAX)
});

for (i, (key_path, value)) in children.into_iter().enumerate() {
let key = key_path_display(&key_path, DEFAULT_INLINE_KEY_DECOR);
if i > 0 {
Expand Down Expand Up @@ -143,7 +148,11 @@ fn visit_table(
path: &[&Key],
is_array_of_tables: bool,
) -> Result {
let children = table.get_values();
let mut children = table.get_values();
children.sort_by_key(|(k, _)| {
let last_index = k.len() - 1;
k[last_index].position().unwrap_or(usize::MAX)
});

if path.is_empty() {
// don't print header for the root node
Expand Down
18 changes: 18 additions & 0 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub struct Key {
key: InternalString,
pub(crate) repr: Repr,
pub(crate) decor: Decor,
pub(crate) position: Option<usize>,
}

impl Key {
Expand All @@ -45,6 +46,7 @@ impl Key {
key,
repr,
decor: Default::default(),
position: Default::default(),
}
}

Expand All @@ -54,6 +56,12 @@ impl Key {
self
}

/// While creating the `Key`, add a table position to it
pub fn with_position(mut self, position: Option<usize>) -> Self {
self.position = position;
self
}

/// Returns the parsed key value.
pub fn get(&self) -> &str {
&self.key
Expand All @@ -74,6 +82,16 @@ impl Key {
&mut self.decor
}

/// Get the position relative to other keys in parent table
pub fn position(&self) -> Option<usize> {
return self.position;
}

/// Set the position relative to other keys in parent table
pub fn set_position(&mut self, position: Option<usize>) {
self.position = position;
}

fn try_parse(s: &str) -> Result<Key, parser::TomlError> {
use combine::EasyParser;
let result = parser::key_parser().easy_parse(Stream::new(s));
Expand Down
2 changes: 2 additions & 0 deletions src/parser/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ impl TomlParser {
first_key.decor.suffix().unwrap_or_default(),
);
}
kv.key.set_position(Some(self.current_value_position));
self.current_value_position += 1;

let root = self.document.as_table_mut();
let table = Self::descend_path(root, self.current_table_path.as_slice(), 0, false)
Expand Down
4 changes: 3 additions & 1 deletion src/parser/inline_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ fn table_from_pairs(
..Default::default()
};

for (path, kv) in v {
for (position, (path, mut kv)) in v.into_iter().enumerate() {
kv.key.set_position(Some(position));

let table = descend_path(&mut root, &path, 0)?;
if table.contains_key(kv.key.get()) {
return Err(CustomError::DuplicateKey {
Expand Down
8 changes: 8 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub(crate) struct TomlParser {
document: Box<Document>,
current_table_path: Vec<Key>,
current_table_position: usize,
// Current position within a table, to help order dotted keys
current_value_position: usize,
}

impl Default for TomlParser {
Expand All @@ -34,6 +36,7 @@ impl Default for TomlParser {
document: Box::new(Document::new()),
current_table_path: Vec::new(),
current_table_position: 0,
current_value_position: 0,
}
}
}
Expand Down Expand Up @@ -391,6 +394,7 @@ trimmed in raw strings.
r#"{a = 1e165}"#,
r#"{ hello = "world", a = 1}"#,
r#"{ hello.world = "a" }"#,
r#"{ hello.world = "a", goodbye = "b", hello.moon = "c" }"#,
];
for input in &inputs {
parsed_value_eq!(input);
Expand Down Expand Up @@ -498,6 +502,10 @@ that
key = "value"
"#,
r#"hello.world = "a"
"#,
r#"hello.world = "a"
goodbye = "b"
hello.moon = "c"
"#,
];
for document in &documents {
Expand Down
2 changes: 2 additions & 0 deletions src/parser/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ impl TomlParser {
let leading = mem::take(&mut self.document.trailing);
let table = self.document.as_table_mut();
self.current_table_position += 1;
self.current_value_position = 0;

let table = Self::descend_path(table, &path[..path.len() - 1], 0, false)?;
let key = &path[path.len() - 1];
Expand Down Expand Up @@ -160,6 +161,7 @@ impl TomlParser {

let leading = mem::take(&mut self.document.trailing);
let table = self.document.as_table_mut();
self.current_value_position = 0;

let key = &path[path.len() - 1];
let table = Self::descend_path(table, &path[..path.len() - 1], 0, false);
Expand Down