From 0914a972e4ec471ef6ec9db2d6027fa6b1964f01 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Sun, 5 Dec 2021 05:01:25 +0000 Subject: [PATCH] made a TLV module --- src/main.rs | 6 ++-- src/tlv.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 src/tlv.rs diff --git a/src/main.rs b/src/main.rs index 952ca3b..09a9358 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,8 @@ use std::{ use mac_address::get_mac_address; use thiserror::Error; +mod tlv; + #[derive (Debug, Error)] enum AppError { #[error (transparent)] @@ -56,10 +58,10 @@ fn main () -> Result <(), AppError> { } match args.next ().as_ref ().map (|s| &s[..]) { - None => return Err (CliArgError::MissingSubcommand.into ()), + None => Err (CliArgError::MissingSubcommand)?, Some ("client") => client ()?, Some ("server") => server ()?, - Some (x) => return Err (CliArgError::UnknownSubcommand (x.to_string ()).into ()), + Some (x) => Err (CliArgError::UnknownSubcommand (x.to_string ()))?, } Ok (()) diff --git a/src/tlv.rs b/src/tlv.rs new file mode 100644 index 0000000..beac0a5 --- /dev/null +++ b/src/tlv.rs @@ -0,0 +1,94 @@ +use thiserror::Error; + +type Result = std::result::Result ; + +#[derive (Debug, Error)] +pub enum TlvError { + #[error ("Buffer too big")] + BufferTooBig, + #[error ("Caller-provided buffer too small")] + CallerBufferTooSmall, + #[error (transparent)] + Io (#[from] std::io::Error), + #[error (transparent)] + TryFromInt (#[from] std::num::TryFromIntError), +} + +struct Writer { + _x: std::marker::PhantomData , +} + +impl Writer { + fn length (w: &mut W, x: u32) -> Result <()> { + w.write_all (&x.to_le_bytes ())?; + Ok (()) + } + + fn lv_bytes (w: &mut W, b: &[u8]) -> Result <()> { + if b.len () > 2_000_000_000 { + Err (TlvError::BufferTooBig)?; + } + + let l = u32::try_from (b.len ())?; + + Self::length (w, l)?; + w.write_all (b)?; + + Ok (()) + } +} + +struct Reader { + _x: std::marker::PhantomData , +} + +impl Reader { + fn length (r: &mut R) -> Result { + let mut buf = [0; 4]; + r.read_exact (&mut buf)?; + + Ok (u32::from_le_bytes (buf)) + } + + fn lv_bytes (r: &mut R, buf: &mut [u8]) -> Result { + let l = Self::length (r)?; + if usize::try_from (l)? > buf.len () { + Err (TlvError::CallerBufferTooSmall)?; + } + + r.read_exact (&mut buf [0..usize::try_from (l)?])?; + + Ok (l) + } +} + +#[cfg (test)] +mod test { + #[test] + fn test_1 () { + use std::io::Cursor; + + let b = "hi there".as_bytes (); + + let mut w = Cursor::new (Vec::default ()); + + super::Writer::lv_bytes (&mut w, b).unwrap (); + + let v = w.into_inner (); + + assert_eq! (v, vec! [ + 8, 0, 0, 0, + 104, 105, 32, + 116, 104, 101, 114, 101, + ]); + + let mut r = Cursor::new (v); + + let mut buf = vec! [0; 1024]; + + let bytes_read = super::Reader::lv_bytes (&mut r, &mut buf).unwrap (); + + assert_eq! (usize::try_from (bytes_read).unwrap (), b.len ()); + assert_eq! (b, &buf [0..usize::try_from (bytes_read).unwrap ()]); + } +}