git.delta.rocks / jrsonnet / refs/commits / 4daa40be7e69

difftreelog

source

crates/nixlike/src/lib.rs3.0 KiBsourcehistory
1use linked_hash_map::LinkedHashMap;2use peg::str::LineCol;3use se_impl::MySerialize;4use serde::{Deserialize, Serialize};56mod de_impl;7mod se_impl;8mod to_string;910#[derive(thiserror::Error, Debug)]11pub enum Error {12	#[error("bad number")]13	BadNumber,14	#[error("expected {0}")]15	Expected(&'static str),16	#[error("parse error")]17	ParseError(#[from] peg::error::ParseError<LineCol>),18	#[error("{0}")]19	Custom(String),20	#[error("io: {0}")]21	Io(#[from] std::io::Error),22	#[error("fmt: {0}")]23	Fmt(#[from] std::fmt::Error),24}2526#[derive(Debug)]27pub enum Value {28	Number(i64),29	String(String),30	Boolean(bool),31	Object(LinkedHashMap<String, Value>),32	Array(Vec<Value>),33	Null,34}3536peg::parser! {37pub grammar nixlike() for str {38	rule number() -> i6439		= quiet! { v:$(['0'..='9' | '+' | '-']+) {? v.parse().map_err(|_| "<number>")} } / expected!("<number>")40	rule string_char() -> &'input str41		= "\\\"" { "\"" }42		/ "\\\\" { "\\" }43		/ "\\n" { "\n" }44		/ "\\t" { "\t" }45		/ "\\r" { "\r" }46		/ "\\$" { "$" }47		/ c:$([_]) { c }48	rule string() -> String49		= quiet! { "\"" v:(!"\"" c:string_char() {c})* "\"" { v.into_iter().collect() } } / expected!("<string>")50	rule boolean() -> bool51		= quiet! { "true" {true}52		/ "false" {false} } / expected!("<boolean>")53	rule indent() -> String54		= quiet! {55			s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() }56			/ "\"" s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-' | '.']+) "\"" { s.to_owned() }57		} / expected!("<identifier>")58	rule object() -> LinkedHashMap<String, Value>59		= "{" _60			e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*61		"}" {?62			let mut out = LinkedHashMap::new();63			for (k, v) in e {64				let mut map = &mut out;65				for v in k.iter().take(k.len() - 1) {66					map = match map.entry(v.clone()).or_insert_with(|| Value::Object(Default::default())) {67						Value::Object(v) => v,68						_ => return Err("expected object"),69					}70				}7172				let key = k.into_iter().last().unwrap();73				if map.contains_key(&key) {74					return Err("can't override object");75				}76				map.insert(key, v);77			}78			Ok(out)79		}8081	rule array() -> Vec<Value>82		= "[" _ v:value()**_ _ "]" {v}8384	rule value() -> Value85		= o:object() { Value::Object(o) }86		/ a:array() { Value::Array(a) }87		/ s:string() { Value::String(s) }88		/ "null" { Value::Null }89		/ b:boolean() { Value::Boolean(b) }90		/ n:number() { Value::Number(n) }9192	pub rule root() -> Value93		= _ v:value() _ { v }9495	rule _()96		= ( quiet!{ [' ' | '\t' | '\n']+ }97		/ "#" (!['\n'] [_])* "\n" )*98}99}100101pub fn parse_str<'de, D: Deserialize<'de>>(s: &str) -> Result<D, Error> {102	let value = nixlike::root(s)?;103	D::deserialize(value)104}105106pub fn parse_value<'de, D: Deserialize<'de>>(value: Value) -> Result<D, Error> {107	D::deserialize(value)108}109110pub fn serialize_value_pretty(value: Value) -> String {111	to_string::write_nix(&value)112}113114pub fn serialize<S: Serialize>(value: S) -> Result<String, Error> {115	let value: Value = value.serialize(MySerialize)?;116	Ok(serialize_value_pretty(value))117}118119#[test]120fn test() {121	assert_eq!(serialize("Hello\nworld").unwrap(), "\"Hello\\nworld\"");122}