1234use linked_hash_map::LinkedHashMap;5use peg::str::LineCol;6use se_impl::MySerialize;7use serde::{Deserialize, Serialize};89mod de_impl;10mod se_impl;11mod to_string;1213#[derive(thiserror::Error, Debug)]14pub enum Error {15 #[error("bad number")]16 BadNumber,17 #[error("expected {0}")]18 Expected(&'static str),19 #[error("parse error")]20 ParseError(#[from] peg::error::ParseError<LineCol>),21 #[error("{0}")]22 Custom(String),23 #[error("io: {0}")]24 Io(#[from] std::io::Error),25 #[error("fmt: {0}")]26 Fmt(#[from] std::fmt::Error),27}2829#[derive(Debug)]30pub enum Value {31 Number(i64),32 String(String),33 Boolean(bool),34 Object(LinkedHashMap<String, Value>),35 Array(Vec<Value>),36 Null,37}3839peg::parser! {40pub grammar nixlike() for str {41 rule number() -> i6442 = quiet! { v:$(['0'..='9' | '+' | '-']+) {? v.parse().map_err(|_| "<number>")} } / expected!("<number>")43 rule string_char() -> &'input str44 = "\\\"" { "\"" }45 / "\\\\" { "\\" }46 / "\\n" { "\n" }47 / "\\t" { "\t" }48 / "\\r" { "\r" }49 / "\\$" { "$" }50 / c:$([_]) { c }51 rule string() -> String52 = quiet! { "\"" v:(!"\"" c:string_char() {c})* "\"" { v.into_iter().collect() } } / expected!("<string>")53 rule boolean() -> bool54 = quiet! { "true" {true}55 / "false" {false} } / expected!("<boolean>")56 rule indent() -> String57 = quiet! {58 s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() }59 / "\"" s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-' | '.']+) "\"" { s.to_owned() }60 } / expected!("<identifier>")61 rule object() -> LinkedHashMap<String, Value>62 = "{" _63 e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*64 "}" {?65 let mut out = LinkedHashMap::new();66 for (k, v) in e {67 let mut map = &mut out;68 for v in k.iter().take(k.len() - 1) {69 map = match map.entry(v.clone()).or_insert_with(|| Value::Object(Default::default())) {70 Value::Object(v) => v,71 _ => return Err("expected object"),72 }73 }7475 let key = k.into_iter().last().unwrap();76 if map.contains_key(&key) {77 return Err("can't override object");78 }79 map.insert(key, v);80 }81 Ok(out)82 }8384 rule array() -> Vec<Value>85 = "[" _ v:value()**_ _ "]" {v}8687 rule value() -> Value88 = o:object() { Value::Object(o) }89 / a:array() { Value::Array(a) }90 / s:string() { Value::String(s) }91 / "null" { Value::Null }92 / b:boolean() { Value::Boolean(b) }93 / n:number() { Value::Number(n) }9495 pub rule root() -> Value96 = _ v:value() _ { v }9798 rule _()99 = ( quiet!{ [' ' | '\t' | '\n']+ }100 / "#" (!['\n'] [_])* "\n" )*101}102}103104pub fn parse_str<'de, D: Deserialize<'de>>(s: &str) -> Result<D, Error> {105 let value = nixlike::root(s)?;106 D::deserialize(value)107}108109pub fn parse_value<'de, D: Deserialize<'de>>(value: Value) -> Result<D, Error> {110 D::deserialize(value)111}112113pub fn serialize_value_pretty(value: Value) -> String {114 to_string::write_nix(&value)115}116117pub fn serialize<S: Serialize>(value: S) -> Result<String, Error> {118 let value: Value = value.serialize(MySerialize)?;119 Ok(serialize_value_pretty(value))120}121122#[test]123fn test() {124 assert_eq!(serialize("Hello\nworld").unwrap(), "\"Hello\\nworld\"\n");125}126pub fn format_nix(value: &String) -> String {127 let (_, out) = alejandra::format::in_memory("".to_owned(), value.to_owned());128 out129}