diff options
author | Vincent Ambo <mail@tazj.in> | 2022-02-07T15·49+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-02-08T12·06+0000 |
commit | 3d8ee620875085ae7e8d7ef31f4f8e3738cfdca1 (patch) | |
tree | c4597319495abbb82c9753791fbde11bfdb644f0 /users/Profpatsch | |
parent | 3318982f81c01b570b7021fd9f71aa2bfe192271 (diff) |
style(rust): Format all Rust code with rustfmt r/3791
Change-Id: Iab7e00cc26a4f9727d3ab98691ef379921a33052 Reviewed-on: https://cl.tvl.fyi/c/depot/+/5240 Tested-by: BuildkiteCI Reviewed-by: kanepyork <rikingcoding@gmail.com> Reviewed-by: Profpatsch <mail@profpatsch.de> Reviewed-by: grfn <grfn@gws.fyi> Reviewed-by: tazjin <tazjin@tvl.su>
Diffstat (limited to 'users/Profpatsch')
-rw-r--r-- | users/Profpatsch/execline/exec_helpers.rs | 84 | ||||
-rw-r--r-- | users/Profpatsch/git-db/git-db.rs | 39 | ||||
-rw-r--r-- | users/Profpatsch/imap-idle.rs | 40 | ||||
-rw-r--r-- | users/Profpatsch/netencode/netencode-mustache.rs | 29 | ||||
-rw-r--r-- | users/Profpatsch/netencode/netencode.rs | 519 | ||||
-rw-r--r-- | users/Profpatsch/netencode/pretty.rs | 73 | ||||
-rw-r--r-- | users/Profpatsch/read-http.rs | 152 |
7 files changed, 547 insertions, 389 deletions
diff --git a/users/Profpatsch/execline/exec_helpers.rs b/users/Profpatsch/execline/exec_helpers.rs index b9e1f5797386..a57cbca35391 100644 --- a/users/Profpatsch/execline/exec_helpers.rs +++ b/users/Profpatsch/execline/exec_helpers.rs @@ -1,13 +1,16 @@ -use std::os::unix::process::CommandExt; use std::ffi::OsStr; -use std::os::unix::ffi::{OsStringExt, OsStrExt}; +use std::os::unix::ffi::{OsStrExt, OsStringExt}; +use std::os::unix::process::CommandExt; pub fn no_args(current_prog_name: &str) -> () { let mut args = std::env::args_os(); // remove argv[0] let _ = args.nth(0); if args.len() > 0 { - die_user_error(current_prog_name, format!("Expected no arguments, got {:?}", args.collect::<Vec<_>>())) + die_user_error( + current_prog_name, + format!("Expected no arguments, got {:?}", args.collect::<Vec<_>>()), + ) } } @@ -16,31 +19,46 @@ pub fn args(current_prog_name: &str, no_of_positional_args: usize) -> Vec<Vec<u8 // remove argv[0] let _ = args.nth(0); if args.len() != no_of_positional_args { - die_user_error(current_prog_name, format!("Expected {} arguments, got {}, namely {:?}", no_of_positional_args, args.len(), args.collect::<Vec<_>>())) + die_user_error( + current_prog_name, + format!( + "Expected {} arguments, got {}, namely {:?}", + no_of_positional_args, + args.len(), + args.collect::<Vec<_>>() + ), + ) } args.map(|arg| arg.into_vec()).collect() } -pub fn args_for_exec(current_prog_name: &str, no_of_positional_args: usize) -> (Vec<Vec<u8>>, Vec<Vec<u8>>) { +pub fn args_for_exec( + current_prog_name: &str, + no_of_positional_args: usize, +) -> (Vec<Vec<u8>>, Vec<Vec<u8>>) { let mut args = std::env::args_os(); // remove argv[0] let _ = args.nth(0); let mut args = args.map(|arg| arg.into_vec()); let mut pos_args = vec![]; // get positional args - for i in 1..no_of_positional_args+1 { - pos_args.push( - args.nth(0).expect( - &format!("{}: expects {} positional args, only got {}", current_prog_name, no_of_positional_args, i)) - ); + for i in 1..no_of_positional_args + 1 { + pos_args.push(args.nth(0).expect(&format!( + "{}: expects {} positional args, only got {}", + current_prog_name, no_of_positional_args, i + ))); } // prog... is the rest of the iterator - let prog : Vec<Vec<u8>> = args.collect(); + let prog: Vec<Vec<u8>> = args.collect(); (pos_args, prog) } -pub fn exec_into_args<'a, 'b, Args, Arg, Env, Key, Val>(current_prog_name: &str, args: Args, env_additions: Env) -> ! - where +pub fn exec_into_args<'a, 'b, Args, Arg, Env, Key, Val>( + current_prog_name: &str, + args: Args, + env_additions: Env, +) -> ! +where Args: IntoIterator<Item = Arg>, Arg: AsRef<[u8]>, Env: IntoIterator<Item = (Key, Val)>, @@ -50,27 +68,40 @@ pub fn exec_into_args<'a, 'b, Args, Arg, Env, Key, Val>(current_prog_name: &str, // TODO: is this possible without collecting into a Vec first, just leaving it an IntoIterator? let args = args.into_iter().collect::<Vec<Arg>>(); let mut args = args.iter().map(|v| OsStr::from_bytes(v.as_ref())); - let prog = args.nth(0).expect(&format!("{}: first argument must be an executable", current_prog_name)); + let prog = args.nth(0).expect(&format!( + "{}: first argument must be an executable", + current_prog_name + )); // TODO: same here let env = env_additions.into_iter().collect::<Vec<(Key, Val)>>(); - let env = env.iter().map(|(k,v)| (OsStr::from_bytes(k.as_ref()), OsStr::from_bytes(v.as_ref()))); + let env = env + .iter() + .map(|(k, v)| (OsStr::from_bytes(k.as_ref()), OsStr::from_bytes(v.as_ref()))); let err = std::process::Command::new(prog).args(args).envs(env).exec(); - die_missing_executable(current_prog_name, format!("exec failed: {}, while trying to execing into {:?}", err, prog)); + die_missing_executable( + current_prog_name, + format!( + "exec failed: {}, while trying to execing into {:?}", + err, prog + ), + ); } /// Exit 1 to signify a generic expected error /// (e.g. something that sometimes just goes wrong, like a nix build). pub fn die_expected_error<S>(current_prog_name: &str, msg: S) -> ! -where S: AsRef<str> +where + S: AsRef<str>, { - die_with(1, current_prog_name, msg) + die_with(1, current_prog_name, msg) } /// Exit 100 to signify a user error (“the user is holding it wrong”). /// This is a permanent error, if the program is executed the same way /// it should crash with 100 again. pub fn die_user_error<S>(current_prog_name: &str, msg: S) -> ! -where S: AsRef<str> +where + S: AsRef<str>, { die_with(100, current_prog_name, msg) } @@ -78,14 +109,16 @@ where S: AsRef<str> /// Exit 101 to signify an unexpected crash (failing assertion or panic). /// This is the same exit code that `panic!()` emits. pub fn die_panic<S>(current_prog_name: &str, msg: S) -> ! -where S: AsRef<str> +where + S: AsRef<str>, { die_with(101, current_prog_name, msg) } /// Exit 111 to signify a temporary error (such as resource exhaustion) pub fn die_temporary<S>(current_prog_name: &str, msg: S) -> ! -where S: AsRef<str> +where + S: AsRef<str>, { die_with(111, current_prog_name, msg) } @@ -93,20 +126,23 @@ where S: AsRef<str> /// Exit 126 to signify an environment problem /// (the user has set up stuff incorrectly so the program cannot work) pub fn die_environment_problem<S>(current_prog_name: &str, msg: S) -> ! -where S: AsRef<str> +where + S: AsRef<str>, { die_with(126, current_prog_name, msg) } /// Exit 127 to signify a missing executable. pub fn die_missing_executable<S>(current_prog_name: &str, msg: S) -> ! -where S: AsRef<str> +where + S: AsRef<str>, { die_with(127, current_prog_name, msg) } fn die_with<S>(status: i32, current_prog_name: &str, msg: S) -> ! - where S: AsRef<str> +where + S: AsRef<str>, { eprintln!("{}: {}", current_prog_name, msg.as_ref()); std::process::exit(status) diff --git a/users/Profpatsch/git-db/git-db.rs b/users/Profpatsch/git-db/git-db.rs index 5c6bb1f85646..c8019bf03661 100644 --- a/users/Profpatsch/git-db/git-db.rs +++ b/users/Profpatsch/git-db/git-db.rs @@ -2,7 +2,7 @@ extern crate git2; use std::os::unix::ffi::OsStrExt; use std::path::PathBuf; -const DEFAULT_BRANCH : &str = "refs/heads/main"; +const DEFAULT_BRANCH: &str = "refs/heads/main"; fn main() { let git_db_dir = std::env::var_os("GIT_DB_DIR").expect("set GIT_DB_DIR"); @@ -16,8 +16,12 @@ fn main() { .bare(true) .mkpath(true) .description("git-db database") - .initial_head(DEFAULT_BRANCH) - ).expect(&format!("unable to create or open bare git repo at {}", &git_db.display())); + .initial_head(DEFAULT_BRANCH), + ) + .expect(&format!( + "unable to create or open bare git repo at {}", + &git_db.display() + )); let mut index = repo.index().expect("cannot get the git index file"); eprintln!("{:#?}", index.version()); @@ -34,8 +38,9 @@ fn main() { let data = "hi, it’s me".as_bytes(); - index.add_frombuffer( - &git2::IndexEntry { + index + .add_frombuffer( + &git2::IndexEntry { mtime: now_git_time, ctime: now_git_time, // don’t make sense @@ -50,25 +55,26 @@ fn main() { flags_extended: 0, path: "hi.txt".as_bytes().to_owned(), }, - data - ).expect("could not add data to index"); + data, + ) + .expect("could not add data to index"); let oid = index.write_tree().expect("could not write index tree"); - let to_add_tree = repo.find_tree(oid) + let to_add_tree = repo + .find_tree(oid) .expect("we just created this tree, where did it go?"); let parent_commits = match repo.find_reference(DEFAULT_BRANCH) { - Ok(ref_) => vec![ - ref_ - .peel_to_commit() - .expect(&format!("reference {} does not point to a commit", DEFAULT_BRANCH)) - ], + Ok(ref_) => vec![ref_.peel_to_commit().expect(&format!( + "reference {} does not point to a commit", + DEFAULT_BRANCH + ))], Err(err) => match err.code() { // no commit exists yet git2::ErrorCode::NotFound => vec![], _ => panic!("could not read latest commit from {}", DEFAULT_BRANCH), - } + }, }; repo.commit( Some(DEFAULT_BRANCH), @@ -79,7 +85,6 @@ fn main() { I wonder if it supports extended commit descriptions?\n", &to_add_tree, &parent_commits.iter().collect::<Vec<_>>()[..], - ).expect("could not commit the index we just wrote"); - - + ) + .expect("could not commit the index we just wrote"); } diff --git a/users/Profpatsch/imap-idle.rs b/users/Profpatsch/imap-idle.rs index 9dce736d0d8a..937847b8798a 100644 --- a/users/Profpatsch/imap-idle.rs +++ b/users/Profpatsch/imap-idle.rs @@ -1,16 +1,16 @@ extern crate exec_helpers; // extern crate arglib_netencode; // extern crate netencode; -extern crate imap; extern crate epoll; +extern crate imap; // use netencode::dec; +use imap::extensions::idle::SetReadTimeout; use std::convert::TryFrom; -use std::io::{Read, Write}; use std::fs::File; -use std::os::unix::io::{FromRawFd, AsRawFd, RawFd}; +use std::io::{Read, Write}; +use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::time::Duration; -use imap::extensions::idle::SetReadTimeout; /// Implements an UCSPI client that wraps fd 6 & 7 /// and implements Write and Read with a timeout. @@ -33,7 +33,7 @@ impl UcspiClient { read: File::from_raw_fd(6), read_epoll_fd, read_timeout: None, - write: File::from_raw_fd(7) + write: File::from_raw_fd(7), }) } } @@ -54,21 +54,23 @@ impl SetReadTimeout for UcspiClient { impl Read for UcspiClient { // TODO: test the epoll code with a short timeout fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { - const NO_DATA : u64 = 0; + const NO_DATA: u64 = 0; // in order to implement the read_timeout, // we use epoll to wait for either data or time out epoll::ctl( self.read_epoll_fd, epoll::ControlOptions::EPOLL_CTL_ADD, self.read.as_raw_fd(), - epoll::Event::new(epoll::Events::EPOLLIN, NO_DATA) + epoll::Event::new(epoll::Events::EPOLLIN, NO_DATA), )?; let UNUSED = epoll::Event::new(epoll::Events::EPOLLIN, NO_DATA); let wait = epoll::wait( self.read_epoll_fd, match self.read_timeout { - Some(duration) => i32::try_from(duration.as_millis()).expect("duration too big for epoll"), - None => -1 // infinite + Some(duration) => { + i32::try_from(duration.as_millis()).expect("duration too big for epoll") + } + None => -1, // infinite }, // event that was generated; but we don’t care &mut vec![UNUSED; 1][..], @@ -79,11 +81,14 @@ impl Read for UcspiClient { self.read_epoll_fd, epoll::ControlOptions::EPOLL_CTL_DEL, self.read.as_raw_fd(), - UNUSED + UNUSED, )?; match wait { // timeout happened (0 events) - Ok(0) => Err(std::io::Error::new(std::io::ErrorKind::TimedOut, "ucspi read timeout")), + Ok(0) => Err(std::io::Error::new( + std::io::ErrorKind::TimedOut, + "ucspi read timeout", + )), // its ready for reading, we can read Ok(_) => self.read.read(buf), // error @@ -110,18 +115,21 @@ fn main() { let username = std::env::var("IMAP_USERNAME").expect("username"); let password = std::env::var("IMAP_PASSWORD").expect("password"); - let net = unsafe { - UcspiClient::new_from_6_and_7().expect("no ucspi client for you") - }; + let net = unsafe { UcspiClient::new_from_6_and_7().expect("no ucspi client for you") }; let client = imap::Client::new(net); - let mut session = client.login(username, password).map_err(|(err, _)| err).expect("unable to login"); + let mut session = client + .login(username, password) + .map_err(|(err, _)| err) + .expect("unable to login"); eprintln!("{:#?}", session); let list = session.list(None, Some("*")); eprintln!("{:#?}", list); let mailbox = session.examine("INBOX"); eprintln!("{:#?}", mailbox); fn now() -> String { - String::from_utf8_lossy(&std::process::Command::new("date").output().unwrap().stdout).trim_right().to_string() + String::from_utf8_lossy(&std::process::Command::new("date").output().unwrap().stdout) + .trim_right() + .to_string() } loop { eprintln!("{}: idling on INBOX", now()); diff --git a/users/Profpatsch/netencode/netencode-mustache.rs b/users/Profpatsch/netencode/netencode-mustache.rs index ee7bafed2250..73ed5be1ded2 100644 --- a/users/Profpatsch/netencode/netencode-mustache.rs +++ b/users/Profpatsch/netencode/netencode-mustache.rs @@ -1,12 +1,12 @@ -extern crate netencode; -extern crate mustache; extern crate arglib_netencode; +extern crate mustache; +extern crate netencode; -use mustache::{Data}; -use netencode::{T}; +use mustache::Data; +use netencode::T; use std::collections::HashMap; -use std::os::unix::ffi::{OsStrExt}; -use std::io::{Read}; +use std::io::Read; +use std::os::unix::ffi::OsStrExt; fn netencode_to_mustache_data_dwim(t: T) -> Data { match t { @@ -25,27 +25,26 @@ fn netencode_to_mustache_data_dwim(t: T) -> Data { T::Record(xs) => Data::Map( xs.into_iter() .map(|(key, val)| (key, netencode_to_mustache_data_dwim(val))) - .collect::<HashMap<_,_>>() + .collect::<HashMap<_, _>>(), ), T::List(xs) => Data::Vec( xs.into_iter() .map(|x| netencode_to_mustache_data_dwim(x)) - .collect::<Vec<_>>() + .collect::<Vec<_>>(), ), } } pub fn from_stdin() -> () { - let data = netencode_to_mustache_data_dwim( - arglib_netencode::arglib_netencode("netencode-mustache", Some(std::ffi::OsStr::new("TEMPLATE_DATA"))) - ); + let data = netencode_to_mustache_data_dwim(arglib_netencode::arglib_netencode( + "netencode-mustache", + Some(std::ffi::OsStr::new("TEMPLATE_DATA")), + )); 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() + .and_then(|templ| templ.render_data(&mut std::io::stdout(), &data)) + .unwrap() } pub fn main() { diff --git a/users/Profpatsch/netencode/netencode.rs b/users/Profpatsch/netencode/netencode.rs index 5bd43f992f0b..0d92cf1ed4ae 100644 --- a/users/Profpatsch/netencode/netencode.rs +++ b/users/Profpatsch/netencode/netencode.rs @@ -1,9 +1,9 @@ -extern crate nom; extern crate exec_helpers; +extern crate nom; use std::collections::HashMap; -use std::io::{Write, Read}; -use std::fmt::{Display, Debug}; +use std::fmt::{Debug, Display}; +use std::io::{Read, Write}; #[derive(Debug, PartialEq, Eq, Clone)] pub enum T { @@ -46,22 +46,19 @@ impl T { T::I7(i) => U::I7(*i), T::Text(t) => U::Text(t.as_str()), T::Binary(v) => U::Binary(v), - T::Sum(Tag { tag, val }) => U::Sum( - Tag { tag: tag.as_str(), val: Box::new(val.to_u()) } - ), - T::Record(map) => U::Record( - map.iter().map(|(k, v)| (k.as_str(), v.to_u())).collect() - ), - T::List(l) => U::List( - l.iter().map(|v| v.to_u()).collect::<Vec<U<'a>>>() - ), + T::Sum(Tag { tag, val }) => U::Sum(Tag { + tag: tag.as_str(), + val: Box::new(val.to_u()), + }), + T::Record(map) => U::Record(map.iter().map(|(k, v)| (k.as_str(), v.to_u())).collect()), + T::List(l) => U::List(l.iter().map(|v| v.to_u()).collect::<Vec<U<'a>>>()), } } pub fn encode<'a>(&'a self) -> Vec<u8> { match self { // TODO: don’t go via U, inefficient - o => o.to_u().encode() + o => o.to_u().encode(), } } } @@ -110,15 +107,16 @@ impl<'a> U<'a> { U::I7(i) => T::I7(*i), U::Text(t) => T::Text((*t).to_owned()), U::Binary(v) => T::Binary((*v).to_owned()), - U::Sum(Tag { tag, val }) => T::Sum( - Tag { tag: (*tag).to_owned(), val: Box::new(val.to_t()) } - ), + U::Sum(Tag { tag, val }) => T::Sum(Tag { + tag: (*tag).to_owned(), + val: Box::new(val.to_t()), + }), U::Record(map) => T::Record( - map.iter().map(|(k, v)| ((*k).to_owned(), v.to_t())).collect::<HashMap<String, T>>() - ), - U::List(l) => T::List( - l.iter().map(|v| v.to_t()).collect::<Vec<T>>() + map.iter() + .map(|(k, v)| ((*k).to_owned(), v.to_t())) + .collect::<HashMap<String, T>>(), ), + U::List(l) => T::List(l.iter().map(|v| v.to_t()).collect::<Vec<T>>()), } } } @@ -127,16 +125,18 @@ impl<'a> U<'a> { pub struct Tag<S, A> { // TODO: make into &str pub tag: S, - pub val: Box<A> + pub val: Box<A>, } impl<S, A> Tag<S, A> { fn map<F, B>(self, f: F) -> Tag<S, B> - where F: Fn(A) -> B { - Tag { - tag: self.tag, - val: Box::new(f(*self.val)) - } + where + F: Fn(A) -> B, + { + Tag { + tag: self.tag, + val: Box::new(f(*self.val)), + } } } @@ -147,45 +147,51 @@ fn encode_tag<W: Write>(w: &mut W, tag: &str, val: &U) -> std::io::Result<()> { } pub fn encode<W: Write>(w: &mut W, u: &U) -> std::io::Result<()> { - match u { - U::Unit => write!(w, "u,"), - U::N1(b) => if *b { write!(w, "n1:1,") } else { write!(w, "n1:0,") }, - U::N3(n) => write!(w, "n3:{},", n), - U::N6(n) => write!(w, "n6:{},", n), - U::N7(n) => write!(w, "n7:{},", n), - U::I3(i) => write!(w, "i3:{},", i), - U::I6(i) => write!(w, "i6:{},", i), - U::I7(i) => write!(w, "i7:{},", i), - U::Text(s) => { - write!(w, "t{}:", s.len()); - w.write_all(s.as_bytes()); - write!(w, ",") - } - U::Binary(s) => { - write!(w, "b{}:", s.len()); - w.write_all(&s); - write!(w, ",") - }, - U::Sum(Tag{tag, val}) => encode_tag(w, tag, val), - U::Record(m) => { - let mut c = std::io::Cursor::new(vec![]); - for (k, v) in m { - encode_tag(&mut c, k, v)?; - } - write!(w, "{{{}:", c.get_ref().len())?; - w.write_all(c.get_ref())?; - write!(w, "}}") - }, - U::List(l) => { - let mut c = std::io::Cursor::new(vec![]); - for u in l { - encode(&mut c, u)?; - } - write!(w, "[{}:", c.get_ref().len())?; - w.write_all(c.get_ref())?; - write!(w, "]") - } - } + match u { + U::Unit => write!(w, "u,"), + U::N1(b) => { + if *b { + write!(w, "n1:1,") + } else { + write!(w, "n1:0,") + } + } + U::N3(n) => write!(w, "n3:{},", n), + U::N6(n) => write!(w, "n6:{},", n), + U::N7(n) => write!(w, "n7:{},", n), + U::I3(i) => write!(w, "i3:{},", i), + U::I6(i) => write!(w, "i6:{},", i), + U::I7(i) => write!(w, "i7:{},", i), + U::Text(s) => { + write!(w, "t{}:", s.len()); + w.write_all(s.as_bytes()); + write!(w, ",") + } + U::Binary(s) => { + write!(w, "b{}:", s.len()); + w.write_all(&s); + write!(w, ",") + } + U::Sum(Tag { tag, val }) => encode_tag(w, tag, val), + U::Record(m) => { + let mut c = std::io::Cursor::new(vec![]); + for (k, v) in m { + encode_tag(&mut c, k, v)?; + } + write!(w, "{{{}:", c.get_ref().len())?; + w.write_all(c.get_ref())?; + write!(w, "}}") + } + U::List(l) => { + let mut c = std::io::Cursor::new(vec![]); + for u in l { + encode(&mut c, u)?; + } + write!(w, "[{}:", c.get_ref().len())?; + w.write_all(c.get_ref())?; + write!(w, "]") + } + } } pub fn text(s: String) -> T { @@ -197,27 +203,36 @@ pub fn u_from_stdin_or_die_user_error<'a>(prog_name: &'_ str, stdin_buf: &'a mut let u = match parse::u_u(stdin_buf) { Ok((rest, u)) => match rest { b"" => u, - _ => exec_helpers::die_user_error(prog_name, format!("stdin contained some soup after netencode value: {:?}", String::from_utf8_lossy(rest))) + _ => exec_helpers::die_user_error( + prog_name, + format!( + "stdin contained some soup after netencode value: {:?}", + String::from_utf8_lossy(rest) + ), + ), }, - Err(err) => exec_helpers::die_user_error(prog_name, format!("unable to parse netencode from stdin: {:?}", err)) + Err(err) => exec_helpers::die_user_error( + prog_name, + format!("unable to parse netencode from stdin: {:?}", err), + ), }; u } pub mod parse { - use super::{T, Tag, U}; + use super::{Tag, T, U}; - use std::str::FromStr; - use std::ops::Neg; use std::collections::HashMap; + use std::ops::Neg; + use std::str::FromStr; - use nom::{IResult}; - use nom::branch::{alt}; + use nom::branch::alt; use nom::bytes::streaming::{tag, take}; - use nom::character::streaming::{digit1, char}; - use nom::sequence::{tuple}; - use nom::combinator::{map, map_res, flat_map, map_parser, opt}; + use nom::character::streaming::{char, digit1}; + use nom::combinator::{flat_map, map, map_parser, map_res, opt}; use nom::error::{context, ErrorKind, ParseError}; + use nom::sequence::tuple; + use nom::IResult; fn unit_t(s: &[u8]) -> IResult<&[u8], ()> { let (s, _) = context("unit", tag("u,"))(s)?; @@ -227,9 +242,9 @@ pub mod parse { 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>()) + map_res(map_res(digit1, |n| std::str::from_utf8(n)), |s| { + s.parse::<usize>() + }), )(s) } @@ -238,87 +253,77 @@ pub mod parse { // This is the point where we check the descriminator; // if the beginning char does not match, we can immediately return. let (s, _) = char(begin)(s)?; - let (s, (len, _)) = tuple(( - usize_t, - char(':') - ))(s)?; - let (s, (res, _)) = tuple(( - take(len), - char(end) - ))(s)?; + let (s, (len, _)) = tuple((usize_t, char(':')))(s)?; + let (s, (res, _)) = tuple((take(len), char(end)))(s)?; Ok((s, res)) } } - fn uint_t<'a, I: FromStr + 'a>(t: &'static str) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], I> { move |s: &'a [u8]| { let (s, (_, _, int, _)) = tuple(( tag(t.as_bytes()), char(':'), - map_res( - map_res(digit1, |n: &[u8]| std::str::from_utf8(n)), - |s| s.parse::<I>() - ), - char(',') + map_res(map_res(digit1, |n: &[u8]| std::str::from_utf8(n)), |s| { + s.parse::<I>() + }), + char(','), ))(s)?; Ok((s, int)) } } fn bool_t<'a>() -> impl Fn(&'a [u8]) -> IResult<&'a [u8], bool> { - context("bool", alt(( - map(tag("n1:0,"), |_| false), - map(tag("n1:1,"), |_| true), - ))) - } - - fn int_t<'a, I: FromStr + Neg<Output=I>>(t: &'static str) -> impl Fn(&'a [u8]) -> IResult<&[u8], I> { context( - t, - move |s: &'a [u8]| { - let (s, (_, _, neg, int, _)) = tuple(( - tag(t.as_bytes()), - char(':'), - opt(char('-')), - map_res( - map_res(digit1, |n: &[u8]| std::str::from_utf8(n)), - |s| s.parse::<I>() - ), - char(',') - ))(s)?; - let res = match neg { - Some(_) => -int, - None => int, - }; - Ok((s, res)) - } + "bool", + alt((map(tag("n1:0,"), |_| false), map(tag("n1:1,"), |_| true))), ) } + fn int_t<'a, I: FromStr + Neg<Output = I>>( + t: &'static str, + ) -> impl Fn(&'a [u8]) -> IResult<&[u8], I> { + context(t, move |s: &'a [u8]| { + let (s, (_, _, neg, int, _)) = tuple(( + tag(t.as_bytes()), + char(':'), + opt(char('-')), + map_res(map_res(digit1, |n: &[u8]| std::str::from_utf8(n)), |s| { + s.parse::<I>() + }), + char(','), + ))(s)?; + let res = match neg { + Some(_) => -int, + None => int, + }; + Ok((s, res)) + }) + } + fn tag_t(s: &[u8]) -> IResult<&[u8], Tag<String, T>> { // recurses into the main parser - map(tag_g(t_t), - |Tag {tag, val}| - Tag { - tag: tag.to_string(), - val - })(s) + map(tag_g(t_t), |Tag { tag, val }| Tag { + tag: tag.to_string(), + val, + })(s) } fn tag_g<'a, P, O>(inner: P) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Tag<&'a str, O>> where - P: Fn(&'a [u8]) -> IResult<&'a [u8], O> + P: Fn(&'a [u8]) -> IResult<&'a [u8], O>, { move |s: &[u8]| { let (s, tag) = sized('<', '|')(s)?; let (s, val) = inner(s)?; - Ok((s, Tag { - tag: std::str::from_utf8(tag) - .map_err(|_| nom::Err::Failure((s, ErrorKind::Char)))?, - val: Box::new(val) - })) - + Ok(( + s, + Tag { + tag: std::str::from_utf8(tag) + .map_err(|_| nom::Err::Failure((s, ErrorKind::Char)))?, + val: Box::new(val), + }, + )) } } @@ -330,9 +335,9 @@ pub mod parse { fn text_g(s: &[u8]) -> IResult<&[u8], &str> { let (s, res) = sized('t', ',')(s)?; - Ok((s, - std::str::from_utf8(res) - .map_err(|_| nom::Err::Failure((s, ErrorKind::Char)))?, + Ok(( + s, + std::str::from_utf8(res).map_err(|_| nom::Err::Failure((s, ErrorKind::Char)))?, )) } @@ -374,22 +379,24 @@ pub mod parse { { map_parser( sized('[', ']'), - nom::multi::many0(inner_no_empty_string(inner)) + nom::multi::many0(inner_no_empty_string(inner)), ) } fn record_t<'a>(s: &'a [u8]) -> IResult<&'a [u8], HashMap<String, T>> { let (s, r) = record_g(t_t)(s)?; - Ok((s, + Ok(( + s, r.into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect::<HashMap<_,_>>())) + .map(|(k, v)| (k.to_string(), v)) + .collect::<HashMap<_, _>>(), + )) } fn record_g<'a, P, O>(inner: P) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], HashMap<&'a str, O>> where O: Clone, - P: Fn(&'a [u8]) -> IResult<&'a [u8], O> + P: Fn(&'a [u8]) -> IResult<&'a [u8], O>, { move |s: &'a [u8]| { let (s, map) = map_parser( @@ -397,19 +404,19 @@ pub mod parse { nom::multi::fold_many0( inner_no_empty_string(tag_g(&inner)), HashMap::new(), - |mut acc: HashMap<_,_>, Tag { tag, mut val }| { + |mut acc: HashMap<_, _>, Tag { tag, mut val }| { // ignore duplicated tag names that appear later // according to netencode spec - if ! acc.contains_key(tag) { + if !acc.contains_key(tag) { acc.insert(tag, *val); } acc - } - ) + }, + ), )(s)?; if map.is_empty() { // records must not be empty, according to the spec - Err(nom::Err::Failure((s,nom::error::ErrorKind::Many1))) + Err(nom::Err::Failure((s, nom::error::ErrorKind::Many1))) } else { Ok((s, map)) } @@ -424,7 +431,6 @@ pub mod parse { map(tag_g(u_u), |t| U::Sum(t)), map(list_g(u_u), U::List), map(record_g(u_u), U::Record), - map(bool_t(), |u| U::N1(u)), map(uint_t("n3"), |u| U::N3(u)), map(uint_t("n6"), |u| U::N6(u)), @@ -432,7 +438,6 @@ pub mod parse { map(int_t("i3"), |u| U::I3(u)), map(int_t("i6"), |u| U::I6(u)), map(int_t("i7"), |u| U::I7(u)), - // less common map(uint_t("n2"), |u| U::N3(u)), map(uint_t("n4"), |u| U::N6(u)), @@ -445,7 +450,7 @@ pub mod parse { ))(s) } - pub fn t_t(s: &[u8]) -> IResult<&[u8], T> { + pub fn t_t(s: &[u8]) -> IResult<&[u8], T> { alt(( text, binary(), @@ -453,7 +458,6 @@ pub mod parse { map(tag_t, |t| T::Sum(t)), map(list_t, |l| T::List(l)), map(record_t, |p| T::Record(p)), - map(bool_t(), |u| T::N1(u)), // 8, 64 and 128 bit map(uint_t("n3"), |u| T::N3(u)), @@ -462,7 +466,6 @@ pub mod parse { map(int_t("i3"), |u| T::I3(u)), map(int_t("i6"), |u| T::I6(u)), map(int_t("i7"), |u| T::I7(u)), - // less common map(uint_t("n2"), |u| T::N3(u)), map(uint_t("n4"), |u| T::N6(u)), @@ -481,30 +484,18 @@ pub mod parse { #[test] fn test_parse_unit_t() { - assert_eq!( - unit_t("u,".as_bytes()), - Ok(("".as_bytes(), ())) - ); + assert_eq!(unit_t("u,".as_bytes()), Ok(("".as_bytes(), ()))); } #[test] fn test_parse_bool_t() { - assert_eq!( - bool_t()("n1:0,".as_bytes()), - Ok(("".as_bytes(), false)) - ); - assert_eq!( - bool_t()("n1:1,".as_bytes()), - Ok(("".as_bytes(), true)) - ); + assert_eq!(bool_t()("n1:0,".as_bytes()), Ok(("".as_bytes(), false))); + assert_eq!(bool_t()("n1:1,".as_bytes()), Ok(("".as_bytes(), true))); } #[test] fn test_parse_usize_t() { - assert_eq!( - usize_t("32foo".as_bytes()), - Ok(("foo".as_bytes(), 32)) - ); + assert_eq!(usize_t("32foo".as_bytes()), Ok(("foo".as_bytes(), 32))); } #[test] @@ -515,7 +506,10 @@ pub mod parse { ); assert_eq!( uint_t::<u8>("n3")("n3:1024,abc".as_bytes()), - Err(nom::Err::Error(("1024,abc".as_bytes(), nom::error::ErrorKind::MapRes))) + Err(nom::Err::Error(( + "1024,abc".as_bytes(), + nom::error::ErrorKind::MapRes + ))) ); assert_eq!( int_t::<i64>("i6")("i6:-23,abc".as_bytes()), @@ -544,18 +538,21 @@ pub mod parse { assert_eq!( text("t5:hello,".as_bytes()), Ok(("".as_bytes(), T::Text("hello".to_owned()))), - "{}", r"t5:hello," + "{}", + r"t5:hello," ); assert_eq!( text("t4:fo".as_bytes()), // The content of the text should be 4 long Err(nom::Err::Incomplete(nom::Needed::Size(4))), - "{}", r"t4:fo," + "{}", + r"t4:fo," ); assert_eq!( text("t9:今日は,".as_bytes()), Ok(("".as_bytes(), T::Text("今日は".to_owned()))), - "{}", r"t9:今日は," + "{}", + r"t9:今日は," ); } @@ -564,24 +561,28 @@ pub mod parse { assert_eq!( binary()("b5:hello,".as_bytes()), Ok(("".as_bytes(), T::Binary(Vec::from("hello".to_owned())))), - "{}", r"b5:hello," + "{}", + r"b5:hello," ); assert_eq!( binary()("b4:fo".as_bytes()), // The content of the byte should be 4 long Err(nom::Err::Incomplete(nom::Needed::Size(4))), - "{}", r"b4:fo," + "{}", + r"b4:fo," ); assert_eq!( binary()("b4:foob".as_bytes()), // The content is 4 bytes now, but the finishing , is missing Err(nom::Err::Incomplete(nom::Needed::Size(1))), - "{}", r"b4:fo," - ); + "{}", + r"b4:fo," + ); assert_eq!( binary()("b9:今日は,".as_bytes()), Ok(("".as_bytes(), T::Binary(Vec::from("今日は".as_bytes())))), - "{}", r"b9:今日は," + "{}", + r"b9:今日は," ); } @@ -590,25 +591,23 @@ pub mod parse { assert_eq!( list_t("[0:]".as_bytes()), Ok(("".as_bytes(), vec![])), - "{}", r"[0:]" + "{}", + r"[0:]" ); assert_eq!( list_t("[6:u,u,u,]".as_bytes()), - Ok(("".as_bytes(), vec![ - T::Unit, - T::Unit, - T::Unit, - ])), - "{}", r"[6:u,u,u,]" + Ok(("".as_bytes(), vec![T::Unit, T::Unit, T::Unit,])), + "{}", + r"[6:u,u,u,]" ); assert_eq!( list_t("[15:u,[7:t3:foo,]u,]".as_bytes()), - Ok(("".as_bytes(), vec![ - T::Unit, - T::List(vec![T::Text("foo".to_owned())]), - T::Unit, - ])), - "{}", r"[15:u,[7:t3:foo,]u,]" + Ok(( + "".as_bytes(), + vec![T::Unit, T::List(vec![T::Text("foo".to_owned())]), T::Unit,] + )), + "{}", + r"[15:u,[7:t3:foo,]u,]" ); } @@ -616,27 +615,40 @@ pub mod parse { fn test_record() { assert_eq!( record_t("{21:<1:a|u,<1:b|u,<1:c|u,}".as_bytes()), - Ok(("".as_bytes(), vec![ - ("a".to_owned(), T::Unit), - ("b".to_owned(), T::Unit), - ("c".to_owned(), T::Unit), - ].into_iter().collect::<HashMap<String, T>>())), - "{}", r"{21:<1:a|u,<1:b|u,<1:c|u,}" + Ok(( + "".as_bytes(), + vec![ + ("a".to_owned(), T::Unit), + ("b".to_owned(), T::Unit), + ("c".to_owned(), T::Unit), + ] + .into_iter() + .collect::<HashMap<String, T>>() + )), + "{}", + r"{21:<1:a|u,<1:b|u,<1:c|u,}" ); // duplicated keys are ignored (first is taken) assert_eq!( record_t("{25:<1:a|u,<1:b|u,<1:a|i1:-1,}".as_bytes()), - Ok(("".as_bytes(), vec![ - ("a".to_owned(), T::Unit), - ("b".to_owned(), T::Unit), - ].into_iter().collect::<HashMap<_,_>>())), - "{}", r"{25:<1:a|u,<1:b|u,<1:a|i1:-1,}" + Ok(( + "".as_bytes(), + vec![("a".to_owned(), T::Unit), ("b".to_owned(), T::Unit),] + .into_iter() + .collect::<HashMap<_, _>>() + )), + "{}", + r"{25:<1:a|u,<1:b|u,<1:a|i1:-1,}" ); // empty records are not allowed assert_eq!( record_t("{0:}".as_bytes()), - Err(nom::Err::Failure(("".as_bytes(), nom::error::ErrorKind::Many1))), - "{}", r"{0:}" + Err(nom::Err::Failure(( + "".as_bytes(), + nom::error::ErrorKind::Many1 + ))), + "{}", + r"{0:}" ); } @@ -645,37 +657,62 @@ pub mod parse { assert_eq!( t_t("n3:255,".as_bytes()), Ok(("".as_bytes(), T::N3(255))), - "{}", r"n3:255," + "{}", + r"n3:255," ); assert_eq!( t_t("t6:halloo,".as_bytes()), Ok(("".as_bytes(), T::Text("halloo".to_owned()))), - "{}", r"t6:halloo," + "{}", + r"t6:halloo," ); assert_eq!( t_t("<3:foo|t6:halloo,".as_bytes()), - Ok(("".as_bytes(), T::Sum (Tag { - tag: "foo".to_owned(), - val: Box::new(T::Text("halloo".to_owned())) - }))), - "{}", r"<3:foo|t6:halloo," + Ok(( + "".as_bytes(), + T::Sum(Tag { + tag: "foo".to_owned(), + val: Box::new(T::Text("halloo".to_owned())) + }) + )), + "{}", + r"<3:foo|t6:halloo," ); // { a: Unit // , foo: List <A: Unit | B: List i3> } assert_eq!( t_t("{52:<1:a|u,<3:foo|[33:<1:A|u,<1:A|n1:1,<1:B|[7:i3:127,]]}".as_bytes()), - Ok(("".as_bytes(), T::Record(vec![ - ("a".to_owned(), T::Unit), - ("foo".to_owned(), T::List(vec![ - T::Sum(Tag { tag: "A".to_owned(), val: Box::new(T::Unit) }), - T::Sum(Tag { tag: "A".to_owned(), val: Box::new(T::N1(true)) }), - T::Sum(Tag { tag: "B".to_owned(), val: Box::new(T::List(vec![T::I3(127)])) }), - ])) - ].into_iter().collect::<HashMap<String, T>>()))), - "{}", r"{52:<1:a|u,<3:foo|[33:<1:A|u,<1:A|n1:1,<1:B|[7:i3:127,]]}" + Ok(( + "".as_bytes(), + T::Record( + vec![ + ("a".to_owned(), T::Unit), + ( + "foo".to_owned(), + T::List(vec![ + T::Sum(Tag { + tag: "A".to_owned(), + val: Box::new(T::Unit) + }), + T::Sum(Tag { + tag: "A".to_owned(), + val: Box::new(T::N1(true)) + }), + T::Sum(Tag { + tag: "B".to_owned(), + val: Box::new(T::List(vec![T::I3(127)])) + }), + ]) + ) + ] + .into_iter() + .collect::<HashMap<String, T>>() + ) + )), + "{}", + r"{52:<1:a|u,<3:foo|[33:<1:A|u,<1:A|n1:1,<1:B|[7:i3:127,]]}" ); } - } } @@ -735,7 +772,10 @@ pub mod dec { fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> { match u { U::Binary(b) => Ok(b), - other => Err(DecodeError(format!("Cannot decode {:?} into Binary", other))), + other => Err(DecodeError(format!( + "Cannot decode {:?} into Binary", + other + ))), } } } @@ -766,16 +806,17 @@ pub mod dec { pub struct Record<T>(pub T); impl<'a, Inner> Decoder<'a> for Record<Inner> - where Inner: Decoder<'a> + where + Inner: Decoder<'a>, { type A = HashMap<&'a str, Inner::A>; fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> { match u { - U::Record(map) => - map.into_iter() + U::Record(map) => map + .into_iter() .map(|(k, v)| self.0.dec(v).map(|v2| (k, v2))) .collect::<Result<Self::A, _>>(), - o => Err(DecodeError(format!("Cannot decode {:?} into record", o))) + o => Err(DecodeError(format!("Cannot decode {:?} into record", o))), } } } @@ -784,18 +825,22 @@ pub mod dec { #[derive(Clone, Copy)] pub struct RecordDot<'a, T> { pub field: &'a str, - pub inner: T + pub inner: T, } - impl <'a, Inner> Decoder<'a> for RecordDot<'_, Inner> - where Inner: Decoder<'a> + Clone + impl<'a, Inner> Decoder<'a> for RecordDot<'_, Inner> + where + Inner: Decoder<'a> + Clone, { type A = Inner::A; fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> { match Record(self.inner.clone()).dec(u) { Ok(mut map) => match map.remove(self.field) { Some(inner) => Ok(inner), - None => Err(DecodeError(format!("Cannot find `{}` in record map", self.field))), + None => Err(DecodeError(format!( + "Cannot find `{}` in record map", + self.field + ))), }, Err(err) => Err(err), } @@ -804,23 +849,27 @@ pub mod dec { /// Equals one of the listed `A`s exactly, after decoding. #[derive(Clone)] - pub struct OneOf<T, A>{ + pub struct OneOf<T, A> { pub inner: T, pub list: Vec<A>, } - impl <'a, Inner> Decoder<'a> for OneOf<Inner, Inner::A> - where Inner: Decoder<'a>, - Inner::A: Display + Debug + PartialEq + impl<'a, Inner> Decoder<'a> for OneOf<Inner, Inner::A> + where + Inner: Decoder<'a>, + Inner::A: Display + Debug + PartialEq, { type A = Inner::A; fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> { match self.inner.dec(u) { Ok(inner) => match self.list.iter().any(|x| x.eq(&inner)) { true => Ok(inner), - false => Err(DecodeError(format!("{} is not one of {:?}", inner, self.list))) + false => Err(DecodeError(format!( + "{} is not one of {:?}", + inner, self.list + ))), }, - Err(err) => Err(err) + Err(err) => Err(err), } } } @@ -829,16 +878,16 @@ pub mod dec { #[derive(Clone)] pub struct Try<T>(pub T); - impl <'a, Inner> Decoder<'a> for Try<Inner> - where Inner: Decoder<'a> + impl<'a, Inner> Decoder<'a> for Try<Inner> + where + Inner: Decoder<'a>, { type A = Option<Inner::A>; fn dec(&self, u: U<'a>) -> Result<Self::A, DecodeError> { match self.0.dec(u) { Ok(inner) => Ok(Some(inner)), - Err(err) => Ok(None) + Err(err) => Ok(None), } } } - } diff --git a/users/Profpatsch/netencode/pretty.rs b/users/Profpatsch/netencode/pretty.rs index 8fec24a60e1a..935c3d4a8a17 100644 --- a/users/Profpatsch/netencode/pretty.rs +++ b/users/Profpatsch/netencode/pretty.rs @@ -1,6 +1,6 @@ extern crate netencode; -use netencode::{U, T, Tag}; +use netencode::{Tag, T, U}; pub enum Pretty { Single { @@ -20,7 +20,7 @@ pub enum Pretty { r#type: char, length: String, vals: Vec<Pretty>, - trailer: char + trailer: char, }, } @@ -39,7 +39,7 @@ impl Pretty { r#type: 't', length: format!("{}:", s.len()), val: s.to_string(), - trailer: ',' + trailer: ',', }, U::Binary(s) => Pretty::Single { r#type: 'b', @@ -47,15 +47,18 @@ impl Pretty { // For pretty printing we want the string to be visible obviously. // Instead of not supporting binary, let’s use lossy conversion. val: String::from_utf8_lossy(s).into_owned(), - trailer: ',' + trailer: ',', }, - U::Sum(Tag{tag, val}) => Self::pretty_tag(tag, Self::from_u(*val)), + U::Sum(Tag { tag, val }) => Self::pretty_tag(tag, Self::from_u(*val)), U::Record(m) => Pretty::Multi { r#type: '{', // TODO: we are losing the size here, should we recompute it? Keep it? length: String::from(""), - vals: m.into_iter().map(|(k, v)| Self::pretty_tag(k, Self::from_u(v))).collect(), - trailer: '}' + vals: m + .into_iter() + .map(|(k, v)| Self::pretty_tag(k, Self::from_u(v))) + .collect(), + trailer: '}', }, U::List(l) => Pretty::Multi { r#type: '[', @@ -68,13 +71,14 @@ impl Pretty { } fn scalar<D>(r#type: char, length: &str, d: D) -> Pretty - where D: std::fmt::Display + where + D: std::fmt::Display, { Pretty::Single { r#type, length: length.to_string(), val: format!("{}", d), - trailer: ',' + trailer: ',', } } @@ -89,43 +93,62 @@ impl Pretty { } pub fn print_multiline<W>(&self, mut w: &mut W) -> std::io::Result<()> - where W: std::io::Write + where + W: std::io::Write, { Self::go(&mut w, self, 0, true); write!(w, "\n") } fn go<W>(mut w: &mut W, p: &Pretty, depth: usize, is_newline: bool) -> std::io::Result<()> - where W: std::io::Write + where + W: std::io::Write, { - const full : usize = 4; - const half : usize = 2; - let i = &vec![b' '; depth*full]; - let iandhalf = &vec![b' '; depth*full + half]; - let (i, iandhalf) = unsafe {( - std::str::from_utf8_unchecked(i), - std::str::from_utf8_unchecked(iandhalf), - )}; + const full: usize = 4; + const half: usize = 2; + let i = &vec![b' '; depth * full]; + let iandhalf = &vec![b' '; depth * full + half]; + let (i, iandhalf) = unsafe { + ( + std::str::from_utf8_unchecked(i), + std::str::from_utf8_unchecked(iandhalf), + ) + }; if is_newline { write!(&mut w, "{}", i); } match p { - Pretty::Single {r#type, length, val, trailer} => - write!(&mut w, "{} {}{}", r#type, val, trailer), - Pretty::Tag { r#type, length, key, inner, val } => { + Pretty::Single { + r#type, + length, + val, + trailer, + } => write!(&mut w, "{} {}{}", r#type, val, trailer), + Pretty::Tag { + r#type, + length, + key, + inner, + val, + } => { write!(&mut w, "{} {} {}", r#type, key, inner)?; Self::go::<W>(&mut w, val, depth, false) - }, + } // if the length is 0 or 1, we print on one line, // only if there’s more than one element we split the resulting value. // we never break lines on arbitrary column sizes, since that is just silly. - Pretty::Multi {r#type, length, vals, trailer} => match vals.len() { + Pretty::Multi { + r#type, + length, + vals, + trailer, + } => match vals.len() { 0 => write!(&mut w, "{} {}", r#type, trailer), 1 => { write!(&mut w, "{} ", r#type); Self::go::<W>(&mut w, &vals[0], depth, false)?; write!(&mut w, "{}", trailer) - }, + } more => { write!(&mut w, "\n{}{} \n", iandhalf, r#type)?; for v in vals { diff --git a/users/Profpatsch/read-http.rs b/users/Profpatsch/read-http.rs index 50ff663b994a..efaded87e6cd 100644 --- a/users/Profpatsch/read-http.rs +++ b/users/Profpatsch/read-http.rs @@ -1,37 +1,35 @@ -extern crate httparse; -extern crate netencode; extern crate arglib_netencode; extern crate ascii; extern crate exec_helpers; +extern crate httparse; +extern crate netencode; -use std::os::unix::io::FromRawFd; -use std::io::Read; -use std::io::Write; +use exec_helpers::{die_expected_error, die_temporary, die_user_error}; use std::collections::HashMap; -use exec_helpers::{die_user_error, die_expected_error, die_temporary}; +use std::io::{Read, Write}; +use std::os::unix::io::FromRawFd; -use netencode::{U, T, dec}; use netencode::dec::Decoder; +use netencode::{dec, T, U}; enum What { Request, - Response + Response, } // reads a http request (stdin), and writes all headers to stdout, as netencoded record. // The keys are text, but can be lists of text iff headers appear multiple times, so beware. fn main() -> std::io::Result<()> { - exec_helpers::no_args("read-http"); let args = dec::RecordDot { field: "what", inner: dec::OneOf { list: vec!["request", "response"], - inner: dec::Text - } + inner: dec::Text, + }, }; - let what : What = match args.dec(arglib_netencode::arglib_netencode("read-http", None).to_u()) { + let what: What = match args.dec(arglib_netencode::arglib_netencode("read-http", None).to_u()) { Ok("request") => What::Request, Ok("response") => What::Response, Ok(v) => panic!("shouldn’t happen!, value was: {}", v), @@ -39,7 +37,8 @@ fn main() -> std::io::Result<()> { }; fn read_stdin_to_complete<F>(mut parse: F) -> () - where F: FnMut(&[u8]) -> httparse::Result<usize> + where + F: FnMut(&[u8]) -> httparse::Result<usize>, { let mut res = httparse::Status::Partial; loop { @@ -48,16 +47,22 @@ fn main() -> std::io::Result<()> { } let mut buf = [0; 2048]; match std::io::stdin().read(&mut buf[..]) { - Ok(size) => if size == 0 { - break; - }, - Err(err) => die_temporary("read-http", format!("could not read from stdin, {:?}", err)) + Ok(size) => { + if size == 0 { + break; + } + } + Err(err) => { + die_temporary("read-http", format!("could not read from stdin, {:?}", err)) + } } match parse(&buf) { Ok(status) => { res = status; } - Err(err) => die_temporary("read-http", format!("httparse parsing failed: {:#?}", err)) + Err(err) => { + die_temporary("read-http", format!("httparse parsing failed: {:#?}", err)) + } } } } @@ -66,7 +71,10 @@ fn main() -> std::io::Result<()> { let mut res = HashMap::new(); for httparse::Header { name, value } in headers { let val = ascii::AsciiStr::from_ascii(*value) - .expect(&format!("read-http: we require header values to be ASCII, but the header {} was {:?}", name, value)) + .expect(&format!( + "read-http: we require header values to be ASCII, but the header {} was {:?}", + name, value + )) .as_str(); // lowercase the header names, since the standard doesn’t care // and we want unique strings to match against @@ -77,13 +85,13 @@ fn main() -> std::io::Result<()> { let name_lower = name.to_lowercase(); let _ = res.insert(name_lower, U::List(vec![U::Text(t), U::Text(val)])); () - }, + } Some(U::List(mut l)) => { let name_lower = name.to_lowercase(); l.push(U::Text(val)); let _ = res.insert(name_lower, U::List(l)); () - }, + } Some(o) => panic!("read-http: header not text nor list: {:?}", o), } } @@ -98,12 +106,14 @@ fn main() -> std::io::Result<()> { match chonker.next() { Some(Ok(chunk)) => { buf.extend_from_slice(&chunk); - if chunk.windows(4).any(|c| c == b"\r\n\r\n" ) { + if chunk.windows(4).any(|c| c == b"\r\n\r\n") { return Some(()); } - }, - Some(Err(err)) => die_temporary("read-http", format!("error reading from stdin: {:?}", err)), - None => return None + } + Some(Err(err)) => { + die_temporary("read-http", format!("error reading from stdin: {:?}", err)) + } + None => return None, } } } @@ -118,66 +128,97 @@ fn main() -> std::io::Result<()> { let mut buf: Vec<u8> = vec![]; match read_till_end_of_header(&mut buf, stdin.lock()) { Some(()) => match req.parse(&buf) { - Ok(httparse::Status::Complete(_body_start)) => {}, - Ok(httparse::Status::Partial) => die_expected_error("read-http", "httparse should have gotten a full header"), - Err(err) => die_expected_error("read-http", format!("httparse response parsing failed: {:#?}", err)) + Ok(httparse::Status::Complete(_body_start)) => {} + Ok(httparse::Status::Partial) => { + die_expected_error("read-http", "httparse should have gotten a full header") + } + Err(err) => die_expected_error( + "read-http", + format!("httparse response parsing failed: {:#?}", err), + ), }, - None => die_expected_error("read-http", format!("httparse end of stdin reached before able to parse request headers")) + None => die_expected_error( + "read-http", + format!("httparse end of stdin reached before able to parse request headers"), + ), } let method = req.method.expect("method must be filled on complete parse"); let path = req.path.expect("path must be filled on complete parse"); write_dict_req(method, path, &normalize_headers(req.headers)) - }, + } Response => { let mut resp = httparse::Response::new(&mut headers); let mut buf: Vec<u8> = vec![]; match read_till_end_of_header(&mut buf, stdin.lock()) { Some(()) => match resp.parse(&buf) { - Ok(httparse::Status::Complete(_body_start)) => {}, - Ok(httparse::Status::Partial) => die_expected_error("read-http", "httparse should have gotten a full header"), - Err(err) => die_expected_error("read-http", format!("httparse response parsing failed: {:#?}", err)) + Ok(httparse::Status::Complete(_body_start)) => {} + Ok(httparse::Status::Partial) => { + die_expected_error("read-http", "httparse should have gotten a full header") + } + Err(err) => die_expected_error( + "read-http", + format!("httparse response parsing failed: {:#?}", err), + ), }, - None => die_expected_error("read-http", format!("httparse end of stdin reached before able to parse response headers")) + None => die_expected_error( + "read-http", + format!("httparse end of stdin reached before able to parse response headers"), + ), } let code = resp.code.expect("code must be filled on complete parse"); - let reason = resp.reason.expect("reason must be filled on complete parse"); + let reason = resp + .reason + .expect("reason must be filled on complete parse"); write_dict_resp(code, reason, &normalize_headers(resp.headers)) } } } -fn write_dict_req<'a, 'buf>(method: &'buf str, path: &'buf str, headers: &'a HashMap<String, U<'a>>) -> std::io::Result<()> { - let mut http = vec![ - ("method", U::Text(method)), - ("path", U::Text(path)), - ].into_iter().collect(); +fn write_dict_req<'a, 'buf>( + method: &'buf str, + path: &'buf str, + headers: &'a HashMap<String, U<'a>>, +) -> std::io::Result<()> { + let mut http = vec![("method", U::Text(method)), ("path", U::Text(path))] + .into_iter() + .collect(); write_dict(http, headers) } -fn write_dict_resp<'a, 'buf>(code: u16, reason: &'buf str, headers: &'a HashMap<String, U<'a>>) -> std::io::Result<()> { +fn write_dict_resp<'a, 'buf>( + code: u16, + reason: &'buf str, + headers: &'a HashMap<String, U<'a>>, +) -> std::io::Result<()> { let mut http = vec![ ("status", U::N6(code as u64)), ("status-text", U::Text(reason)), - ].into_iter().collect(); + ] + .into_iter() + .collect(); write_dict(http, headers) } - -fn write_dict<'buf, 'a>(mut http: HashMap<&str, U<'a>>, headers: &'a HashMap<String, U<'a>>) -> std::io::Result<()> { - match http.insert("headers", U::Record( - headers.iter().map(|(k,v)| (k.as_str(), v.clone())).collect() - )) { +fn write_dict<'buf, 'a>( + mut http: HashMap<&str, U<'a>>, + headers: &'a HashMap<String, U<'a>>, +) -> std::io::Result<()> { + match http.insert( + "headers", + U::Record( + headers + .iter() + .map(|(k, v)| (k.as_str(), v.clone())) + .collect(), + ), + ) { None => (), Some(_) => panic!("read-http: headers already in dict"), }; - netencode::encode( - &mut std::io::stdout(), - &U::Record(http) - )?; + netencode::encode(&mut std::io::stdout(), &U::Record(http))?; Ok(()) } - // iter helper struct Chunkyboi<T> { @@ -188,10 +229,7 @@ struct Chunkyboi<T> { impl<R: Read> Chunkyboi<R> { fn new(inner: R, chunksize: usize) -> Self { let buf = vec![0; chunksize]; - Chunkyboi { - inner, - buf - } + Chunkyboi { inner, buf } } } @@ -205,7 +243,7 @@ impl<R: Read> Iterator for Chunkyboi<R> { // clone a new buffer so we can reuse the internal one Some(Ok(self.buf[..read].to_owned())) } - Err(err) => Some(Err(err)) + Err(err) => Some(Err(err)), } } } |