use std::fmt;
use serde::{Serialize, Deserialize};
use crate::AntelopeType;
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TypeName<'a>(pub &'a str);
impl<'a> TypeName<'a> {
pub fn as_str(&self) -> &'a str {
self.0
}
pub fn is_array(&self) -> bool {
self.0.ends_with("[]")
}
pub fn is_sized_array(&self) -> bool {
match (self.0.rfind('['), self.0.rfind(']')) {
(Some(pos1), Some(pos2)) => {
if pos1 + 1 < pos2 {
self.0[pos1 + 1..pos2].chars().all(|c| c.is_ascii_digit())
}
else {
false
}
},
_ => false,
}
}
pub fn is_optional(&self) -> bool {
self.0.ends_with('?')
}
pub fn is_integer(&self) -> bool {
self.0.starts_with("int") || self.0.starts_with("uint")
}
pub fn fundamental_type(&self) -> TypeName<'a> {
if self.is_array() {
TypeName(&self.0[..self.0.len() - 2])
}
else if self.is_sized_array() {
TypeName(&self.0[..self.0.rfind('[').unwrap()]) }
else if self.is_optional() {
TypeName(&self.0[..self.0.len() - 1])
}
else {
*self
}
}
pub fn has_bin_extension(&self) -> bool {
self.0.ends_with('$')
}
pub fn remove_bin_extension(&self) -> TypeName<'a> {
if self.0.ends_with('$') {
TypeName(&self.0[..self.0.len()-1])
}
else {
*self
}
}
}
impl fmt::Debug for TypeName<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Display for TypeName<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<'a> From<&'a String> for TypeName<'a> {
fn from(t: &String) -> TypeName<'_> {
TypeName(t.as_str())
}
}
impl<'a> From<&'a str> for TypeName<'a> {
fn from(t: &str) -> TypeName<'_> {
TypeName(t)
}
}
impl<'a> From<TypeName<'a>> for &'a str {
fn from(t: TypeName<'_>) -> &str {
t.0
}
}
impl<'a> TryFrom<TypeName<'a>> for AntelopeType {
type Error = strum::ParseError;
fn try_from(value: TypeName<'a>) -> Result<Self, Self::Error> {
AntelopeType::try_from(value.0)
}
}
impl<'a> std::ops::Deref for TypeName<'a> {
type Target = &'a str;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl PartialEq<str> for TypeName<'_> {
fn eq(&self, other: &str) -> bool {
self.0 == other
}
}
impl PartialEq<String> for TypeName<'_> {
fn eq(&self, other: &String) -> bool {
self.0 == other
}
}
impl<'a> PartialEq<TypeName<'a>> for String {
fn eq(&self, other: &TypeName<'a>) -> bool {
self == other.0
}
}