depot/third_party/tvl/users/Profpatsch/cdb.nix
Default email a291c8690a Project import generated by Copybara.
GitOrigin-RevId: e6e19f3d81a982a62e1bba08f0b4f7fdc21b4ea0
2022-05-19 16:39:52 +02:00

93 lines
3.5 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ depot, pkgs, ... }:
let
cdbListToNetencode = depot.nix.writers.rustSimple
{
name = "cdb-list-to-netencode";
dependencies = [
depot.third_party.rust-crates.nom
depot.users.Profpatsch.execline.exec-helpers
depot.users.Profpatsch.netencode.netencode-rs
];
} ''
extern crate nom;
extern crate exec_helpers;
extern crate netencode;
use std::collections::HashMap;
use std::io::BufRead;
use nom::{IResult};
use nom::sequence::{tuple};
use nom::bytes::complete::{tag, take};
use nom::character::complete::{digit1, char};
use nom::error::{context, ErrorKind, ParseError};
use nom::combinator::{map_res};
use netencode::{T, Tag};
fn usize_t(s: &[u8]) -> IResult<&[u8], usize> {
context(
"usize",
map_res(
map_res(digit1, |n| std::str::from_utf8(n)),
|s| s.parse::<usize>())
)(s)
}
fn parse_cdb_record(s: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
let (s, (_, klen, _, vlen, _)) = tuple((
char('+'),
usize_t,
char(','),
usize_t,
char(':')
))(s)?;
let (s, (key, _, val)) = tuple((
take(klen),
tag("->"),
take(vlen),
))(s)?;
Ok((s, (key, val)))
}
fn main() {
let mut res = vec![];
let stdin = std::io::stdin();
let mut lines = stdin.lock().split(b'\n');
loop {
match lines.next() {
None => exec_helpers::die_user_error("cdb-list-to-netencode", "stdin ended but we didnt receive the empty line to signify the end of the cdbdump input!"),
Some(Err(err)) => exec_helpers::die_temporary("cdb-list-to-netencode", format!("could not read from stdin: {}", err)),
Some(Ok(line)) =>
if &line == b"" {
// the cdbdump input ends after an empty line (double \n)
break;
} else {
match parse_cdb_record(&line) {
Ok((b"", (key, val))) => {
let (key, val) = match
std::str::from_utf8(key)
.and_then(|k| std::str::from_utf8(val).map(|v| (k, v))) {
Ok((key, val)) => (key.to_owned(), val.to_owned()),
Err(err) => exec_helpers::die_user_error("cdb-list-to-netencode", format!("cannot decode line {:?}, we only support utf8-encoded key/values pairs for now: {}", String::from_utf8_lossy(&line), err)),
};
let _ = res.push((key, val));
},
Ok((rest, _)) => exec_helpers::die_user_error("cdb-list-to-netencode", format!("could not decode record line {:?}, had some trailing bytes", String::from_utf8_lossy(&line))),
Err(err) => exec_helpers::die_user_error("cdb-list-to-netencode", format!("could not decode record line {:?}: {:?}", String::from_utf8_lossy(&line), err)),
}
}
}
}
let list = T::List(res.into_iter().map(
|(k, v)| T::Record(vec![(String::from("key"), T::Text(k)), (String::from("val"), T::Text(v))].into_iter().collect())
).collect());
netencode::encode(&mut std::io::stdout(), &list.to_u());
}
'';
in
{
inherit
cdbListToNetencode
;
}