--- 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"] --- /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" --- /dev/null +++ b/crates/nixlike/src/de_impl.rs @@ -0,0 +1,368 @@ +use std::{ + collections::BTreeMap, + convert::{TryFrom, TryInto}, +}; + +use serde::{ + de::{self, MapAccess, SeqAccess}, + Deserializer, +}; + +use crate::{Error, Value}; + +struct ObjectAccess { + iter: std::collections::btree_map::IntoIter, + value: Option, +} +impl ObjectAccess { + fn new(v: BTreeMap) -> Self { + Self { + iter: v.into_iter(), + value: None, + } + } +} + +impl<'de> MapAccess<'de> for ObjectAccess { + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + if let Some((k, v)) = self.iter.next() { + let _ = self.value.insert(v); + Ok(Some(seed.deserialize(Value::String(k))?)) + } else { + Ok(None) + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + seed.deserialize(self.value.take().unwrap()) + } +} + +struct ArrayAccess { + iter: std::vec::IntoIter, +} +impl ArrayAccess { + fn new(v: Vec) -> Self { + Self { + iter: v.into_iter(), + } + } +} + +impl<'de> SeqAccess<'de> for ArrayAccess { + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + if let Some(v) = self.iter.next() { + Ok(Some(seed.deserialize(v)?)) + } else { + Ok(None) + } + } +} + +impl Value { + fn parse_int>(&self) -> Result { + match self { + Value::Number(n) => Ok((*n).try_into().map_err(|_| Error::BadNumber)?), + _ => Err(Error::Expected("integer")), + } + } + fn parse_boolean(self) -> Result { + match self { + Value::Boolean(b) => Ok(b), + _ => Err(Error::Expected("boolean")), + } + } + pub fn parse_string(&self) -> Result<&str, Error> { + match self { + Value::String(s) => Ok(s), + _ => Err(Error::Expected("string")), + } + } + fn parse_char(self) -> Result { + match self { + Value::String(s) if s.chars().count() == 1 => Ok(s.chars().next().unwrap()), + _ => Err(Error::Expected("char")), + } + } + fn parse_array(self) -> Result, Error> { + match self { + Value::Array(s) => Ok(s), + _ => Err(Error::Expected("array")), + } + } + fn parse_object(self) -> Result, Error> { + match self { + Value::Object(s) => Ok(s), + _ => Err(Error::Expected("object")), + } + } + fn parse_null(self) -> Result<(), Error> { + match self { + Value::Null => Ok(()), + _ => Err(Error::Expected("null")), + } + } +} + +impl de::Error for Error { + fn custom(msg: T) -> Self + where + T: std::fmt::Display, + { + Self::Custom(format!("{}", msg)) + } +} + +impl<'de> Deserializer<'de> for Value { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + match self { + Value::Number(f) => visitor.visit_i64(f), + Value::String(s) => visitor.visit_str(&s), + Value::Boolean(b) => visitor.visit_bool(b), + Value::Object(o) => visitor.visit_map(ObjectAccess::new(o)), + Value::Array(a) => visitor.visit_seq(ArrayAccess::new(a)), + Value::Null => visitor.visit_none(), + } + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_bool(self.parse_boolean()?) + } + + fn deserialize_i8(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i8(self.parse_int()?) + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i16(self.parse_int()?) + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i32(self.parse_int()?) + } + + fn deserialize_i64(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i64(self.parse_int()?) + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u8(self.parse_int()?) + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u16(self.parse_int()?) + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u32(self.parse_int()?) + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u64(self.parse_int()?) + } + + fn deserialize_f32(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + todo!() + } + + fn deserialize_f64(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + todo!() + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_char(self.parse_char()?) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_str(self.parse_string()?) + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_string(self.parse_string()?.to_owned()) + } + + fn deserialize_bytes(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + todo!() + } + + fn deserialize_byte_buf(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + todo!() + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + match self { + Value::Null => visitor.visit_none(), + v => visitor.visit_some(v), + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + self.parse_null()?; + visitor.visit_unit() + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_seq(self.parse_array().map(ArrayAccess::new)?) + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_map(self.parse_object().map(ObjectAccess::new)?) + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_map(visitor) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + _visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + todo!() + } + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_any(visitor) + } +} --- /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), + #[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), + Array(Vec), + Null, +} + +peg::parser! { +pub grammar nixlike() for str { + rule number() -> i64 + = v:$(['0'..='9' | '+' | '-']+) {? v.parse().map_err(|_| "")} + 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 + = "{" _ + 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 + = "[" _ 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 { + let value = nixlike::root(s)?; + D::deserialize(value) +} + +pub fn parse_value<'de, D: Deserialize<'de>>(value: Value) -> Result { + D::deserialize(value) +} + +pub fn serialize_value_pretty(value: Value) -> Result { + to_string::write_nix(&value) +} + +pub fn serialize(value: S) -> Result { + 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); +} --- /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(msg: T) -> Self + where + T: std::fmt::Display, + { + Self::Custom(format!("{}", msg)) + } +} + +pub struct MySerializeSeq(Vec); + +impl SerializeSeq for MySerializeSeq { + type Ok = Value; + + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.0.push(value.serialize(MySerialize)?); + Ok(()) + } + + fn end(self) -> Result { + Ok(Value::Array(self.0)) + } +} +impl SerializeTuple for MySerializeSeq { + type Ok = Value; + + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.0.push(value.serialize(MySerialize)?); + Ok(()) + } + + fn end(self) -> Result { + Ok(Value::Array(self.0)) + } +} +impl SerializeTupleStruct for MySerializeSeq { + type Ok = Value; + + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.0.push(value.serialize(MySerialize)?); + Ok(()) + } + + fn end(self) -> Result { + Ok(Value::Array(self.0)) + } +} + +pub struct MySerializeSeqVariant(String, MySerializeSeq); + +impl SerializeTupleVariant for MySerializeSeqVariant { + type Ok = Value; + + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.1.serialize_field(value) + } + + fn end(self) -> Result { + Ok(Value::Object( + vec![(self.0, Value::Array(self.1 .0))] + .into_iter() + .collect(), + )) + } +} + +pub struct MySerializeMap(BTreeMap, Option); + +impl SerializeMap for MySerializeMap { + type Ok = Value; + + type Error = Error; + + fn serialize_key(&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(&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 { + Ok(Value::Object(self.0)) + } +} + +pub struct MySerializeStruct(BTreeMap); + +impl SerializeStruct for MySerializeStruct { + type Ok = Value; + + type Error = Error; + + fn serialize_field(&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 { + Ok(Value::Object(self.0)) + } +} + +pub struct MySerializeStructVariant(String, BTreeMap); + +impl SerializeStructVariant for MySerializeStructVariant { + type Ok = Value; + + type Error = Error; + + fn serialize_field( + &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 { + 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 { + Ok(Value::Boolean(v)) + } + + fn serialize_i8(self, v: i8) -> Result { + Ok(Value::Number(v as i64)) + } + + fn serialize_i16(self, v: i16) -> Result { + Ok(Value::Number(v as i64)) + } + + fn serialize_i32(self, v: i32) -> Result { + Ok(Value::Number(v as i64)) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(Value::Number(v as i64)) + } + + fn serialize_u8(self, v: u8) -> Result { + Ok(Value::Number(v as i64)) + } + + fn serialize_u16(self, v: u16) -> Result { + Ok(Value::Number(v as i64)) + } + + fn serialize_u32(self, v: u32) -> Result { + Ok(Value::Number(v as i64)) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(Value::Number(v.try_into().map_err(|_| Error::BadNumber)?)) + } + + fn serialize_f32(self, _v: f32) -> Result { + todo!() + } + + fn serialize_f64(self, _v: f64) -> Result { + todo!() + } + + fn serialize_char(self, v: char) -> Result { + Ok(Value::String(v.to_string())) + } + + fn serialize_str(self, v: &str) -> Result { + Ok(Value::String(v.to_owned())) + } + + fn serialize_bytes(self, _v: &[u8]) -> Result { + todo!() + } + + fn serialize_none(self) -> Result { + Ok(Value::Null) + } + + fn serialize_some(self, value: &T) -> Result + where + T: serde::Serialize, + { + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + Ok(Value::Null) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + Ok(Value::String(variant.to_string())) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result + where + T: serde::Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: serde::Serialize, + { + Ok(Value::Object( + vec![(variant.to_string(), value.serialize(self)?)] + .into_iter() + .collect(), + )) + } + + fn serialize_seq(self, len: Option) -> Result { + Ok(MySerializeSeq(Vec::with_capacity(len.unwrap_or_default()))) + } + + fn serialize_tuple(self, len: usize) -> Result { + Ok(MySerializeSeq(Vec::with_capacity(len))) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + Ok(MySerializeSeq(Vec::with_capacity(len))) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(MySerializeSeqVariant( + variant.to_owned(), + MySerializeSeq(Vec::with_capacity(len)), + )) + } + + fn serialize_map(self, _len: Option) -> Result { + Ok(MySerializeMap(BTreeMap::new(), None)) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(MySerializeStruct(BTreeMap::new())) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + Ok(MySerializeStructVariant( + variant.to_owned(), + BTreeMap::new(), + )) + } +} --- /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 { + let mut out = String::new(); + let mut indent = String::new(); + + write_nix_buf(value, &mut out, &mut indent)?; + Ok(out) +}