chara_card 0.4.1

A library to deal with character card formats and `.charx` in Rust.
Documentation
use crate::raw::cbs::Node;
use crate::raw::decorator;
use crate::raw::decorator::Decorator;
use crate::raw::resolve::Resolve;
use crate::raw::{cbs, Error};
use serdev::{Deserialize, Deserializer, Serialize, Serializer};
use std::borrow::Cow;
use std::ops::Range;

/// Represents abstraction over `content` field in lorebook entry.
#[derive(Debug, Clone)]
pub struct Content {
    content: String,
    decorators: Vec<Decorator>,
    parts: Vec<Node>,
}

impl Content {
    /// Gets decorators attached to this content.
    pub fn decorators(&self) -> &[Decorator] {
        &self.decorators
    }

    /// Gets parts of this content.
    ///
    /// Each part can be text or evaluatable node,
    /// and these nodes need to be evaluated to be represented as string.
    pub fn parts(&self) -> &[Node] {
        &self.parts
    }
}

impl Resolve<Range<usize>> for Content {
    fn resolve(&'_ self, value: Range<usize>) -> Cow<'_, str> {
        Cow::Borrowed(&self.as_ref()[value])
    }
}

impl AsRef<str> for Content {
    fn as_ref(&self) -> &str {
        &self.content
    }
}

impl TryFrom<String> for Content {
    type Error = Error;

    fn try_from(value: String) -> Result<Self, Self::Error> {
        let (range, decorators) = decorator::extract(&value)?;
        let offset = range.start;
        let parts = cbs::parse(&value[offset..], offset).map_err(Error::CBS)?;

        Ok(Self {
            content: value,
            decorators,
            parts,
        })
    }
}

impl Serialize for Content {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.as_ref())
    }
}

impl<'de> Deserialize<'de> for Content {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        use serdev::de::Error;

        let string = String::deserialize(deserializer)?;
        Self::try_from(string).map_err(D::Error::custom)
    }
}