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;
#[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
{
/// Join an iterator of `str` with a seperator
@ -24,14 +70,15 @@ pub trait JoinStrsExt: Sized
}
impl<T,I> JoinStrsExt for I
where I: Iterator<Item=T>,
where I: IntoIterator<Item=T>,
T: AsRef<str>
{
/// Join an iterator of `str` with a seperator
fn join(self, with: &str) -> String
{
let mut output = String::new();
let mut first=true;
for string in self
for string in self.into_iter()
{
if !first {
output.push_str(with);
@ -44,60 +91,99 @@ where I: Iterator<Item=T>,
}
}
/*macro_rules! typed_swap {
(@ [] $($reversed:tt)*) => {
fn swap(self) -> ($($reversed)*);
};
(@ [$first:tt $($rest:tt)*] $($reversed:tt)*) => {
typed_swap!{@ [$($rest)*] $first $($reversed)*}
};
(@impl {$($body:tt)*} [] $($reversed:tt)*) => {
fn swap(self) -> ($($reversed)*)
#[derive(Debug, Clone)]
pub struct StrChunks<'a, T: ?Sized>(&'a str, usize, PhantomData<&'a T>);
impl<'a, T: ?Sized> StrChunks<'a, T>
{
$($body)*
/// The rest of the string
pub fn as_str(&self) -> &'a str
{
&self.0[..]
}
};
(@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
/// The number of chars to break at
pub fn every(&self) -> usize
{
typed_swap!(@ [$($params)*]);
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,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.0.chars().size_hint();
(low / self.1, high.map(|x| (x / self.1) + 1)) //not too sure if this is right...
}
}
impl<'a, T: ?Sized> std::iter::FusedIterator for StrChunks<'a, T>{}
impl<$($params)*> SwapTupleExt<$($params)*> for ($($params)*)
/// Split a `str` into chunks on char boundaries
pub trait ChunkStrsExt
{
typed_swap!(@impl {
todo!()
} [$($params)*]);
/// 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>;
}
typed_swap!($($rest)*);
#[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)+) => {
typed_swap!({$first, $($params),+});
mod nswap {
typed_swap!(all $($params)+);
let string = r"a2eab409c57a829d23139c61ff2d5e479260c96158ebec0ce4d458afb85b76dłこんな僕は生きてるだけ何万人の人が悲しいんで。!?";
let astr: String = string.chars().group(8).map(|x| -> String {x.iter().collect()}).collect();
assert_eq!(&astr[..], string);
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();
}*/
// ^ unfortunately not lol
fn chunk(&self, every: usize) -> StrChunks<'_, Self>
{
StrChunks(self.as_ref(), every, PhantomData)
}
}
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] = [
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

@ -163,7 +163,7 @@ async fn fuck() -> eyre::Result<()>
println!("Wrote {} bytes", written);
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 (reads, readn) = SuperHeader::from_memory(&mut read, serialise::Mode::Binary, |salt| Some(Password::derive(password, salt)))?; // SuperHeader::read_text(read).await?;

Loading…
Cancel
Save