mod formatting;
use std::{ops::Add, fmt::Display};
use super::{fchar::{FChar, FCharDraw}, interface::ToFString};
#[derive(Clone, Default, Debug)]
pub struct FString {
pub(super) characters: Vec<FChar>,
}
impl From<&str> for FString {
fn from(string: &str) -> Self {
FString { characters: string.chars().map(FChar::from).collect()}
}
}
impl FString {
pub fn with_capacity(capacity: usize) -> Self {
FString { characters: Vec::with_capacity(capacity) }
}
pub fn push<'a>(&mut self, s: impl ToFString) {
self.characters.extend(s.to_fchars());
}
pub fn truncate(&mut self, new_len: usize) {
self.characters.truncate(new_len)
}
pub fn pop(&mut self) -> Option<FChar> {
self.characters.pop()
}
pub fn remove(&mut self, idx: usize) -> Option<FChar> {
if idx >= self.characters.len() {
return None
}
return Some(self.characters.remove(idx))
}
pub fn retain(&mut self, mut f: impl FnMut(FChar) -> bool) {
self.characters.retain(|x| f(*x))
}
pub fn insert(&mut self, idx: usize, s: impl ToFString) {
self.characters.splice(idx..idx, s.to_fchars());
}
pub fn as_mut_vec(&mut self) -> &mut Vec<FChar> { &mut self.characters }
pub fn as_slice(&self) -> &[FChar] { &self.characters }
pub fn len(&self) -> usize { self.characters.len() }
pub fn is_empty(&self) -> bool { self.characters.is_empty()}
pub fn split_off(&mut self, ix: usize) -> Option<FString> {
if ix > self.characters.len() { return None }
let characters = self.characters.split_off(ix);
Some(FString { characters })
}
pub fn clear(&mut self) { self.characters.clear() }
pub fn get(&self, ix: usize) -> Option<FChar> {
self.characters.get(ix).map(|x| *x)
}
pub fn get_mut(&mut self, ix: usize) -> Option<&mut FChar> {
self.characters.get_mut(ix)
}
pub fn map_fchars(mut self, mut f: impl FnMut(FChar) -> FChar) -> FString {
for i in self.characters.iter_mut() { *i = f(*i); }
self
}
pub fn map_fchars_draw(mut self, mut f: impl FnMut(FCharDraw) -> FCharDraw) -> FString {
for i in self.characters.iter_mut() {
i.map_draw(&mut f);
}
self
}
pub fn map_chars(self, mut f: impl FnMut(char) -> char) -> FString {
self.map_fchars_draw(|mut fcd| {
fcd.character = f(fcd.character);
fcd
})
}
pub fn to_ascii_lowercase(self) -> FString {
self.map_chars(|x| x.to_ascii_lowercase())
}
pub fn to_ascii_uppercase(self) -> FString {
self.map_chars(|x| x.to_ascii_uppercase())
}
pub fn repeat(&self, n: usize) -> FString {
FString { characters: self.characters.repeat(n) }
}
}
impl Add<FString> for FString {
type Output = FString;
fn add(self, rhs: Self) -> Self::Output {
FString { characters: self.characters.iter().chain(rhs.characters.iter()).cloned().collect() }
}
}
impl Add<FChar> for FString {
type Output = FString;
fn add(self, rhs: FChar) -> Self::Output {
self + rhs.to_fstring()
}
}
impl Add<FString> for FChar {
type Output = FString;
fn add(self, rhs: FString) -> Self::Output {
self.to_fstring() + rhs
}
}
impl Display for FString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let simplified = String::from_iter(self.characters.iter().map(|i|
match i {
FChar::Empty => ' ',
FChar::Draw(fcd) => fcd.character,
FChar::Newline => '\n',
}
));
simplified.fmt(f)
}
}
impl <'a> Extend<&'a FChar> for FString {
fn extend<T: IntoIterator<Item = &'a FChar>>(&mut self, iter: T) {
self.characters.extend(iter)
}
}
impl Extend<FChar> for FString {
fn extend<T: IntoIterator<Item = FChar>>(&mut self, iter: T) {
self.characters.extend(iter)
}
}
impl <'a> Extend<&'a FString> for FString {
fn extend<T: IntoIterator<Item = &'a FString>>(&mut self, iter: T) {
for i in iter {
self.characters.extend(&i.characters)
}
}
}
impl Extend<FString> for FString {
fn extend<T: IntoIterator<Item = FString>>(&mut self, iter: T) {
for i in iter {
self.characters.extend(&i.characters)
}
}
}