difftreelog
feat nixlike serialization
in: trunk
6 files changed
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,3 +21,6 @@
tempfile = "3.2"
once_cell = "1.5"
hostname = "0.3.1"
+
+[workspace]
+members = ["crates/nixlike"]
crates/nixlike/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/crates/nixlike/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "nixlike"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+anyhow = "1.0.44"
+dprint-core = "0.46.2"
+peg = "0.7.0"
+serde = "1.0.130"
+serde_json = "1.0.68"
+thiserror = "1.0.29"
crates/nixlike/src/de_impl.rsdiffbeforeafterboth1use std::{2 collections::BTreeMap,3 convert::{TryFrom, TryInto},4};56use serde::{7 de::{self, MapAccess, SeqAccess},8 Deserializer,9};1011use crate::{Error, Value};1213struct ObjectAccess {14 iter: std::collections::btree_map::IntoIter<String, Value>,15 value: Option<Value>,16}17impl ObjectAccess {18 fn new(v: BTreeMap<String, Value>) -> Self {19 Self {20 iter: v.into_iter(),21 value: None,22 }23 }24}2526impl<'de> MapAccess<'de> for ObjectAccess {27 type Error = Error;2829 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>30 where31 K: de::DeserializeSeed<'de>,32 {33 if let Some((k, v)) = self.iter.next() {34 let _ = self.value.insert(v);35 Ok(Some(seed.deserialize(Value::String(k))?))36 } else {37 Ok(None)38 }39 }4041 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>42 where43 V: de::DeserializeSeed<'de>,44 {45 seed.deserialize(self.value.take().unwrap())46 }47}4849struct ArrayAccess {50 iter: std::vec::IntoIter<Value>,51}52impl ArrayAccess {53 fn new(v: Vec<Value>) -> Self {54 Self {55 iter: v.into_iter(),56 }57 }58}5960impl<'de> SeqAccess<'de> for ArrayAccess {61 type Error = Error;6263 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>64 where65 T: de::DeserializeSeed<'de>,66 {67 if let Some(v) = self.iter.next() {68 Ok(Some(seed.deserialize(v)?))69 } else {70 Ok(None)71 }72 }73}7475impl Value {76 fn parse_int<T: TryFrom<i64>>(&self) -> Result<T, Error> {77 match self {78 Value::Number(n) => Ok((*n).try_into().map_err(|_| Error::BadNumber)?),79 _ => Err(Error::Expected("integer")),80 }81 }82 fn parse_boolean(self) -> Result<bool, Error> {83 match self {84 Value::Boolean(b) => Ok(b),85 _ => Err(Error::Expected("boolean")),86 }87 }88 pub fn parse_string(&self) -> Result<&str, Error> {89 match self {90 Value::String(s) => Ok(s),91 _ => Err(Error::Expected("string")),92 }93 }94 fn parse_char(self) -> Result<char, Error> {95 match self {96 Value::String(s) if s.chars().count() == 1 => Ok(s.chars().next().unwrap()),97 _ => Err(Error::Expected("char")),98 }99 }100 fn parse_array(self) -> Result<Vec<Value>, Error> {101 match self {102 Value::Array(s) => Ok(s),103 _ => Err(Error::Expected("array")),104 }105 }106 fn parse_object(self) -> Result<BTreeMap<String, Value>, Error> {107 match self {108 Value::Object(s) => Ok(s),109 _ => Err(Error::Expected("object")),110 }111 }112 fn parse_null(self) -> Result<(), Error> {113 match self {114 Value::Null => Ok(()),115 _ => Err(Error::Expected("null")),116 }117 }118}119120impl de::Error for Error {121 fn custom<T>(msg: T) -> Self122 where123 T: std::fmt::Display,124 {125 Self::Custom(format!("{}", msg))126 }127}128129impl<'de> Deserializer<'de> for Value {130 type Error = Error;131132 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>133 where134 V: serde::de::Visitor<'de>,135 {136 match self {137 Value::Number(f) => visitor.visit_i64(f),138 Value::String(s) => visitor.visit_str(&s),139 Value::Boolean(b) => visitor.visit_bool(b),140 Value::Object(o) => visitor.visit_map(ObjectAccess::new(o)),141 Value::Array(a) => visitor.visit_seq(ArrayAccess::new(a)),142 Value::Null => visitor.visit_none(),143 }144 }145146 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>147 where148 V: serde::de::Visitor<'de>,149 {150 visitor.visit_bool(self.parse_boolean()?)151 }152153 fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>154 where155 V: serde::de::Visitor<'de>,156 {157 visitor.visit_i8(self.parse_int()?)158 }159160 fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>161 where162 V: serde::de::Visitor<'de>,163 {164 visitor.visit_i16(self.parse_int()?)165 }166167 fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>168 where169 V: serde::de::Visitor<'de>,170 {171 visitor.visit_i32(self.parse_int()?)172 }173174 fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>175 where176 V: serde::de::Visitor<'de>,177 {178 visitor.visit_i64(self.parse_int()?)179 }180181 fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>182 where183 V: serde::de::Visitor<'de>,184 {185 visitor.visit_u8(self.parse_int()?)186 }187188 fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>189 where190 V: serde::de::Visitor<'de>,191 {192 visitor.visit_u16(self.parse_int()?)193 }194195 fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>196 where197 V: serde::de::Visitor<'de>,198 {199 visitor.visit_u32(self.parse_int()?)200 }201202 fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>203 where204 V: serde::de::Visitor<'de>,205 {206 visitor.visit_u64(self.parse_int()?)207 }208209 fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>210 where211 V: serde::de::Visitor<'de>,212 {213 todo!()214 }215216 fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>217 where218 V: serde::de::Visitor<'de>,219 {220 todo!()221 }222223 fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>224 where225 V: serde::de::Visitor<'de>,226 {227 visitor.visit_char(self.parse_char()?)228 }229230 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>231 where232 V: serde::de::Visitor<'de>,233 {234 visitor.visit_str(self.parse_string()?)235 }236237 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>238 where239 V: serde::de::Visitor<'de>,240 {241 visitor.visit_string(self.parse_string()?.to_owned())242 }243244 fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>245 where246 V: serde::de::Visitor<'de>,247 {248 todo!()249 }250251 fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error>252 where253 V: serde::de::Visitor<'de>,254 {255 todo!()256 }257258 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>259 where260 V: serde::de::Visitor<'de>,261 {262 match self {263 Value::Null => visitor.visit_none(),264 v => visitor.visit_some(v),265 }266 }267268 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>269 where270 V: serde::de::Visitor<'de>,271 {272 self.parse_null()?;273 visitor.visit_unit()274 }275276 fn deserialize_unit_struct<V>(277 self,278 _name: &'static str,279 visitor: V,280 ) -> Result<V::Value, Self::Error>281 where282 V: serde::de::Visitor<'de>,283 {284 self.deserialize_unit(visitor)285 }286287 fn deserialize_newtype_struct<V>(288 self,289 _name: &'static str,290 visitor: V,291 ) -> Result<V::Value, Self::Error>292 where293 V: serde::de::Visitor<'de>,294 {295 visitor.visit_newtype_struct(self)296 }297298 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>299 where300 V: serde::de::Visitor<'de>,301 {302 visitor.visit_seq(self.parse_array().map(ArrayAccess::new)?)303 }304305 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>306 where307 V: serde::de::Visitor<'de>,308 {309 self.deserialize_seq(visitor)310 }311312 fn deserialize_tuple_struct<V>(313 self,314 _name: &'static str,315 _len: usize,316 visitor: V,317 ) -> Result<V::Value, Self::Error>318 where319 V: serde::de::Visitor<'de>,320 {321 self.deserialize_seq(visitor)322 }323324 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>325 where326 V: serde::de::Visitor<'de>,327 {328 visitor.visit_map(self.parse_object().map(ObjectAccess::new)?)329 }330331 fn deserialize_struct<V>(332 self,333 _name: &'static str,334 _fields: &'static [&'static str],335 visitor: V,336 ) -> Result<V::Value, Self::Error>337 where338 V: serde::de::Visitor<'de>,339 {340 self.deserialize_map(visitor)341 }342343 fn deserialize_enum<V>(344 self,345 _name: &'static str,346 _variants: &'static [&'static str],347 _visitor: V,348 ) -> Result<V::Value, Self::Error>349 where350 V: serde::de::Visitor<'de>,351 {352 todo!()353 }354355 fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>356 where357 V: serde::de::Visitor<'de>,358 {359 self.deserialize_str(visitor)360 }361362 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>363 where364 V: serde::de::Visitor<'de>,365 {366 self.deserialize_any(visitor)367 }368}crates/nixlike/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/nixlike/src/lib.rs
@@ -0,0 +1,125 @@
+use std::collections::BTreeMap;
+
+use peg::str::LineCol;
+use se_impl::MySerialize;
+use serde::{Deserialize, Serialize};
+
+mod de_impl;
+mod se_impl;
+mod to_string;
+
+#[derive(thiserror::Error, Debug)]
+pub enum Error {
+ #[error("bad number")]
+ BadNumber,
+ #[error("expected {0}")]
+ Expected(&'static str),
+ #[error("parse error")]
+ ParseError(#[from] peg::error::ParseError<LineCol>),
+ #[error("{0}")]
+ Custom(String),
+ #[error("io: {0}")]
+ Io(#[from] std::io::Error),
+ #[error("fmt: {0}")]
+ Fmt(#[from] std::fmt::Error),
+}
+
+#[derive(Debug)]
+pub enum Value {
+ Number(i64),
+ String(String),
+ Boolean(bool),
+ Object(BTreeMap<String, Value>),
+ Array(Vec<Value>),
+ Null,
+}
+
+peg::parser! {
+pub grammar nixlike() for str {
+ rule number() -> i64
+ = v:$(['0'..='9' | '+' | '-']+) {? v.parse().map_err(|_| "<number>")}
+ rule string() -> String
+ = "\"" v:$((!"\"" [_])+) "\"" { v.to_owned() }
+ rule boolean() -> bool
+ = "true" {true}
+ / "false" {false}
+ rule indent() -> String
+ = s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() }
+ rule object() -> BTreeMap<String, Value>
+ = "{" _
+ e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*
+ "}" {?
+ let mut out = BTreeMap::new();
+ for (k, v) in e {
+ let mut map = &mut out;
+ for v in k.iter().take(k.len() - 1) {
+ map = match map.entry(v.clone()).or_insert_with(|| Value::Object(Default::default())) {
+ Value::Object(v) => v,
+ _ => return Err("expected object"),
+ }
+ }
+
+ let key = k.into_iter().last().unwrap();
+ if map.contains_key(&key) {
+ return Err("can't override object");
+ }
+ map.insert(key, v);
+ }
+ Ok(out)
+ }
+
+ rule array() -> Vec<Value>
+ = "[" _ v:value()**_ _ "]" {v}
+
+ rule value() -> Value
+ = o:object() { Value::Object(o) }
+ / a:array() { Value::Array(a) }
+ / s:string() { Value::String(s) }
+ / b:boolean() { Value::Boolean(b) }
+ / n:number() { Value::Number(n) }
+
+ pub rule root() -> Value
+ = _ v:value() _ { v }
+
+ rule _()
+ = [' ' | '\t' | '\n']*
+}
+}
+
+pub fn parse_str<'de, D: Deserialize<'de>>(s: &str) -> Result<D, Error> {
+ let value = nixlike::root(s)?;
+ D::deserialize(value)
+}
+
+pub fn parse_value<'de, D: Deserialize<'de>>(value: Value) -> Result<D, Error> {
+ D::deserialize(value)
+}
+
+pub fn serialize_value_pretty(value: Value) -> Result<String, Error> {
+ to_string::write_nix(&value)
+}
+
+pub fn serialize<S: Serialize>(value: S) -> Result<String, Error> {
+ let value: Value = value.serialize(MySerialize)?;
+ serialize_value_pretty(value)
+}
+
+#[test]
+fn test() {
+ let v: serde_json::Value = parse_str(
+ r#"
+ {
+ b.c = 2;
+ b.d = "hello";
+ c = {
+ k = 123;
+ p = 231;
+ ll = [1 2 3 [] [[4 5 6]] ];
+ };
+ }
+ "#,
+ )
+ .unwrap();
+ let s: String = serialize(v).unwrap();
+ println!("{}", s);
+}
crates/nixlike/src/se_impl.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/nixlike/src/se_impl.rs
@@ -0,0 +1,362 @@
+use std::{collections::BTreeMap, convert::TryInto};
+
+use serde::{
+ ser::{
+ self, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
+ SerializeTupleStruct, SerializeTupleVariant,
+ },
+ Serializer,
+};
+
+use crate::{Error, Value};
+
+impl ser::Error for Error {
+ fn custom<T>(msg: T) -> Self
+ where
+ T: std::fmt::Display,
+ {
+ Self::Custom(format!("{}", msg))
+ }
+}
+
+pub struct MySerializeSeq(Vec<Value>);
+
+impl SerializeSeq for MySerializeSeq {
+ type Ok = Value;
+
+ type Error = Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ self.0.push(value.serialize(MySerialize)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Array(self.0))
+ }
+}
+impl SerializeTuple for MySerializeSeq {
+ type Ok = Value;
+
+ type Error = Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ self.0.push(value.serialize(MySerialize)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Array(self.0))
+ }
+}
+impl SerializeTupleStruct for MySerializeSeq {
+ type Ok = Value;
+
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ self.0.push(value.serialize(MySerialize)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Array(self.0))
+ }
+}
+
+pub struct MySerializeSeqVariant(String, MySerializeSeq);
+
+impl SerializeTupleVariant for MySerializeSeqVariant {
+ type Ok = Value;
+
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ self.1.serialize_field(value)
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Object(
+ vec![(self.0, Value::Array(self.1 .0))]
+ .into_iter()
+ .collect(),
+ ))
+ }
+}
+
+pub struct MySerializeMap(BTreeMap<String, Value>, Option<String>);
+
+impl SerializeMap for MySerializeMap {
+ type Ok = Value;
+
+ type Error = Error;
+
+ fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ let _ = self
+ .1
+ .insert(key.serialize(MySerialize)?.parse_string()?.to_owned());
+ Ok(())
+ }
+
+ fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ self.0
+ .insert(self.1.take().unwrap(), value.serialize(MySerialize)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Object(self.0))
+ }
+}
+
+pub struct MySerializeStruct(BTreeMap<String, Value>);
+
+impl SerializeStruct for MySerializeStruct {
+ type Ok = Value;
+
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, key: &str, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ self.0.insert(key.to_owned(), value.serialize(MySerialize)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Object(self.0))
+ }
+}
+
+pub struct MySerializeStructVariant(String, BTreeMap<String, Value>);
+
+impl SerializeStructVariant for MySerializeStructVariant {
+ type Ok = Value;
+
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(
+ &mut self,
+ key: &'static str,
+ value: &T,
+ ) -> Result<(), Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ self.1.insert(key.to_owned(), value.serialize(MySerialize)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Object(
+ vec![(self.0, Value::Object(self.1))].into_iter().collect(),
+ ))
+ }
+}
+
+pub struct MySerialize;
+
+impl Serializer for MySerialize {
+ type Ok = Value;
+
+ type Error = Error;
+
+ type SerializeSeq = MySerializeSeq;
+
+ type SerializeTuple = MySerializeSeq;
+
+ type SerializeTupleStruct = MySerializeSeq;
+
+ type SerializeTupleVariant = MySerializeSeqVariant;
+
+ type SerializeMap = MySerializeMap;
+
+ type SerializeStruct = MySerializeStruct;
+
+ type SerializeStructVariant = MySerializeStructVariant;
+
+ fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Boolean(v))
+ }
+
+ fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Number(v as i64))
+ }
+
+ fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Number(v as i64))
+ }
+
+ fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Number(v as i64))
+ }
+
+ fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Number(v as i64))
+ }
+
+ fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Number(v as i64))
+ }
+
+ fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Number(v as i64))
+ }
+
+ fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Number(v as i64))
+ }
+
+ fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Number(v.try_into().map_err(|_| Error::BadNumber)?))
+ }
+
+ fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
+ todo!()
+ }
+
+ fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
+ todo!()
+ }
+
+ fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::String(v.to_string()))
+ }
+
+ fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::String(v.to_owned()))
+ }
+
+ fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
+ todo!()
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Null)
+ }
+
+ fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::Null)
+ }
+
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
+ self.serialize_unit()
+ }
+
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ ) -> Result<Self::Ok, Self::Error> {
+ Ok(Value::String(variant.to_string()))
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(
+ self,
+ _name: &'static str,
+ value: &T,
+ ) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ value: &T,
+ ) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::Serialize,
+ {
+ Ok(Value::Object(
+ vec![(variant.to_string(), value.serialize(self)?)]
+ .into_iter()
+ .collect(),
+ ))
+ }
+
+ fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+ Ok(MySerializeSeq(Vec::with_capacity(len.unwrap_or_default())))
+ }
+
+ fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
+ Ok(MySerializeSeq(Vec::with_capacity(len)))
+ }
+
+ fn serialize_tuple_struct(
+ self,
+ _name: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleStruct, Self::Error> {
+ Ok(MySerializeSeq(Vec::with_capacity(len)))
+ }
+
+ fn serialize_tuple_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleVariant, Self::Error> {
+ Ok(MySerializeSeqVariant(
+ variant.to_owned(),
+ MySerializeSeq(Vec::with_capacity(len)),
+ ))
+ }
+
+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
+ Ok(MySerializeMap(BTreeMap::new(), None))
+ }
+
+ fn serialize_struct(
+ self,
+ _name: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeStruct, Self::Error> {
+ Ok(MySerializeStruct(BTreeMap::new()))
+ }
+
+ fn serialize_struct_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeStructVariant, Self::Error> {
+ Ok(MySerializeStructVariant(
+ variant.to_owned(),
+ BTreeMap::new(),
+ ))
+ }
+}
crates/nixlike/src/to_string.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/nixlike/src/to_string.rs
@@ -0,0 +1,74 @@
+use crate::{Error, Value};
+
+fn write_nix_obj_key_buf(
+ k: &str,
+ v: &Value,
+ out: &mut String,
+ indent: &mut String,
+) -> Result<(), Error> {
+ use std::fmt::Write;
+ write!(out, "{}", k)?;
+ match v {
+ Value::Object(o) if o.len() == 1 => {
+ let (k, v) = o.iter().next().unwrap();
+ write!(out, ".")?;
+ write_nix_obj_key_buf(k, v, out, indent)?;
+ }
+ v => {
+ write!(out, " = ")?;
+ write_nix_buf(v, out, indent)?;
+ writeln!(out, ";")?;
+ }
+ }
+ Ok(())
+}
+
+fn write_nix_buf(value: &Value, out: &mut String, indent: &mut String) -> Result<(), Error> {
+ use std::fmt::Write;
+ match value {
+ Value::Null => write!(out, "null")?,
+ Value::Boolean(v) => write!(out, "{:?}", v)?,
+ Value::Number(n) => write!(out, "{}", n)?,
+ Value::String(s) => write!(out, "{:?}", s)?,
+ Value::Array(a) => {
+ if a.is_empty() {
+ write!(out, "[ ]")?;
+ } else {
+ writeln!(out, "[")?;
+ let old_len = indent.len();
+ indent.push_str(" ");
+ for item in a {
+ write!(out, "{}", indent)?;
+ write_nix_buf(item, out, indent)?;
+ writeln!(out)?;
+ }
+ indent.truncate(old_len);
+ write!(out, "{}]", indent)?;
+ }
+ }
+ Value::Object(obj) => {
+ if obj.is_empty() {
+ write!(out, "{{ }}")?;
+ } else {
+ writeln!(out, "{{")?;
+ let old_len = indent.len();
+ indent.push_str(" ");
+ for (k, v) in obj {
+ write!(out, "{}", indent)?;
+ write_nix_obj_key_buf(k, v, out, indent)?;
+ }
+ indent.truncate(old_len);
+ write!(out, "{}}}", indent)?;
+ }
+ }
+ };
+ Ok(())
+}
+
+pub fn write_nix(value: &Value) -> Result<String, Error> {
+ let mut out = String::new();
+ let mut indent = String::new();
+
+ write_nix_buf(value, &mut out, &mut indent)?;
+ Ok(out)
+}