use derive_more::{Constructor, Deref, DerefMut};
use std::fmt::{Debug, Display, Formatter};
use crate::{
join, join_debug,
path::{Key, Path},
raw::raw_value::{
RAW_CONCAT_STRING_TYPE, RAW_MULTILINE_STRING_TYPE, RAW_QUOTED_STRING_TYPE,
RAW_UNQUOTED_STRING_TYPE,
},
};
#[derive(Clone, Eq, PartialEq, Hash)]
pub enum RawString {
QuotedString(String),
UnquotedString(String),
MultilineString(String),
PathExpression(PathExpression),
}
#[derive(Clone, Eq, PartialEq, Hash, Constructor, Deref, DerefMut)]
pub struct PathExpression(Vec<RawString>);
impl PathExpression {
pub fn into_inner(self) -> Vec<RawString> {
self.0
}
}
impl Debug for PathExpression {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
join_debug(self.iter(), ".", f)
}
}
impl Display for PathExpression {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
join(self.iter(), ".", f)
}
}
impl From<&str> for RawString {
fn from(val: &str) -> Self {
if val.chars().any(|c| c == '\n') {
RawString::multiline(val)
} else {
RawString::quoted(val)
}
}
}
impl From<String> for RawString {
fn from(val: String) -> Self {
if val.chars().any(|c| c == '\n') {
RawString::multiline(val)
} else {
RawString::quoted(val)
}
}
}
impl RawString {
pub fn ty(&self) -> &'static str {
match self {
RawString::QuotedString(_) => RAW_QUOTED_STRING_TYPE,
RawString::UnquotedString(_) => RAW_UNQUOTED_STRING_TYPE,
RawString::MultilineString(_) => RAW_MULTILINE_STRING_TYPE,
RawString::PathExpression(_) => RAW_CONCAT_STRING_TYPE,
}
}
pub fn as_path(&self) -> Vec<&str> {
match self {
RawString::QuotedString(s)
| RawString::UnquotedString(s)
| RawString::MultilineString(s) => vec![s],
RawString::PathExpression(c) => c.iter().flat_map(|s| s.as_path()).collect(),
}
}
pub fn into_path(self) -> Path {
match self {
RawString::QuotedString(s)
| RawString::UnquotedString(s)
| RawString::MultilineString(s) => Path::new(Key::String(s), None),
RawString::PathExpression(c) => {
let mut dummy = Path::new(Key::String("".to_string()), None);
let mut curr = &mut dummy;
for path in c.into_inner() {
curr.remainder = Some(Box::new(path.into_path()));
curr = curr.remainder.as_mut().unwrap();
}
*dummy.remainder.expect("empty path found")
}
}
}
pub fn quoted(string: impl Into<String>) -> Self {
Self::QuotedString(string.into())
}
pub fn unquoted(string: impl Into<String>) -> Self {
Self::UnquotedString(string.into())
}
pub fn multiline(string: impl Into<String>) -> Self {
Self::MultilineString(string.into())
}
pub fn path_expression(paths: Vec<RawString>) -> Self {
Self::PathExpression(PathExpression::new(paths))
}
}
impl Display for RawString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
RawString::QuotedString(s) => write!(f, "{}", s),
RawString::UnquotedString(s) => write!(f, "{}", s),
RawString::MultilineString(s) => write!(f, "{}", s),
RawString::PathExpression(s) => write!(f, "{}", s),
}
}
}
impl Debug for RawString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::QuotedString(s) => {
write!(f, "\"{:?}\"", s)
}
Self::UnquotedString(s) => {
write!(f, "{:?}", s)
}
Self::MultilineString(s) => {
write!(f, "\"\"\"{:?}\"\"\"", s)
}
Self::PathExpression(s) => {
write!(f, "{:?}", s)
}
}
}
}