use std::cell::{Cell, RefCell};
use std::rc::Rc;
use super::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LineTextError {
pub text: String,
}
impl std::fmt::Display for LineTextError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Invalid line text given: {}", self.text)
}
}
impl std::error::Error for LineTextError {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LineText {
inner: Rc<String>,
}
impl LineText {
pub fn new<T: Into<String>>(
text: T,
) -> Result<Self, LineTextError> {
let text: String = text.into();
if !text.ends_with('\n') || text[..text.len()-1].contains('\n') {
Err(LineTextError{text})
} else {
Ok(Self{ inner: Rc::new(text) })
}
}
}
impl std::ops::Deref for LineText {
type Target = String;
fn deref(&self) -> &Self::Target {
&(*self.inner)
}
}
impl TryFrom<&str> for LineText {
type Error = LineTextError;
fn try_from(t: &str) -> Result<Self, Self::Error> {
Self::new(t)
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Line {
pub(crate) matched: Rc<RefCell<Vec<bool>>>,
tag: Rc<Cell<char>>,
pub text: LineText,
}
impl Line {
pub (crate) fn new<T: Into<String>>(
text: T,
) -> Result<Self, LineTextError> {
Ok(Self{
matched: Rc::new(RefCell::new(Vec::new())),
tag: Rc::new(Cell::new('\0')),
text: LineText::new(text)?,
})
}
pub fn tag(&self) -> char {
self.tag.get()
}
pub fn set_tag(&self, new: char) {
self.tag.set(new)
}
}
impl Snapshot for Line {
fn create_snapshot(&self) -> Self {
Line{
tag: self.tag.clone(),
matched: self.matched.clone(),
text: self.text.clone(),
}
}
}
impl From<&PubLine> for Line {
fn from(l: &PubLine) -> Self {
Self{
text: l.text.clone(),
tag: Rc::new(Cell::new(l.tag)),
matched: Rc::new(RefCell::new(Vec::new())),
}
}
}
impl TryFrom<&str> for Line {
type Error = LineTextError;
fn try_from(t: &str) -> Result<Self, Self::Error> {
Self::new(t)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PubLine {
pub tag: char,
pub text: LineText,
}
impl<'a> TryFrom<&'a str> for PubLine {
type Error = LineTextError;
fn try_from(t: &str) -> Result<Self, Self::Error> {
Ok(Self{tag: '\0', text: LineText::new(t)?})
}
}
impl<'a> TryFrom<&'a &'a str> for PubLine {
type Error = LineTextError;
fn try_from(t: &&str) -> Result<Self, Self::Error> {
Ok(Self{tag: '\0', text: LineText::new(*t)?})
}
}
impl<'a> TryFrom<(char, &'a str)> for PubLine {
type Error = LineTextError;
fn try_from(l: (char, &str)) -> Result<Self, Self::Error> {
(&l).try_into()
}
}
impl<'a> TryFrom<&'a (char, &'a str)> for PubLine {
type Error = LineTextError;
fn try_from(l: &(char, &str)) -> Result<Self, Self::Error> {
Ok(Self{tag: l.0, text: LineText::new(l.1)?})
}
}
impl From<&Line> for PubLine {
fn from(l: &Line) -> Self {
Self{tag: l.tag.get(), text: l.text.clone()}
}
}