1use alloc::{boxed::Box, string::String, vec::Vec};
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8#[derive(Clone, Debug)]
9pub enum Part<T> {
10 Str(String),
12 Fun(T),
14}
15
16impl<T> Part<T> {
17 pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Part<U> {
19 match self {
20 Self::Str(s) => Part::Str(s),
21 Self::Fun(x) => Part::Fun(f(x)),
22 }
23 }
24
25 pub fn is_empty(&self) -> bool {
27 match self {
28 Self::Str(s) => s.is_empty(),
29 Self::Fun(_) => false,
30 }
31 }
32}
33
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[derive(Clone, Debug)]
37pub struct Str<T> {
38 pub fmt: Option<Box<T>>,
41 pub parts: Vec<Part<T>>,
43}
44
45impl<T> Str<T> {
46 pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Str<U> {
48 Str {
49 fmt: self.fmt.map(|fmt| Box::new(f(*fmt))),
50 parts: self.parts.into_iter().map(|p| p.map(&mut f)).collect(),
51 }
52 }
53}
54
55impl<T> From<String> for Str<T> {
56 fn from(s: String) -> Self {
57 Self {
58 fmt: None,
59 parts: Vec::from([Part::Str(s)]),
60 }
61 }
62}