use std::marker::PhantomData;
const BUFFER_SIZE: usize = 16;
pub trait Pullable {
type Item;
fn pull(&mut self, buffer: &mut [Self::Item]) -> usize;
fn transcode<K, E>(self, encoding: E) -> Transcoder<K, E, Self>
where Self: Sized,
K: TranscoderKind<Input = Self::Item>,
E: TranscoderImpl<K, Self> {
Transcoder::new(encoding, self)
}
fn iter(self) -> PullableIterator<Self> where Self: Sized, Self::Item: Default {
PullableIterator::new(self)
}
}
impl<I> Pullable for I where I: Iterator {
type Item = I::Item;
fn pull(&mut self, buffer: &mut [Self::Item]) -> usize {
let mut count = 0;
while count < buffer.len() {
if let Some(x) = self.next() {
buffer[count] = x;
count += 1;
} else {
break;
}
}
count
}
}
pub struct PullableIterator<I> where I: Pullable {
inner: I,
buffer: [I::Item; BUFFER_SIZE],
index: usize,
count: usize,
}
impl<I> PullableIterator<I> where I: Pullable, I::Item: Default { pub fn new(inner: I) -> Self {
Self { inner, buffer: std::array::from_fn(|_| I::Item::default()), index: 0, count: 0 }
}
}
impl<I> Iterator for PullableIterator<I> where I: Pullable, I::Item: Default { type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.count {
self.index = 0;
self.count = self.inner.pull(&mut self.buffer);
}
if self.index < self.count {
let item = std::mem::take(&mut self.buffer[self.index]);
self.index += 1;
Some(item)
} else {
None
}
}
}
#[derive(Clone)]
pub struct PullBuffer<I> where I: Pullable {
inner: I,
head: usize,
tail: usize,
buffer: [I::Item; BUFFER_SIZE],
}
impl<I> PullBuffer<I> where I: Pullable {
pub fn new(inner: I) -> Self where I::Item: Default { Self { inner, head: 0, tail: 0, buffer: std::array::from_fn(|_| I::Item::default()) }
}
pub fn view(&mut self, amount: usize) -> &[I::Item] {
assert!(amount <= BUFFER_SIZE);
if self.head + amount > self.tail {
if self.head == self.tail {
self.head = 0;
self.tail = 0;
} else {
self.buffer.rotate_left(self.head);
self.tail -= self.head;
self.head = 0;
}
self.tail += self.inner.pull(&mut self.buffer[self.tail..]);
}
&self.buffer[self.head..self.tail.min(self.head + amount)]
}
pub fn advance(&mut self, amount: usize) {
self.head += amount;
assert!(self.head <= self.tail);
}
}
pub struct PushBuffer<'a, T> {
count: usize,
buffer: &'a mut [T],
}
impl<'a, T> PushBuffer<'a, T> {
pub fn new(buffer: &'a mut [T]) -> Self {
Self { count: 0, buffer }
}
pub fn len(&self) -> usize { self.count }
pub fn is_empty(&self) -> bool { self.count == 0 }
pub fn capacity(&self) -> usize { self.buffer.len() }
pub fn fits(&self, count: usize) -> bool { self.count + count <= self.buffer.len() }
pub fn push<const N: usize>(&mut self, items: [T; N]) {
assert!(self.fits(N));
for (i, x) in items.into_iter().enumerate() {
self.buffer[self.count + i] = x;
}
self.count += N;
}
}
pub trait TranscoderKind {
type Input: Default; type Output;
}
pub trait TranscoderImpl<K, I> where K: TranscoderKind, I: Pullable<Item = K::Input> {
fn transcode(&self, input: &mut PullBuffer<I>, output: &mut PushBuffer<'_, K::Output>);
}
pub struct Transcoder<K, E, I> where K: TranscoderKind, I: Pullable<Item = K::Input>, E: TranscoderImpl<K, I> {
encoding: E,
input: PullBuffer<I>,
phantom: PhantomData<K>,
}
impl<K, E, I> Transcoder<K, E, I> where K: TranscoderKind, I: Pullable<Item = K::Input>, E: TranscoderImpl<K, I> {
pub fn new(encoding: E, input: I) -> Self {
Self { encoding, input: PullBuffer::new(input), phantom: PhantomData }
}
}
impl<K, E, I> Pullable for Transcoder<K, E, I> where K: TranscoderKind, I: Pullable<Item = K::Input>, E: TranscoderImpl<K, I> {
type Item = K::Output;
fn pull(&mut self, buffer: &mut [Self::Item]) -> usize {
let mut buf = PushBuffer::new(buffer);
self.encoding.transcode(&mut self.input, &mut buf);
buf.len()
}
}
pub mod str;