148 lines
4.2 KiB
Rust
148 lines
4.2 KiB
Rust
#![allow(clippy::module_name_repetitions)]
|
|
|
|
use std::{borrow::Cow, collections::HashSet, ops::Add};
|
|
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub enum MacroString {
|
|
String(String),
|
|
MacroString(Vec<MacroStringPart>),
|
|
}
|
|
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub enum MacroStringPart {
|
|
String(String),
|
|
MacroUsage(String),
|
|
}
|
|
|
|
impl MacroString {
|
|
/// Returns whether the [`MacroString`] contains any macro usages
|
|
#[must_use]
|
|
pub fn contains_macro(&self) -> bool {
|
|
match self {
|
|
Self::String(_) => false,
|
|
Self::MacroString(parts) => !parts
|
|
.iter()
|
|
.all(|p| matches!(p, MacroStringPart::String(_))),
|
|
}
|
|
}
|
|
|
|
/// Compiles to a string that Minecraft can interpret
|
|
#[must_use]
|
|
pub fn compile(&self) -> String {
|
|
match self {
|
|
Self::String(s) => s.to_owned(),
|
|
Self::MacroString(parts) => parts
|
|
.iter()
|
|
.map(|p| match p {
|
|
MacroStringPart::String(s) => Cow::Borrowed(s),
|
|
MacroStringPart::MacroUsage(m) => Cow::Owned(format!("$({m})")),
|
|
})
|
|
.collect::<Vec<_>>()
|
|
.iter()
|
|
.map(|p| p.as_str())
|
|
.collect::<Vec<_>>()
|
|
.join(""),
|
|
}
|
|
}
|
|
|
|
/// Returns the amount of lines the string has
|
|
#[must_use]
|
|
pub fn line_count(&self) -> usize {
|
|
match self {
|
|
Self::String(s) => s.split('\n').count(),
|
|
Self::MacroString(parts) => {
|
|
parts
|
|
.iter()
|
|
.map(|p| match p {
|
|
MacroStringPart::String(s) => s.split('\n').count() - 1,
|
|
MacroStringPart::MacroUsage(_) => 0,
|
|
})
|
|
.sum::<usize>()
|
|
+ 1
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Returns the names of the macros used in the [`MacroString`]
|
|
#[must_use]
|
|
pub fn get_macros(&self) -> HashSet<&str> {
|
|
match self {
|
|
Self::String(_) => HashSet::new(),
|
|
Self::MacroString(parts) => parts
|
|
.iter()
|
|
.filter_map(|p| match p {
|
|
MacroStringPart::String(_) => None,
|
|
MacroStringPart::MacroUsage(m) => Some(m.as_str()),
|
|
})
|
|
.collect(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<String> for MacroString {
|
|
fn from(value: String) -> Self {
|
|
Self::String(value)
|
|
}
|
|
}
|
|
impl From<&str> for MacroString {
|
|
fn from(value: &str) -> Self {
|
|
Self::String(value.to_string())
|
|
}
|
|
}
|
|
|
|
impl From<String> for MacroStringPart {
|
|
fn from(value: String) -> Self {
|
|
Self::String(value)
|
|
}
|
|
}
|
|
impl From<&str> for MacroStringPart {
|
|
fn from(value: &str) -> Self {
|
|
Self::String(value.to_string())
|
|
}
|
|
}
|
|
|
|
impl Add for MacroString {
|
|
type Output = Self;
|
|
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
match (self, rhs) {
|
|
(Self::String(mut s1), Self::String(s2)) => {
|
|
s1.push_str(&s2);
|
|
Self::String(s1)
|
|
}
|
|
(Self::String(s1), Self::MacroString(s2)) => Self::MacroString(
|
|
std::iter::once(MacroStringPart::String(s1))
|
|
.chain(s2)
|
|
.collect(),
|
|
),
|
|
(Self::MacroString(mut s1), Self::String(s2)) => {
|
|
s1.push(MacroStringPart::String(s2));
|
|
Self::MacroString(s1)
|
|
}
|
|
(Self::MacroString(mut s1), Self::MacroString(s2)) => {
|
|
s1.extend(s2);
|
|
Self::MacroString(s1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Add<&str> for MacroString {
|
|
type Output = Self;
|
|
|
|
fn add(self, rhs: &str) -> Self::Output {
|
|
match self {
|
|
Self::String(mut s1) => {
|
|
s1.push_str(rhs);
|
|
Self::String(s1)
|
|
}
|
|
Self::MacroString(mut s1) => {
|
|
s1.push(MacroStringPart::String(rhs.to_string()));
|
|
Self::MacroString(s1)
|
|
}
|
|
}
|
|
}
|
|
}
|