// The type IR (upstream typify-impl/src/type_entry.rs). Rust type names
// (e.g. "i64", "::uuid::Uuid") are kept verbatim as upstream does; the
// MoonBit backend maps them to MoonBit types.
///|
/// Shared default-value helper functions (`defaults::default_*`).
pub(all) enum DefaultImpl {
Boolean
I64
U64
NZU64
} derive(Eq, Compare, Debug)
///|
pub fn DefaultImpl::fn_name(self : DefaultImpl) -> String {
match self {
Boolean => "default_bool"
I64 => "default_i64"
U64 => "default_u64"
NZU64 => "default_nzu64"
}
}
///|
/// Traits a type may be known to implement.
pub(all) enum TypeSpaceImpl {
FromStr
FromStringIrrefutable
Display
Default
} derive(Eq, Compare, Hash, Debug)
///|
/// Parse an impl name as accepted in settings ("FromStr", "Display",
/// "Default").
pub fn TypeSpaceImpl::parse(s : String) -> TypeSpaceImpl raise TypifyError {
match s {
"FromStr" => FromStr
"Display" => Display
"Default" => Default
_ => raise panic_with("\{s} is not a valid trait specifier")
}
}
///|
pub(all) enum TypeEntryEnumImpl {
AllSimpleVariants
UntaggedFromStr
UntaggedDisplay
UntaggedFromStringIrrefutable
} derive(Eq, Compare, Debug)
///|
pub(all) enum EnumTagType {
External
Internal(tag~ : String)
Adjacent(tag~ : String, content~ : String)
Untagged
} derive(Eq, Debug)
///|
pub(all) enum StructPropertyRename {
NoRename
Rename(String)
Flatten
} derive(Eq, Debug)
///|
pub(all) enum StructPropertyState {
Required
Optional
Default(@serde_json.Value)
} derive(Eq, Debug)
///|
pub(all) struct StructProperty {
name : String
rename : StructPropertyRename
state : StructPropertyState
description : String?
type_id : TypeId
} derive(Eq, Debug)
///|
pub(all) enum VariantDetails {
Simple
Item(TypeId)
Tuple(Array[TypeId])
Struct(Array[StructProperty])
} derive(Eq, Debug)
///|
pub(all) struct Variant {
raw_name : String
ident_name : String?
description : String?
details : VariantDetails
} derive(Eq, Debug)
///|
pub fn Variant::new(
raw_name : String,
description : String?,
details : VariantDetails,
) -> Variant {
{ raw_name, ident_name: None, description, details, }
}
///|
pub(all) struct TypeEntryEnum {
name : String
rename : String?
description : String?
default : @serde_json.Value?
tag_type : EnumTagType
variants : Array[Variant]
deny_unknown_fields : Bool
bespoke_impls : Array[TypeEntryEnumImpl]
schema : @schema.Schema
} derive(Eq, Debug)
///|
pub(all) struct TypeEntryStruct {
name : String
rename : String?
description : String?
default : @serde_json.Value?
properties : Array[StructProperty]
deny_unknown_fields : Bool
schema : @schema.Schema
} derive(Eq, Debug)
///|
pub(all) enum TypeEntryNewtypeConstraints {
NoConstraints
EnumValue(Array[@serde_json.Value])
DenyValue(Array[@serde_json.Value])
String(max_length~ : UInt?, min_length~ : UInt?, pattern~ : String?)
} derive(Eq, Debug)
///|
pub(all) struct TypeEntryNewtype {
name : String
rename : String?
description : String?
default : @serde_json.Value?
type_id : TypeId
constraints : TypeEntryNewtypeConstraints
schema : @schema.Schema
} derive(Eq, Debug)
///|
pub(all) struct TypeEntryNative {
type_name : String
impls : Array[TypeSpaceImpl]
parameters : Array[TypeId]
} derive(Eq, Debug)
///|
/// Whether a native type's last path segment matches a required type name.
pub fn TypeEntryNative::name_match(
self : TypeEntryNative,
type_name : Name,
) -> Bool {
let segments = self.type_name.split("::").collect()
let native_name = segments[segments.length() - 1].to_owned()
!self.parameters.is_empty() ||
(type_name is Required(req) && req == native_name)
}
///|
pub(all) enum TypeEntryDetails {
Enum(TypeEntryEnum)
Struct(TypeEntryStruct)
Newtype(TypeEntryNewtype)
/// A type exported from a well-known crate.
Native(TypeEntryNative)
Option(TypeId)
Box(TypeId)
Vec(TypeId)
Map(TypeId, TypeId)
Set(TypeId)
Array(TypeId, Int)
Tuple(Array[TypeId])
Unit
Boolean
/// Integers, with their Rust type name.
Integer(String)
/// Floats, with their Rust type name.
Float(String)
String
JsonValue
/// Only used during conversion for aliases between named definitions.
Reference(TypeId)
} derive(Eq, Debug)
///|
pub(all) struct TypeEntry {
details : TypeEntryDetails
extra_derives : @collections.StrSet
extra_attrs : @collections.StrSet
} derive(Eq, Debug)
///|
pub fn TypeEntry::from_details(details : TypeEntryDetails) -> TypeEntry {
{
details,
extra_derives: @collections.StrSet::new(),
extra_attrs: @collections.StrSet::new(),
}
}
///|
pub fn TypeEntry::new_native(
type_name : String,
impls : Array[TypeSpaceImpl],
) -> TypeEntry {
TypeEntry::from_details(Native({ type_name, impls, parameters: [], }))
}
///|
pub fn TypeEntry::new_native_params(
type_name : String,
parameters : Array[TypeId],
) -> TypeEntry {
TypeEntry::from_details(Native({ type_name, impls: [], parameters, }))
}
///|
pub fn TypeEntry::new_integer(type_name : String) -> TypeEntry {
TypeEntry::from_details(Integer(type_name))
}
///|
pub fn TypeEntry::new_float(type_name : String) -> TypeEntry {
TypeEntry::from_details(Float(type_name))
}
///|
/// The name of a named (enum, struct or newtype) type.
pub fn TypeEntry::name(self : TypeEntry) -> String? {
match self.details {
Enum({ name, .. }) | Struct({ name, .. }) | Newtype({ name, .. }) =>
Some(name)
_ => None
}
}
///|
/// Replace the `default` of a named type (no-op for other types).
fn TypeEntry::with_default(
self : TypeEntry,
default : @serde_json.Value?,
) -> TypeEntry {
let details : TypeEntryDetails = match self.details {
Enum(e) => Enum({ ..e, default, })
Struct(s) => Struct({ ..s, default, })
Newtype(n) => Newtype({ ..n, default, })
other => other
}
{ ..self, details, }
}
///|
/// Structural key of an unnamed type, standing in for upstream's derived
/// `Ord` on `TypeEntryDetails` in the `type_to_id` map.
fn TypeEntryDetails::dedup_key(self : TypeEntryDetails) -> String {
let ids = (xs : Array[TypeId]) => xs.map(x => x.0.to_string()).join(",")
match self {
Native({ type_name, impls, parameters, }) =>
"Native(\{type_name};\{impls.map(i => Repr(i).to_string()).join(",")};\{ids(parameters)})"
Option(t) => "Option(\{t.0})"
Box(t) => "Box(\{t.0})"
Vec(t) => "Vec(\{t.0})"
Map(k, v) => "Map(\{k.0},\{v.0})"
Set(t) => "Set(\{t.0})"
Array(t, n) => "Array(\{t.0},\{n})"
Tuple(ts) => "Tuple(\{ids(ts)})"
Unit => "Unit"
Boolean => "Boolean"
Integer(n) => "Integer(\{n})"
Float(n) => "Float(\{n})"
String => "String"
JsonValue => "JsonValue"
Enum(_) | Struct(_) | Newtype(_) | Reference(_) =>
abort("dedup_key on a named or reference type")
}
}