use std::fmt::Debug; use std::fmt::Display; use super::TypeNamespaceId; use super::GlobalNamespace; use super::r#trait::Trait; use super::r#type::Type; pub enum TypeDef<'a> { Type(Type<'a>), Trait(Trait<'a>), List(Vec>), Record(Vec<(String, TypeDef<'a>)>), } impl<'a> TypeDef<'a> { pub(super) fn from_internal(ns: &'a GlobalNamespace, def: &InternalTypeDef) -> TypeDef<'a> { match def { InternalTypeDef::Single(id) => match id { // safe to unwrap because this is only used with internal representations TypeNamespaceId::Types(id) => TypeDef::Type( ns.get_type(*id) .expect("Incorrect internal type id. This is a bug."), ), TypeNamespaceId::Traits(id) => TypeDef::Trait( ns.get_trait(*id) .expect("Incorrect internal trait id. This is a bug."), ), }, InternalTypeDef::List(list) => TypeDef::List( list.iter() .map(|def| Self::from_internal(ns, def)) .collect(), ), InternalTypeDef::Record(rec) => TypeDef::Record( rec.iter() .map(|(name, def)| (name.clone(), Self::from_internal(ns, def))) .collect(), ), } } } impl Display for TypeDef<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TypeDef::Type(t) => Display::fmt(&t, f), TypeDef::Trait(t) => Display::fmt(&t, f), TypeDef::List(l) => { f.write_str("[ ")?; for (i, item) in l.iter().enumerate() { if i != 0 { f.write_str(", ")?; } Display::fmt(&item, f)?; } f.write_str(" ]") } TypeDef::Record(rec) => { f.write_str("{ ")?; for (i, item) in rec.iter().enumerate() { if i != 0 { f.write_str(", ")?; } f.write_fmt(format_args!("{}: {}", item.0, item.1))?; } f.write_str(" }") } } } } impl Debug for TypeDef<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TypeDef::Type(t) => Debug::fmt(&t, f), TypeDef::Trait(t) => Debug::fmt(&t, f), TypeDef::List(l) => { f.write_str("[ ")?; for (i, item) in l.iter().enumerate() { if i != 0 { f.write_str(", ")?; } Debug::fmt(&item, f)?; } f.write_str(" ]") } TypeDef::Record(rec) => { f.write_str("{ ")?; for (i, item) in rec.iter().enumerate() { if i != 0 { f.write_str(", ")?; } f.write_fmt(format_args!("{:?}: {:?}", item.0, item.1))?; } f.write_str(" }") } } } } pub(super) enum InternalTypeDef { Single(TypeNamespaceId), List(Vec), Record(Vec<(String, InternalTypeDef)>), } impl From> for InternalTypeDef { fn from(value: TypeDef) -> Self { match value { TypeDef::Type(val) => Self::Single(TypeNamespaceId::Types(val.id)), TypeDef::Trait(val) => Self::Single(TypeNamespaceId::Traits(val.id)), TypeDef::List(list) => Self::List(list.into_iter().map(std::convert::Into::into).collect()), TypeDef::Record(rec) => Self::Record( rec.into_iter() .map(|(name, typ)| (name, typ.into())) .collect(), ), } } }