difftreelog
feat preserve object field order
in: trunk
5 files changed
crates/nixlike/Cargo.tomldiffbeforeafterboth8[dependencies]8[dependencies]9anyhow = "1.0.44"9anyhow = "1.0.44"10dprint-core = "0.46.2"10dprint-core = "0.46.2"11linked-hash-map = "0.5.4"11peg = "0.7.0"12peg = "0.7.0"12serde = "1.0.130"13serde = "1.0.130"13serde_json = "1.0.68"14serde_json = "1.0.68"crates/nixlike/src/de_impl.rsdiffbeforeafterboth1use std::{1use std::convert::{TryFrom, TryInto};2 collections::BTreeMap,23 convert::{TryFrom, TryInto},3use linked_hash_map::LinkedHashMap;4};56use serde::{4use serde::{7 de::{self, MapAccess, SeqAccess},5 de::{self, MapAccess, SeqAccess},11use crate::{Error, Value};9use crate::{Error, Value};121013struct ObjectAccess {11struct ObjectAccess {14 iter: std::collections::btree_map::IntoIter<String, Value>,12 iter: linked_hash_map::IntoIter<String, Value>,15 value: Option<Value>,13 value: Option<Value>,16}14}17impl ObjectAccess {15impl ObjectAccess {18 fn new(v: BTreeMap<String, Value>) -> Self {16 fn new(v: LinkedHashMap<String, Value>) -> Self {19 Self {17 Self {20 iter: v.into_iter(),18 iter: v.into_iter(),21 value: None,19 value: None,103 _ => Err(Error::Expected("array")),101 _ => Err(Error::Expected("array")),104 }102 }105 }103 }106 fn parse_object(self) -> Result<BTreeMap<String, Value>, Error> {104 fn parse_object(self) -> Result<LinkedHashMap<String, Value>, Error> {107 match self {105 match self {108 Value::Object(s) => Ok(s),106 Value::Object(s) => Ok(s),109 _ => Err(Error::Expected("object")),107 _ => Err(Error::Expected("object")),crates/nixlike/src/lib.rsdiffbeforeafterboth1use std::collections::BTreeMap;1use linked_hash_map::LinkedHashMap;23use peg::str::LineCol;2use peg::str::LineCol;4use se_impl::MySerialize;3use se_impl::MySerialize;29 Number(i64),28 Number(i64),30 String(String),29 String(String),31 Boolean(bool),30 Boolean(bool),32 Object(BTreeMap<String, Value>),31 Object(LinkedHashMap<String, Value>),33 Array(Vec<Value>),32 Array(Vec<Value>),34 Null,33 Null,35}34}49 / "false" {false} } / expected!("<boolean>")48 / "false" {false} } / expected!("<boolean>")50 rule indent() -> String49 rule indent() -> String51 = quiet! { s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() } } / expected!("<identifier>")50 = quiet! { s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() } } / expected!("<identifier>")52 rule object() -> BTreeMap<String, Value>51 rule object() -> LinkedHashMap<String, Value>53 = "{" _52 = "{" _54 e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*53 e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*55 "}" {?54 "}" {?56 let mut out = BTreeMap::new();55 let mut out = LinkedHashMap::new();57 for (k, v) in e {56 for (k, v) in e {58 let mut map = &mut out;57 let mut map = &mut out;59 for v in k.iter().take(k.len() - 1) {58 for v in k.iter().take(k.len() - 1) {crates/nixlike/src/se_impl.rsdiffbeforeafterboth1use std::{collections::BTreeMap, convert::TryInto};1use std::convert::TryInto;223use linked_hash_map::LinkedHashMap;3use serde::{4use serde::{4 ser::{5 ser::{5 self, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,6 self, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,96 }97 }97}98}989999pub struct MySerializeMap(BTreeMap<String, Value>, Option<String>);100pub struct MySerializeMap(LinkedHashMap<String, Value>, Option<String>);100101101impl SerializeMap for MySerializeMap {102impl SerializeMap for MySerializeMap {102 type Ok = Value;103 type Ok = Value;127 }128 }128}129}129130130pub struct MySerializeStruct(BTreeMap<String, Value>);131pub struct MySerializeStruct(LinkedHashMap<String, Value>);131132132impl SerializeStruct for MySerializeStruct {133impl SerializeStruct for MySerializeStruct {133 type Ok = Value;134 type Ok = Value;147 }148 }148}149}149150150pub struct MySerializeStructVariant(String, BTreeMap<String, Value>);151pub struct MySerializeStructVariant(String, LinkedHashMap<String, Value>);151152152impl SerializeStructVariant for MySerializeStructVariant {153impl SerializeStructVariant for MySerializeStructVariant {153 type Ok = Value;154 type Ok = Value;336 }337 }337338338 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {339 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {339 Ok(MySerializeMap(BTreeMap::new(), None))340 Ok(MySerializeMap(LinkedHashMap::new(), None))340 }341 }341342342 fn serialize_struct(343 fn serialize_struct(343 self,344 self,344 _name: &'static str,345 _name: &'static str,345 _len: usize,346 _len: usize,346 ) -> Result<Self::SerializeStruct, Self::Error> {347 ) -> Result<Self::SerializeStruct, Self::Error> {347 Ok(MySerializeStruct(BTreeMap::new()))348 Ok(MySerializeStruct(LinkedHashMap::new()))348 }349 }349350350 fn serialize_struct_variant(351 fn serialize_struct_variant(356 ) -> Result<Self::SerializeStructVariant, Self::Error> {357 ) -> Result<Self::SerializeStructVariant, Self::Error> {357 Ok(MySerializeStructVariant(358 Ok(MySerializeStructVariant(358 variant.to_owned(),359 variant.to_owned(),359 BTreeMap::new(),360 LinkedHashMap::new(),360 ))361 ))361 }362 }362}363}crates/nixlike/src/to_string.rsdiffbeforeafterboth41 out.push_signal(Signal::StartIndent);41 out.push_signal(Signal::StartIndent);42 out.push_condition(conditions::if_true_or(42 out.push_condition(conditions::if_true_or(43 "array start",43 "array start",44 is_multiple_lines.clone(),44 is_multiple_lines,45 Signal::NewLine.into(),45 Signal::NewLine.into(),46 Signal::SpaceOrNewLine.into(),46 Signal::SpaceOrNewLine.into(),47 ));47 ));48 for item in a {48 for item in a {49 write_nix_buf(item, out);49 write_nix_buf(item, out);50 out.push_condition(conditions::if_true_or(50 out.push_condition(conditions::if_true_or(51 "element separator",51 "element separator",52 is_multiple_lines.clone(),52 is_multiple_lines,53 Signal::NewLine.into(),53 Signal::NewLine.into(),54 Signal::SpaceOrNewLine.into(),54 Signal::SpaceOrNewLine.into(),55 ));55 ));73 out.push_signal(Signal::StartIndent);73 out.push_signal(Signal::StartIndent);74 out.push_condition(conditions::if_true_or(74 out.push_condition(conditions::if_true_or(75 "object start",75 "object start",76 is_multiple_lines.clone(),76 is_multiple_lines,77 Signal::NewLine.into(),77 Signal::NewLine.into(),78 Signal::SpaceOrNewLine.into(),78 Signal::SpaceOrNewLine.into(),79 ));79 ));80 for (k, v) in obj {80 for (k, v) in obj {81 write_nix_obj_key_buf(k, v, out);81 write_nix_obj_key_buf(k, v, out);82 out.push_condition(conditions::if_true_or(82 out.push_condition(conditions::if_true_or(83 "element separator",83 "element separator",84 is_multiple_lines.clone(),84 is_multiple_lines,85 Signal::NewLine.into(),85 Signal::NewLine.into(),86 Signal::SpaceOrNewLine.into(),86 Signal::SpaceOrNewLine.into(),87 ));87 ));