Skip to content

Commit

Permalink
Skip whitespace in base64 encoded inputs given to the CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
leighmcculloch committed Jul 15, 2024
1 parent 6c7ecd1 commit cdbed82
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/cli/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{
use clap::{Args, ValueEnum};
use serde::Serialize;

use crate::cli::Channel;
use crate::cli::{skip_whitespace::SkipWhitespace, Channel};

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down Expand Up @@ -82,27 +82,33 @@ macro_rules! run_x {
Error::UnknownType(self.r#type.clone(), &crate::$m::TypeVariant::VARIANTS_STR)
})?;
for f in &mut files {
let mut f = crate::$m::Limited::new(f, crate::$m::Limits::none());
match self.input {
InputFormat::Single => {
let mut f = crate::$m::Limited::new(f, crate::$m::Limits::none());
let t = crate::$m::Type::read_xdr_to_end(r#type, &mut f)?;
self.out(&t)?;
}
InputFormat::SingleBase64 => {
let f = SkipWhitespace::new(f);
let mut f = crate::$m::Limited::new(f, crate::$m::Limits::none());
let t = crate::$m::Type::read_xdr_base64_to_end(r#type, &mut f)?;
self.out(&t)?;
}
InputFormat::Stream => {
let mut f = crate::$m::Limited::new(f, crate::$m::Limits::none());
for t in crate::$m::Type::read_xdr_iter(r#type, &mut f) {
self.out(&t?)?;
}
}
InputFormat::StreamBase64 => {
let f = SkipWhitespace::new(f);
let mut f = crate::$m::Limited::new(f, crate::$m::Limits::none());
for t in crate::$m::Type::read_xdr_base64_iter(r#type, &mut f) {
self.out(&t?)?;
}
}
InputFormat::StreamFramed => {
let mut f = crate::$m::Limited::new(f, crate::$m::Limits::none());
for t in crate::$m::Type::read_xdr_framed_iter(r#type, &mut f) {
self.out(&t?)?;
}
Expand Down
1 change: 1 addition & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod decode;
pub mod encode;
pub mod guess;
mod skip_whitespace;
pub mod types;
mod version;

Expand Down
70 changes: 70 additions & 0 deletions src/cli/skip_whitespace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use std::io::Read;

/// Forwards read operations to the wrapped object, skipping over any whitespace
/// in what is written to buf when the function returns.
pub struct SkipWhitespace<R: Read> {
inner: R,
}

impl<R: Read> SkipWhitespace<R> {
pub fn new(inner: R) -> Self {
SkipWhitespace { inner }
}
}

impl<R: Read> Read for SkipWhitespace<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let n = self.inner.read(buf)?;

let mut written = 0;
for read in 0..n {
if !buf[read].is_ascii_whitespace() {
buf[written] = buf[read];
written += 1;
}
}

Ok(written)
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test() {
struct Test {
input: &'static [u8],
output: &'static [u8],
}
let tests = [
Test {
input: b"",
output: b"",
},
Test {
input: b" \n\t\r",
output: b"",
},
Test {
input: b"a c",
output: b"ac",
},
Test {
input: b"ab cd",
output: b"abcd",
},
Test {
input: b" ab \n cd ",
output: b"abcd",
},
];
for (i, t) in tests.iter().enumerate() {
let mut skip = SkipWhitespace::new(t.input);
let mut output = Vec::new();
skip.read_to_end(&mut output).unwrap();
assert_eq!(output, t.output, "#{i}");
}
}
}

0 comments on commit cdbed82

Please sign in to comment.