From be115732303dd6b89648f60d7e00b0c6933103d7 Mon Sep 17 00:00:00 2001 From: Avril Date: Fri, 2 Oct 2020 05:16:42 +0100 Subject: [PATCH] improve text reading format --- src/ext.rs | 75 +++++++++++++++++++++++++++++++++++++++++-- src/format/key/mod.rs | 72 +++++++++++++++++++---------------------- src/main.rs | 12 +++---- 3 files changed, 112 insertions(+), 47 deletions(-) diff --git a/src/ext.rs b/src/ext.rs index d58b3f4..eb7fe9d 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -17,6 +17,77 @@ use tokio::{ }; use futures::future::Future; +pub trait FindSliceBounds +{ + type SliceType: ?Sized; + fn slice_bounds(&self, from: &Self::SliceType) -> Range; +} + +pub trait SliceInPlace +{ + fn slice_in_place(&mut self, slice: Range); +} + +impl SliceInPlace for String +{ + fn slice_in_place(&mut self, slice: Range) { + let mut i=0; + self.retain(|_| (slice.contains(&i), i+=1).0); + } +} + +impl SliceInPlace for Vec +{ + fn slice_in_place(&mut self, slice: Range) { + let mut i=0; + self.retain(|_| (slice.contains(&i), i+=1).0); + } +} + +impl> FindSliceBounds for T +{ + type SliceType = str; + fn slice_bounds(&self, from: &Self::SliceType) -> Range{ + let this = self.as_ref(); + unsafe { + let sptr = from.as_ptr(); + let eptr = sptr.add(from.len()); + + let ssptr = this.as_ptr(); + let septr = ssptr.add(this.len()); + + let sptr = sptr as usize; + let ssptr = ssptr as usize; + let eptr = eptr as usize; + let septr = septr as usize; + + assert!(sptr >= ssptr && sptr <= septr, "Start index of slice is outside the bounds of self"); + assert!(eptr >= ssptr && eptr <= septr, "End index of slice is outside the bounds of self"); + + (sptr - ssptr)..(eptr - ssptr) + } + } +} + +#[cfg(test)] +mod test_slice_in_place +{ + use super::*; + #[test] + fn slice_in_place_str() + { + let mut string = String::from(" hello world "); + assert_eq!(&string[string.slice_bounds(string.trim())], string.trim()); + assert_eq!(&string[string.slice_bounds(string.trim())], "hello world"); + string.slice_in_place(string.slice_bounds(string.trim())); + assert_eq!(&string[..], "hello world"); + let string = String::from("hello world"); + assert_eq!(&string[string.slice_bounds(string.trim())], string.trim()); + assert_eq!(&string[string.slice_bounds(string.trim())], "hello world"); + } +} + + #[derive(Debug)] pub struct GroupIter>(std::iter::Fuse, Vec, usize, PhantomData); @@ -78,7 +149,7 @@ pub trait GroupIterExt: Sized impl GroupIterExt<::IntoIter, ::Item> for T { fn group_into(self, every: usize) -> GroupIter<::IntoIter, ::Item, U> - where U: From::Item>> + where U: From::Item>> { GroupIter(self.into_iter().fuse(), Vec::with_capacity(every), every, PhantomData) } @@ -130,7 +201,7 @@ impl<'a, T: ?Sized> StrChunks<'a, T> /// Set the number of chars to break at. /// /// # Note - /// Probably don't do this unless you know what you're doing. + /// Probably don't do this as it modifies the iterators internal state weirdly. But it should be fine generally. pub fn every_mut(&mut self) -> &mut usize { &mut self.1 diff --git a/src/format/key/mod.rs b/src/format/key/mod.rs index 4614578..7d4393d 100644 --- a/src/format/key/mod.rs +++ b/src/format/key/mod.rs @@ -207,9 +207,8 @@ impl KeyHeader out.write_u8(b'\n').await?; written += bytes.len() + 1; } - out.write_all(b"---\n>BEGIN\nBODY<\n").await?; // We can add a comment after > as long as it doesn't have any newlines. - // this is because of the retarded way i did read_text with mpsc. - Ok(written + 8 + 9) + out.write_all(b"---\n").await?; + Ok(written + 4) } /// Read a superheader as text bytes from this stream #[instrument(err, skip(input, passwd))] @@ -266,34 +265,40 @@ impl KeyHeader let line_sender = async move { //this causes the >\n<\n dumbness in the encoding. Rewrite this to not use mpsc pls let mut buffer = String::new(); while input.read_line(&mut buffer).await? != 0 { + let bounds = { + let trimmed = buffer.trim(); + if trimmed.len() == 0 { + continue; + } else if trimmed == "---" { + return Ok(true) + } + buffer.slice_bounds(trimmed) + }; + buffer.slice_in_place(bounds); + if { + let bytes = buffer.as_bytes(); + + if bytes.len() > 0 && bytes[bytes.len()-1] == b'\n' { + true + } else { + false + } + } { + buffer.truncate(buffer.len()-1); + } tx.send(buffer.clone()).await?; buffer.clear(); } - Ok::<(), SendError>(()) + warn!("Buffer contained no end-of-entry delimiter"); + Ok::(false) }; let line_reader = async move { macro_rules! take_one { ($msg:literal $($tt:tt)*) => { - loop { - if let Some(mut line) = rx.recv().await { - if line.trim().len() == 0 { - continue; - } - if { - let bytes = line.as_bytes(); - - if bytes.len() > 0 && bytes[bytes.len()-1] == b'\n' { - true - } else { - false - } - } { - line.truncate(line.len()-1); - } - break line; - } else { - return Err(eyre::eyre!(format!($msg $($tt)*))).wrap_err(eyre::eyre!("Failed to deserialise string")); - } + if let Some(line) = rx.recv().await { + line + } else { + return Err(eyre::eyre!(format!($msg $($tt)*))).wrap_err(eyre::eyre!("Failed to deserialise string")); } } } @@ -312,21 +317,9 @@ impl KeyHeader }; trace!("Decoded hex"); let mut enc = String::new(); - let mut had_delim =false; while let Some(line) = rx.recv().await { - let line = line.trim(); - if line.len() == 0 { - continue; - } - if line == "---" { - had_delim=true; - break; - } else if line.len()>0 { - enc.push_str(line) - } - } - if !had_delim { - warn!("Buffer contained no end-of-entry delimiter"); + debug_assert_eq!(&line[..], line.trim()); + enc.push_str(&line[..]); } trace!("Done reading lines"); @@ -361,12 +354,13 @@ impl KeyHeader let (sres, rres) = tokio::join!(line_sender, line_reader); match sres { Err(x @ SendError::IO(_)) => Err(x).with_note(|| "In line reader"), - Err(_) => { + Err(_) | Ok(true) => { trace!("We completed without reading whole file"); Ok(rres?) }, _ => { warn!("Header reading completed to EOF, there is no body in this stream."); + Ok(rres?) }, } diff --git a/src/main.rs b/src/main.rs index 06cf18a..fa5e997 100644 --- a/src/main.rs +++ b/src/main.rs @@ -157,21 +157,21 @@ async fn fuck() -> eyre::Result<()> let password = "hello world. I am a password"; let superheader = SuperHeader::::new_for(&header); println!("Writing: {:?}\n\t{:?}\n\t{:?}", superheader, header, body); - let mut written = superheader.write_bytes(&mut ser, |salt| Some(Password::derive(password, salt.as_ref()))).await?; - ser.extend(header.into_memory(serialise::Mode::Binary, |salt| Some(Password::derive(password, salt.as_ref())))?); //header.write_text(&mut ser).await?; - written += body.write_bytes(&mut ser, header.body_key()).await?; + let mut written = superheader.write_text(&mut ser, |salt| Some(Password::derive(password, salt.as_ref()))).await?; + ser.extend(header.into_memory(serialise::Mode::Text, |salt| Some(Password::derive(password, salt.as_ref())))?); //header.write_text(&mut ser).await?; + written += body.write_text(&mut ser, header.body_key()).await?; println!("Wrote {} bytes", written); println!("{}\n", ser.fmt_view()); println!("As text:\n{}\n", ser.fmt_ascii()); let mut read = &ser[..]; - let (reads, readn) = SuperHeader::from_memory(&mut read, serialise::Mode::Binary, |salt| Some(Password::derive(password, salt)))?; // SuperHeader::read_text(read).await?; + let (reads, readn) = SuperHeader::from_memory(&mut read, serialise::Mode::Text, |salt| Some(Password::derive(password, salt)))?; // SuperHeader::read_text(read).await?; let mut read = &read[readn..]; println!("Read super: {:?}", reads); - let readheader = KeyHeader::read_bytes(&mut read, |salt| Some(Password::derive(password, salt))).await?; + let readheader = KeyHeader::read_text(&mut read, |salt| Some(Password::derive(password, salt))).await?; println!("Read real: {:?}", readheader); - let readbody = key::aes::AesBody::read_bytes(&mut read, readheader.body_key()).await?; + let readbody = key::aes::AesBody::read_text(&mut read, readheader.body_key()).await?; println!("Read body: {:?}", readbody); reads.verify_for(&header)?; reads.verify_for(&readheader)?;