pub mod builder;
pub mod combined;
pub mod helper;
pub mod renderer;
pub use element::Element;
use std::convert::Into;
use super::*;
use crate::sequence::renderer::*;
use std::fmt;
use std::ops::{AddAssign, SubAssign};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Sequence {
start: u64,
end: Option<u64>,
inner: Option<u64>,
step: u32,
initialized: bool,
done: bool,
renderer: SeqRenderer,
}
impl Default for Sequence {
fn default() -> Self {
Self {
initialized: false,
start: 0,
end: None,
inner: None,
done: false,
renderer: Default::default(),
step: 1,
}
}
}
impl Iterator for Sequence {
type Item = Element;
fn next(&mut self) -> Option<Self::Item> {
match (self.done, self.initialized, self.inner) {
(true, _, _) => None,
(false, false, Some(_)) => {
self.initialized = true;
Some(self.generate_element())
}
(false, _, None) => {
self.initialized = true;
match self.inner(self.start) {
Ok(_) => Some(self.generate_element()),
_ => None
}
},
(false, true, Some(_)) => {
match self.add(self.step as u64) {
Ok(_) => Some(self.generate_element()),
Err(_) => { self.done = true; None }
}
}
}
}
}
impl fmt::Display for Sequence {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", 42 ) }
}
impl Sequence {
fn new_unchecked(inner: u64) -> Self {
Self {
start: inner,
..Self::default()
}
}
pub fn reset(&mut self) {
self.inner = None;
self.done = false;
}
pub fn zero(&mut self) {
self.initialized = false;
self.inner = Some(0);
self.done = false;
}
pub fn rollover(&mut self) {
self.initialized = true;
self.inner = Some(0);
self.done = false;
}
pub fn add(&mut self, rhs: u64) -> Result<(), SequenceError> {
match (self.done, self.inner) {
(true, _) => Err(SequenceError::Done),
(false, None) => Err(SequenceError::Uninitialized),
(false, Some(inner)) => match inner.checked_add(rhs) {
None => return Err(SequenceError::OutOfRange),
Some(new_inner) => self.inner(new_inner)
}
}
}
pub fn sub(&mut self, rhs: u64) -> Result<(), SequenceError> {
match (self.done, self.inner) {
(true, _) => Err(SequenceError::Done),
(false, None) => Err(SequenceError::Uninitialized),
(false, Some(inner)) => match inner.checked_sub(rhs) {
None => return Err(SequenceError::OutOfRange),
Some(new_inner) => self.inner(new_inner)
}
}
}
pub fn set(&mut self, inner: u64) -> Option<Element> {
self.initialized = false;
self.inner(inner).map( |_| self.generate_element()).ok()
}
fn inner(&mut self, new_inner: u64) -> Result<(), SequenceError> {
if let Some(renderlimit) = self.renderer.max() {
if renderlimit < new_inner {
return Err(SequenceError::OutOfRangeRender);
}
}
if let Some(end) = self.end {
if end <= new_inner {
return Err(SequenceError::OutOfRange);
}
}
self.inner = Some(new_inner);
Ok(())
}
fn generate_element(&self) -> Element {
element::ElementBuilder::default()
.inner(self.inner.unwrap())
.renderer(self.renderer.clone())
.build()
.unwrap()
}
}
impl<T: Into<u64>> AddAssign<T> for Sequence {
fn add_assign(&mut self, rhs: T) {
self.initialized = false;
self.add(rhs.into()).expect("Failed to call add_assisgn on sequence");
}
}
impl<T: Into<u64>> SubAssign<T> for Sequence {
fn sub_assign(&mut self, rhs: T) {
self.initialized = false;
self.sub(rhs.into()).expect("Failed to call sub_assign on sequence");
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn default() {
let mut seq = Sequence::default();
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "0");
}
#[test]
fn new_unchecked() {
let mut seq = Sequence::new_unchecked(u64::MAX);
let elem = seq.next().unwrap();
assert_eq!(
elem.to_string(),
u64::MAX.to_string()
);
}
#[test]
fn num() {
for i in 0..123_456 {
let mut seq = SequenceBuilder::new().start(i).build().unwrap();
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), i.to_string());
}
}
#[test]
fn lower() {
for i in 0..100 {
let mut seq = SequenceBuilder::new().start(i).lower().build().unwrap();
let elem = seq.next().unwrap();
assert_eq!(
elem.to_string().matches(|c: char| !c.is_lowercase()).count(),
0
);
assert_eq!(seq.to_string(), seq.to_string().to_ascii_lowercase(),)
}
}
#[test]
fn upper() {
for i in 0..100 {
let mut seq = SequenceBuilder::new().start(i).upper().build().unwrap();
let elem = seq.next().unwrap();
assert_eq!(
elem.to_string().matches(|c: char| !c.is_uppercase()).count(),
0
);
assert_eq!(seq.to_string(), seq.to_string().to_ascii_uppercase(),)
}
}
#[test]
fn rollover() {
use std::convert::TryFrom;
let mut seq = SequenceBuilder::try_from("Z").unwrap().build().unwrap();
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "Z");
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "AA");
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "AB");
let mut seq = SequenceBuilder::try_from("z").unwrap().build().unwrap();
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "z");
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "aa");
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "ab");
let mut seq = SequenceBuilder::try_from("9").unwrap().build().unwrap();
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), (9).to_string());
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), (10).to_string());
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), (11).to_string());
}
#[test]
fn zero() {
use std::convert::TryFrom;
let mut seq = SequenceBuilder::try_from(0).unwrap().build().unwrap();
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "0");
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "1");
seq.zero();
let elem = seq.next().unwrap();
assert_eq!(elem.to_string(), "0");
}
#[test]
fn assignmod() {
let mut seq = SequenceBuilder::new().start(42).build().unwrap();
let elem = seq.next().unwrap();
assert_eq!( elem.to_string(), "42" );
seq += 0u32;
let elem = seq.next().unwrap();
assert_eq!( elem.to_string(), "42" );
seq += 5u32;
let elem = seq.next().unwrap();
assert_eq!( elem.to_string(), "47" );
seq -= 5u32;
let elem = seq.next().unwrap();
assert_eq!( elem.to_string(), "42" );
}
}