From 27a73171cf97c24c7785787eb7661405334329de Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Sat, 2 Jan 2021 17:08:27 +0100 Subject: feat(Profpatsch/netencode): add netencode-mustache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A little executable, combining the netencode and mustache libraries to make easy templating from the command line possible. Combined with the nix netencode generators, it’s now trivial to populate a mustache template with (nearly) arbitrary data. Yay. Change-Id: I5b892c38fbc33dd826a26174dd9567f0b72e6322 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2320 Reviewed-by: Profpatsch Tested-by: BuildkiteCI --- users/Profpatsch/netencode/default.nix | 51 +++++++++++++++++ users/Profpatsch/netencode/netencode-mustache.rs | 71 ++++++++++++++++++++++++ users/Profpatsch/netencode/netencode.rs | 2 +- 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 users/Profpatsch/netencode/netencode-mustache.rs diff --git a/users/Profpatsch/netencode/default.nix b/users/Profpatsch/netencode/default.nix index 4a06cd700e..80ff73aff5 100644 --- a/users/Profpatsch/netencode/default.nix +++ b/users/Profpatsch/netencode/default.nix @@ -40,9 +40,60 @@ let netencode-rs = netencode-rs-common false; + gen = import ./netencode.nix; + + cfg-if = pkgs.buildRustCrate { + pname = "cfg-if"; + version = "1.0.0"; + crateName = "cfg-if"; + sha256 = "1fzidq152hnxhg4lj6r2gv4jpnn8yivp27z6q6xy7w6v0dp6bai9"; + }; + + log = pkgs.buildRustCrate { + pname = "log"; + version = "0.4.11"; + crateName = "log"; + sha256 = "0m6xhqxsps5mgd7r91g5mqkndbh8zbjd58p7w75r330zl4n40l07"; + dependencies = [ cfg-if ]; + }; + + serde_derive = pkgs.buildRustCrate { + pname = "serde"; + version = "1.0.118"; + crateName = "serde"; + sha256 = "1kbi2csphq8m4z77fpd6v8jih10j7867wniqnlxnk308mrnxi4r2"; + }; + + serde = pkgs.buildRustCrate { + pname = "serde"; + version = "1.0.118"; + crateName = "serde"; + sha256 = "1kbi2csphq8m4z77fpd6v8jih10j7867wniqnlxnk308mrnxi4r2"; + features = [ "std" ]; + }; + + mustache = pkgs.buildRustCrate { + pname = "mustache"; + version = "0.9.0"; + crateName = "mustache"; + sha256 = "1zgl8l15i19lzp90icgwyi6zqdd31b9vm8w129f41d1zd0hs7ayq"; + dependencies = [ log serde ]; + }; + + netencode-mustache = imports.writers.rustSimple { + name = "netencode_mustache"; + dependencies = [ + netencode-rs + mustache + ]; + } (builtins.readFile ./netencode-mustache.rs); + + in { inherit netencode-rs netencode-rs-tests + netencode-mustache + gen ; } diff --git a/users/Profpatsch/netencode/netencode-mustache.rs b/users/Profpatsch/netencode/netencode-mustache.rs new file mode 100644 index 0000000000..796c7a68d4 --- /dev/null +++ b/users/Profpatsch/netencode/netencode-mustache.rs @@ -0,0 +1,71 @@ +extern crate netencode; +extern crate mustache; + +use mustache::{Data}; +use netencode::{T}; +use std::collections::HashMap; +use std::os::unix::ffi::{OsStrExt}; +use std::io::{Read}; + +fn arglib_netencode(env: Option<&std::ffi::OsStr>) -> Result { + let env = match env { + None => std::ffi::OsStr::from_bytes("ARGLIB_NETENCODE".as_bytes()), + Some(a) => a + }; + match std::env::var_os(env) { + None => Err(format!("could not read args, envvar {} not set", env.to_string_lossy())), + // TODO: good error handling for the different parser errors + Some(soup) => match netencode::parse::t_t(soup.as_bytes()) { + Ok((remainder, t)) => match remainder.is_empty() { + true => Ok(t), + false => Err(format!("there was some unparsed bytes remaining: {:?}", remainder)) + }, + Err(err) => Err(format!("parsing error: {:?}", err)) + } + } +} + + +fn netencode_to_mustache_data_dwim(t: T) -> Data { + match t { + // TODO: good idea? + T::Unit => Data::Null, + T::N1(b) => Data::Bool(b), + T::N3(u) => Data::String(u.to_string()), + T::N6(u) => Data::String(u.to_string()), + T::N7(u) => Data::String(u.to_string()), + T::I3(i) => Data::String(i.to_string()), + T::I6(i) => Data::String(i.to_string()), + T::I7(i) => Data::String(i.to_string()), + T::Text(s) => Data::String(s), + T::Binary(b) => unimplemented!(), + T::Sum(tag) => unimplemented!(), + T::Record(xs) => Data::Map( + xs.into_iter() + .map(|(key, val)| (key, netencode_to_mustache_data_dwim(*val))) + .collect::>() + ), + T::List(xs) => Data::Vec( + xs.into_iter() + .map(|x| netencode_to_mustache_data_dwim(x)) + .collect::>() + ), + } +} + +pub fn from_stdin() -> () { + let data = netencode_to_mustache_data_dwim( + arglib_netencode(None).unwrap() + ); + let mut stdin = String::new(); + std::io::stdin().read_to_string(&mut stdin).unwrap(); + mustache::compile_str(&stdin) + .and_then(|templ| templ.render_data( + &mut std::io::stdout(), + &data + )).unwrap() +} + +pub fn main() { + from_stdin() +} diff --git a/users/Profpatsch/netencode/netencode.rs b/users/Profpatsch/netencode/netencode.rs index 57b0a09493..9c999a7cbb 100644 --- a/users/Profpatsch/netencode/netencode.rs +++ b/users/Profpatsch/netencode/netencode.rs @@ -338,7 +338,7 @@ pub mod parse { ))(s) } - fn t_t(s: &[u8]) -> IResult<&[u8], T> { + pub fn t_t(s: &[u8]) -> IResult<&[u8], T> { alt(( text, binary(), -- cgit 1.4.1