master
Avril 4 years ago
parent 70816f31f7
commit b03a90f493
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -17,6 +17,52 @@ use tokio::{
}; };
use futures::future::Future; use futures::future::Future;
#[derive(Debug)]
pub struct GroupIter<I, T>(std::iter::Fuse<I>, Vec<T>, usize);
impl<I: Iterator<Item=T>, T> Iterator for GroupIter<I, T>
{
type Item = Box<[T]>;
fn next(&mut self) -> Option<Self::Item>
{
if self.1.len() == 0 {
// fill
for (_, item) in (0..self.2).zip(&mut self.0)
{
self.1.push(item);
}
}
if self.1.len() == 0 {
None
} else{
Some(std::mem::replace(&mut self.1, Vec::with_capacity(self.2)).into())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.0.size_hint();
(low / self.2, high.map(|x| (x / self.2) + 1)) //not too sure if this is right...
}
}
impl<I: Iterator<Item=T>, T> std::iter::FusedIterator for GroupIter<I, T>{}
pub trait GroupIterExt<I, T>: Sized
{
/// Group this iterator to return a boxed slice of every `n` items.
///
/// # Notes
/// If there isn't `n` items left in the iterator, then the rest is returned.
fn group(self, n: usize) -> GroupIter<I, T>;
}
impl<T: IntoIterator> GroupIterExt<<T as IntoIterator>::IntoIter, <T as IntoIterator>::Item> for T
{
fn group(self, every: usize) -> GroupIter<<T as IntoIterator>::IntoIter, <T as IntoIterator>::Item>
{
GroupIter(self.into_iter().fuse(), Vec::with_capacity(every), every)
}
}
pub trait JoinStrsExt: Sized pub trait JoinStrsExt: Sized
{ {
/// Join an iterator of `str` with a seperator /// Join an iterator of `str` with a seperator
@ -24,14 +70,15 @@ pub trait JoinStrsExt: Sized
} }
impl<T,I> JoinStrsExt for I impl<T,I> JoinStrsExt for I
where I: Iterator<Item=T>, where I: IntoIterator<Item=T>,
T: AsRef<str> T: AsRef<str>
{ {
/// Join an iterator of `str` with a seperator
fn join(self, with: &str) -> String fn join(self, with: &str) -> String
{ {
let mut output = String::new(); let mut output = String::new();
let mut first=true; let mut first=true;
for string in self for string in self.into_iter()
{ {
if !first { if !first {
output.push_str(with); output.push_str(with);
@ -44,60 +91,99 @@ where I: Iterator<Item=T>,
} }
} }
/*macro_rules! typed_swap { #[derive(Debug, Clone)]
(@ [] $($reversed:tt)*) => { pub struct StrChunks<'a, T: ?Sized>(&'a str, usize, PhantomData<&'a T>);
fn swap(self) -> ($($reversed)*);
}; impl<'a, T: ?Sized> StrChunks<'a, T>
(@ [$first:tt $($rest:tt)*] $($reversed:tt)*) => { {
typed_swap!{@ [$($rest)*] $first $($reversed)*} /// The rest of the string
}; pub fn as_str(&self) -> &'a str
(@impl {$($body:tt)*} [] $($reversed:tt)*) => { {
fn swap(self) -> ($($reversed)*) &self.0[..]
{ }
$($body)* /// The number of chars to break at
pub fn every(&self) -> usize
{
self.1
}
/// Set the number of chars to break at.
///
/// # Note
/// Probably don't do this unless you know what you're doing.
pub fn every_mut(&mut self) -> &mut usize
{
&mut self.1
}
}
impl<'a, T: ?Sized> Iterator for StrChunks<'a, T>
{
type Item = &'a str;
fn next(&mut self) -> Option<Self::Item>
{
match self.0.char_indices().nth(self.1).map(|x| x.0) {
None if self.0.len() > 0 => Some(std::mem::replace(&mut self.0, "")),
Some(i) => {
let (left, right) = self.0.split_at(i);
self.0 = right;
Some(left)
},
_ => None,
} }
}; }
(@impl {$($body:tt)*} [$first:tt $($rest:tt)*] $($reversed:tt)*) => {
typed_swap!{@impl {$($body)*} [$($rest)*] $first $($reversed)*}
};
() => {};
({$($params:tt)*} $($rest:tt)*) => {
mod swap {
pub trait SwapTupleExt<$($params)*>: Sized
{
typed_swap!(@ [$($params)*]);
}
impl<$($params)*> SwapTupleExt<$($params)*> for ($($params)*) fn size_hint(&self) -> (usize, Option<usize>) {
{ let (low, high) = self.0.chars().size_hint();
typed_swap!(@impl { (low / self.1, high.map(|x| (x / self.1) + 1)) //not too sure if this is right...
todo!() }
} [$($params)*]); }
} impl<'a, T: ?Sized> std::iter::FusedIterator for StrChunks<'a, T>{}
typed_swap!($($rest)*); /// Split a `str` into chunks on char boundaries
pub trait ChunkStrsExt
{
/// Split this str into a chunking iterator every specified number of chars.
///
/// If there are not enough chars left in the string, the rest is returned.
/// # Note
/// This operates on codepoints, not bytes.
fn chunk(&self, every: usize) -> StrChunks<'_, Self>;
}
#[cfg(test)]
mod chunk_tests
{
use super::*;
#[test]
fn chunk_test()
{
let string = r"a2eab409c57a829d23139c61ff2d5e479260c96158ebec0ce4d458afb85b76dłこんな僕は生きてるだけ何万人の人が悲しいんで。!?";
assert_eq!(&string.chunk(8).join("")[..], string);
for chunk in string.chunk(8) {
println!("{}", chunk);
} }
pub use swap::*; }
};
#[test]
fn group_test()
{
(all $first:tt $($params:tt)+) => { let string = r"a2eab409c57a829d23139c61ff2d5e479260c96158ebec0ce4d458afb85b76dłこんな僕は生きてるだけ何万人の人が悲しいんで。!?";
typed_swap!({$first, $($params),+}); let astr: String = string.chars().group(8).map(|x| -> String {x.iter().collect()}).collect();
mod nswap { assert_eq!(&astr[..], string);
typed_swap!(all $($params)+); for chunk in string.chars().group(8) {
println!("{:?}", chunk);
} }
}; }
(all $($one:tt)?) => {};
} }
typed_swap!(all A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
pub use swap::*;
fn test() impl<T: AsRef<str>+?Sized> ChunkStrsExt for T
{ {
let sw = (1, 2).swap(); fn chunk(&self, every: usize) -> StrChunks<'_, Self>
{
}*/ StrChunks(self.as_ref(), every, PhantomData)
// ^ unfortunately not lol }
}
pub trait SwapTupleExt<T,U>: Sized pub trait SwapTupleExt<T,U>: Sized
{ {
@ -110,11 +196,6 @@ impl<T,U> SwapTupleExt<T,U> for (T,U)
} }
} }
/*typed_swap!({A, B}
{A, U, V}
{T, U, V, W});*/
const ASCII_MAP: [char; 256] = [ const ASCII_MAP: [char; 256] = [
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

@ -163,7 +163,7 @@ async fn fuck() -> eyre::Result<()>
println!("Wrote {} bytes", written); println!("Wrote {} bytes", written);
println!("{}\n", ser.fmt_view()); println!("{}\n", ser.fmt_view());
println!("As text:\n{}\n", String::from_utf8_lossy(&ser[..])); println!("As text:\n{}\n", ser.fmt_ascii());
let mut read = &ser[..]; 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::Binary, |salt| Some(Password::derive(password, salt)))?; // SuperHeader::read_text(read).await?;

Loading…
Cancel
Save