use std::{
fmt::{Debug, Display, Formatter},
iter::repeat_with,
ops::RangeBounds,
slice,
};
use itertools::Itertools;
use crate::{
row::{same_stage_vec, DbgRow},
utils, Bell, Row, RowBuf, SameStageVec, Stage,
};
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct Block<A> {
rows: SameStageVec,
annots: Vec<A>,
}
impl<A> Block<A> {
pub fn parse(s: &str) -> Result<Self, ParseError>
where
A: Default,
{
let rows = SameStageVec::parse(s).map_err(ParseError::Other)?;
if rows.is_empty() {
Err(ParseError::ZeroLengthBlock)
} else {
Ok(Self::with_default_annots(rows))
}
}
pub fn with_default_annots(rows: SameStageVec) -> Self
where
A: Default,
{
assert!(!rows.is_empty());
Self {
annots: repeat_with(A::default).take(rows.len() - 1).collect_vec(),
rows,
}
}
pub fn empty(stage: Stage) -> Self {
Self::with_leftover_row(RowBuf::rounds(stage))
}
pub fn with_leftover_row(leftover_row: RowBuf) -> Self {
Self {
rows: SameStageVec::from_row_buf(leftover_row),
annots: vec![], }
}
pub fn with_annots_from_indices(rows: SameStageVec, f: impl FnMut(usize) -> A) -> Option<Self> {
let length_of_self = rows.len().checked_sub(1)?;
Some(Self {
annots: (0..length_of_self).map(f).collect_vec(),
rows,
})
}
#[inline]
pub fn stage(&self) -> Stage {
self.rows.stage()
}
pub fn effective_stage(&self) -> Stage {
self.all_rows()
.map(Row::effective_stage)
.max()
.unwrap()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.annots.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.annots.len()
}
#[inline]
pub fn get_row(&self, index: usize) -> Option<&Row> {
self.rows.get(index)
}
#[inline]
pub fn get_annot(&self, index: usize) -> Option<&A> {
self.annots.get(index)
}
#[inline]
pub fn get_annot_mut(&mut self, index: usize) -> Option<&mut A> {
self.annots.get_mut(index)
}
#[inline]
pub fn get_annot_row(&self, index: usize) -> Option<(&A, &Row)> {
Some((self.get_annot(index)?, self.get_row(index)?))
}
#[inline]
pub fn first_row(&self) -> &Row {
self.rows.first().unwrap()
}
#[inline]
pub fn first_annot_row(&self) -> Option<(&A, &Row)> {
self.get_annot_row(0)
}
#[inline]
pub fn leftover_row(&self) -> &Row {
self.rows.last().unwrap()
}
#[inline]
pub fn leftover_row_mut(&mut self) -> &mut Row {
self.rows.last_mut().unwrap()
}
#[inline]
pub fn rows(&self) -> same_stage_vec::Iter {
let mut iter = self.all_rows();
iter.next_back(); iter
}
#[inline]
pub fn all_rows(&self) -> same_stage_vec::Iter {
self.rows.iter()
}
#[inline]
pub fn annots(&self) -> std::slice::Iter<A> {
self.annots.iter()
}
#[inline]
pub fn annot_rows(&self) -> impl Iterator<Item = (&A, &Row)> + Clone {
self.annots().zip_eq(self.rows())
}
#[inline]
pub fn all_annot_rows(&self) -> impl Iterator<Item = (Option<&A>, &Row)> + Clone {
self.annots()
.map(Some)
.chain(std::iter::once(None))
.zip_eq(self.all_rows())
}
pub fn path_of(&self, bell: Bell) -> (Vec<usize>, usize) {
let mut full_path = self.full_path_of(bell);
let place_in_leftover_row = full_path.pop().unwrap();
(full_path, place_in_leftover_row)
}
pub fn full_path_of(&self, bell: Bell) -> Vec<usize> {
self.rows.path_of(bell) }
pub fn repeat_iter(&self, start_row: RowBuf) -> RepeatIter<A> {
RepeatIter::new(start_row, self)
}
pub fn pre_multiply(&mut self, lhs_row: &Row) {
self.rows.pre_multiply(lhs_row) }
pub fn extend(&mut self, other: &Self)
where
A: Clone,
{
self.extend_range(other, ..)
}
pub fn extend_range(&mut self, other: &Self, range: impl RangeBounds<usize>)
where
A: Clone,
{
let range = utils::clamp_range(range, other.len());
let transposition =
Row::solve_xa_equals_b(other.get_row(range.start).unwrap(), self.leftover_row());
self.rows.pop(); self.rows
.extend_range_transposed(&transposition, &other.rows, range.start..range.end + 1);
self.annots.extend_from_slice(&other.annots[range]);
}
pub fn extend_from_within(&mut self, range: impl RangeBounds<usize> + Debug + Clone)
where
A: Clone + Debug,
{
let range = utils::clamp_range(range, self.len());
let first_row_of_chunk = self.get_row(range.start).unwrap();
let transposition = Row::solve_xa_equals_b(first_row_of_chunk, self.leftover_row());
self.rows
.extend_transposed_from_within(range.start + 1..range.end + 1, &transposition);
self.annots.extend_from_within(range);
}
pub fn into_rows(self) -> SameStageVec {
self.rows
}
pub fn row_vec(&self) -> &SameStageVec {
&self.rows
}
pub fn map_annots<B>(self, f: impl Fn(A) -> B) -> Block<B> {
Block {
rows: self.rows, annots: self.annots.into_iter().map(f).collect_vec(),
}
}
pub fn map_annots_with_index<B>(self, f: impl Fn(usize, A) -> B) -> Block<B> {
Block {
rows: self.rows, annots: self
.annots
.into_iter()
.enumerate()
.map(|(i, annot)| f(i, annot))
.collect_vec(),
}
}
pub fn clone_map_annots_with_index<'s, B>(&'s self, f: impl Fn(usize, &'s A) -> B) -> Block<B> {
Block {
rows: self.rows.to_owned(), annots: self
.annots
.iter()
.enumerate()
.map(|(i, annot)| f(i, annot))
.collect_vec(),
}
}
pub fn split(self, index: usize) -> Option<(Self, Self)> {
let (first_annots, second_annots) = utils::split_vec(self.annots, index)?;
let (mut first_rows, second_rows) = self.rows.split(index)?;
let first_row_of_second = second_rows.first().unwrap(); first_rows.push(first_row_of_second);
let first_block = Self {
rows: first_rows,
annots: first_annots,
};
let second_block = Self {
rows: second_rows,
annots: second_annots,
};
Some((first_block, second_block))
}
}
impl<T> Debug for Block<T>
where
T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
struct Pair<K, V>(K, V);
impl<K, V> Debug for Pair<K, V>
where
K: Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}: {:?}", self.0, self.1)
}
}
let mut builder = f.debug_tuple(stringify!(Block));
for (annot, row) in self.annot_rows() {
builder.field(&Pair(DbgRow(row), annot));
}
builder.field(&DbgRow(self.leftover_row()));
builder.finish()
}
}
type InnerIter<'b, A> =
std::iter::Enumerate<itertools::ZipEq<same_stage_vec::Iter<'b>, slice::Iter<'b, A>>>;
#[derive(Clone)]
pub struct RepeatIter<'b, A> {
current_block_head: RowBuf,
iter: InnerIter<'b, A>,
block: &'b Block<A>,
}
impl<'b, A> RepeatIter<'b, A> {
fn new(start_row: RowBuf, block: &'b Block<A>) -> Self {
Self {
current_block_head: start_row,
iter: Self::get_iter(block),
block,
}
}
#[must_use]
pub fn next_into(&mut self, out: &mut RowBuf) -> Option<(usize, &'b A)> {
let (source_idx, (untransposed_row, annot)) = self.next_untransposed_row()?;
self.current_block_head.mul_into(untransposed_row, out);
Some((source_idx, annot))
}
fn get_iter(block: &'b Block<A>) -> InnerIter<'b, A> {
block.rows().zip_eq(block.annots()).enumerate()
}
fn next_untransposed_row(&mut self) -> Option<(usize, (&'b Row, &'b A))> {
self.iter.next().or_else(|| {
self.current_block_head = self.current_block_head.as_row() * self.block.leftover_row();
self.iter = Self::get_iter(self.block);
self.iter.next()
})
}
}
impl<'b, A> Iterator for RepeatIter<'b, A> {
type Item = (RowBuf, usize, &'b A);
fn next(&mut self) -> Option<Self::Item> {
let (source_idx, (untransposed_row, annot)) = self.next_untransposed_row()?;
let next_row = self.current_block_head.as_row() * untransposed_row;
Some((next_row, source_idx, annot))
}
}
#[derive(Debug, Clone)]
pub enum ParseError {
ZeroLengthBlock,
Other(same_stage_vec::ParseError),
}
impl Display for ParseError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ParseError::ZeroLengthBlock => write!(f, "Blocks must contain at least one row"),
ParseError::Other(inner) => write!(f, "{}", inner),
}
}
}
impl std::error::Error for ParseError {}