use crate::custom_types::Type;
use alloc::fmt::{Display, Formatter, Result as FmtResult};
#[derive(PartialEq, Eq, Debug)]
pub enum StaticType {
Static,
Const,
}
impl Display for StaticType {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Self::Const => write!(f, "const"),
Self::Static => write!(f, "static"),
}
}
}
pub struct StaticInterface<'a> {
pub vis: &'a str,
pub item_type: StaticType,
pub name: &'a str,
pub value_type: Type<'a>,
pub mutability: bool,
}
impl<'a> StaticInterface<'a> {
pub fn new(mut a: &'a str) -> Result<Self, &'static str> {
a = a.trim();
let vis = if a.starts_with('p') {
let mut index = match a.find(|c: char| c == ':') {
Some(i) => i,
None => return Err("No ':' in global object."),
};
let temp = &a[..index];
index = if temp.contains("(") {
match temp.find(')') {
Some(i) => i,
None => return Err("Detected unmatched '(' in visibility path."),
}
} else {
match temp.find(|c: char| c.is_ascii_whitespace()) {
Some(i) => i - 1,
None => return Err("Expected whitespace after visibility keyword."),
}
};
a = &a[index + 1..].trim();
&temp[..=index]
} else {
""
};
let (mut a, item_type) = Self::get_static_type(a);
let item_type = item_type?;
let mut mutability = false;
let mut index = match a.find(|c: char| c.is_ascii_alphabetic()) {
Some(i) => i,
None => return Err("Expected letters after keyword."),
};
a = &a[index..];
index = match a.find(|c: char| !c.is_ascii_alphabetic()) {
Some(i) => i,
None => return Err("Expected tokens after name or 'mut' keyword."),
};
let mut name = &a[..index];
if item_type == StaticType::Static && name == "mut" {
mutability = true;
a = &a[index..];
index = match a.find(|c: char| c.is_ascii_alphabetic()) {
Some(i) => i,
None => return Err("Expected letters after 'mut' keyword."),
};
a = &a[index..];
index = match a.find(':') {
Some(i) => i,
None => return Err("Expected ':' after name."),
};
name = &a[..index].trim_end();
}
a = &a[index + 1..];
index = a.find(';').unwrap_or_else(|| a.len());
let value_type = Type::new((&a[..index]).trim());
Ok(Self {
vis,
name,
item_type,
value_type,
mutability,
})
}
fn get_static_type(mut a: &str) -> (&str, Result<StaticType, &'static str>) {
a = a.trim();
let index = (match (&a[4..]).find(|c: char| c.is_ascii_whitespace()) {
Some(i) => i,
None => return (a, Err("Expected a whitespace after the keyword.")),
}) + 4;
let m = &a[..index];
a = &a[index + 1..];
(
a,
match m {
"const" => Ok(StaticType::Const),
"static" => Ok(StaticType::Static),
_ => Err("Expected either 'const' or 'static' at start of the passed item."),
},
)
}
}
impl<'a> Display for StaticInterface<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
if self.mutability {
if self.vis == "" {
write!(
f,
"{} mut {}: {};",
self.item_type, self.name, self.value_type
)
} else {
write!(
f,
"{} {} mut {}: {};",
self.vis, self.item_type, self.name, self.value_type
)
}
} else {
if self.vis == "" {
write!(f, "{} {}: {};", self.item_type, self.name, self.value_type)
} else {
write!(
f,
"{} {} {}: {};",
self.vis, self.item_type, self.name, self.value_type
)
}
}
}
}
pub struct Static<'a> {
pub interface: StaticInterface<'a>,
pub value: &'a str,
}
impl<'a> Static<'a> {
pub fn new(mut tp: &'a str) -> Result<Self, &'static str> {
tp = tp.trim();
let mut open_brace_count = 0;
let mut index = match tp.find(|c: char| {
if c == '<' || c == '(' || c == '[' || c == '{' {
open_brace_count += 1;
return false;
}
if c == '>' || c == ')' || c == ']' || c == '}' {
open_brace_count -= 1;
return false;
}
if open_brace_count > 0 {
return false;
}
c == '='
}) {
Some(i) => i,
None => return Err("Expected assign operator '=' in the static item."),
};
let interface = StaticInterface::new(&tp[..index])?;
tp = &tp[index + 1..];
index = tp.rfind(';').unwrap_or_else(|| tp.len());
Ok(Self {
interface,
value: &tp[..index].trim_start(),
})
}
}
impl<'a> Display for Static<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
if self.interface.mutability {
if self.interface.vis == "" {
write!(
f,
"{} mut {}: {} = {};",
self.interface.item_type,
self.interface.name,
self.interface.value_type,
self.value
)
} else {
write!(
f,
"{} {} mut {}: {} = {};",
self.interface.vis,
self.interface.item_type,
self.interface.name,
self.interface.value_type,
self.value
)
}
} else {
if self.interface.vis == "" {
write!(
f,
"{} {}: {} = {};",
self.interface.item_type,
self.interface.name,
self.interface.value_type,
self.value
)
} else {
write!(
f,
"{} {} {}: {} = {};",
self.interface.vis,
self.interface.item_type,
self.interface.name,
self.interface.value_type,
self.value
)
}
}
}
}