use crate::atomic::Atomic;
use crate::union::Union;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum SimpleType {
String,
Int,
Float,
Bool,
Mixed,
Null,
Void,
Never,
Complex(Box<Union>),
}
impl SimpleType {
pub fn from_union(u: Union) -> Self {
if !u.possibly_undefined && !u.from_docblock && u.types.len() == 1 {
match &u.types[0] {
Atomic::TString => return Self::String,
Atomic::TInt => return Self::Int,
Atomic::TFloat => return Self::Float,
Atomic::TBool => return Self::Bool,
Atomic::TMixed => return Self::Mixed,
Atomic::TNull => return Self::Null,
Atomic::TVoid => return Self::Void,
Atomic::TNever => return Self::Never,
_ => {}
}
}
Self::Complex(Box::new(u))
}
pub fn to_union(&self) -> Union {
match self {
Self::String => Union::string(),
Self::Int => Union::int(),
Self::Float => Union::float(),
Self::Bool => Union::bool(),
Self::Mixed => Union::mixed(),
Self::Null => Union::null(),
Self::Void => Union::void(),
Self::Never => Union::never(),
Self::Complex(u) => *u.clone(),
}
}
pub fn is_simple(&self) -> bool {
!matches!(self, Self::Complex(_))
}
pub fn as_complex(&self) -> Option<&Union> {
match self {
Self::Complex(u) => Some(u),
_ => None,
}
}
}
impl fmt::Display for SimpleType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::String => write!(f, "string"),
Self::Int => write!(f, "int"),
Self::Float => write!(f, "float"),
Self::Bool => write!(f, "bool"),
Self::Mixed => write!(f, "mixed"),
Self::Null => write!(f, "null"),
Self::Void => write!(f, "void"),
Self::Never => write!(f, "never"),
Self::Complex(u) => write!(f, "{}", u),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simple_scalar_roundtrip() {
let u = Union::string();
let s = SimpleType::from_union(u.clone());
assert_eq!(s, SimpleType::String);
assert_eq!(s.to_union(), u);
}
#[test]
fn nullable_scalar_is_complex() {
let u = Union::nullable(Atomic::TString);
let s = SimpleType::from_union(u.clone());
assert_eq!(s, SimpleType::Complex(Box::new(u.clone())));
assert_eq!(s.to_union(), u);
}
}