use alloc::{boxed::Box, string::String, vec::Vec};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub enum Part<T> {
Str(String),
Fun(T),
}
impl<T> Part<T> {
pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Part<U> {
match self {
Self::Str(s) => Part::Str(s),
Self::Fun(x) => Part::Fun(f(x)),
}
}
pub fn is_empty(&self) -> bool {
match self {
Self::Str(s) => s.is_empty(),
Self::Fun(_) => false,
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct Str<T> {
pub fmt: Option<Box<T>>,
pub parts: Vec<Part<T>>,
}
impl<T> Str<T> {
pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Str<U> {
Str {
fmt: self.fmt.map(|fmt| Box::new(f(*fmt))),
parts: self.parts.into_iter().map(|p| p.map(&mut f)).collect(),
}
}
}
impl<T> From<String> for Str<T> {
fn from(s: String) -> Self {
Self {
fmt: None,
parts: Vec::from([Part::Str(s)]),
}
}
}