Skip to content

Commit

Permalink
Introduce Map type + List.unique
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Dec 25, 2023
1 parent 15545c5 commit 12a341c
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 40 deletions.
6 changes: 6 additions & 0 deletions src/datatype/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ pub struct List {
pub(crate) ty: Box<DataType>,
// Length is set for `[Type; N]` arrays.
pub(crate) length: Option<usize>,
// Are each elements unique? Eg. `HashSet` or `BTreeSet`
pub(crate) unique: bool,
}

impl List {
Expand All @@ -16,4 +18,8 @@ impl List {
pub fn length(&self) -> Option<usize> {
self.length
}

pub fn unique(&self) -> bool {
self.unique
}
}
21 changes: 21 additions & 0 deletions src/datatype/map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::DataType;

#[derive(Debug, Clone, PartialEq)]

pub struct Map {
// TODO: Box these fields together as an internal optimization.
// The type of the map keys.
pub(crate) key_ty: Box<DataType>,
// The type of the map values.
pub(crate) value_ty: Box<DataType>,
}

impl Map {
pub fn key_ty(&self) -> &DataType {
&self.key_ty
}

pub fn value_ty(&self) -> &DataType {
&self.value_ty
}
}
4 changes: 3 additions & 1 deletion src/datatype/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod r#enum;
mod fields;
mod list;
mod literal;
mod map;
mod named;
mod primitive;
pub mod reference;
Expand All @@ -16,6 +17,7 @@ mod tuple;
pub use fields::*;
pub use list::*;
pub use literal::*;
pub use map::*;
pub use named::*;
pub use primitive::*;
pub use r#enum::*;
Expand All @@ -36,8 +38,8 @@ pub enum DataType {
Literal(LiteralType),
/// Either a `Set` or a `Vec`
List(List),
Map(Map),
Nullable(Box<DataType>),
Map(Box<(DataType, DataType)>),
// Anonymous Reference types
Struct(StructType),
Enum(EnumType),
Expand Down
4 changes: 2 additions & 2 deletions src/lang/ts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ pub(crate) fn datatype_inner(ctx: ExportContext, typ: &DataType, type_map: &Type
format!(
// We use this isn't of `Record<K, V>` to avoid issues with circular references.
"{{ [key in {}]: {} }}",
datatype_inner(ctx.clone(), &def.0, type_map)?,
datatype_inner(ctx, &def.1, type_map)?
datatype_inner(ctx.clone(), def.key_ty(), type_map)?,
datatype_inner(ctx, def.value_ty(), type_map)?
)
}
// We use `T[]` instead of `Array<T>` to avoid issues with circular references.
Expand Down
15 changes: 8 additions & 7 deletions src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use thiserror::Error;

use crate::{
internal::{skip_fields, skip_fields_named},
DataType, EnumRepr, EnumType, EnumVariants, GenericType, List, LiteralType, PrimitiveType,
DataType, EnumRepr, EnumType, EnumVariants, GenericType, List, LiteralType, Map, PrimitiveType,
SpectaID, StructFields, TypeMap,
};

Expand Down Expand Up @@ -35,8 +35,8 @@ fn is_valid_ty_internal(
match dt {
DataType::Nullable(ty) => is_valid_ty(ty, type_map)?,
DataType::Map(ty) => {
is_valid_map_key(&ty.0, type_map)?;
is_valid_ty_internal(&ty.1, type_map, checked_references)?;
is_valid_map_key(ty.key_ty(), type_map)?;
is_valid_ty_internal(ty.value_ty(), type_map, checked_references)?;
}
DataType::Struct(ty) => match ty.fields() {
StructFields::Unit => {}
Expand Down Expand Up @@ -251,12 +251,13 @@ fn resolve_generics(mut dt: DataType, generics: &Vec<(GenericType, DataType)>) -
DataType::List(v) => DataType::List(List {
ty: Box::new(resolve_generics(*v.ty, generics)),
length: v.length,
unique: v.unique,
}),
DataType::Nullable(v) => DataType::Nullable(Box::new(resolve_generics(*v, generics))),
DataType::Map(v) => DataType::Map(Box::new({
let (k, v) = *v;
(resolve_generics(k, generics), resolve_generics(v, generics))
})),
DataType::Map(v) => DataType::Map(Map {
key_ty: Box::new(resolve_generics(*v.key_ty, generics)),
value_ty: Box::new(resolve_generics(*v.value_ty, generics)),
}),
DataType::Struct(ref mut v) => match &mut v.fields {
StructFields::Unit => dt,
StructFields::Unnamed(f) => {
Expand Down
24 changes: 13 additions & 11 deletions src/type/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ impl_as!(

use std::collections::*;
impl_for_list!(
Vec<T> as "Vec"
VecDeque<T> as "VecDeque"
BinaryHeap<T> as "BinaryHeap"
LinkedList<T> as "LinkedList"
HashSet<T> as "HashSet"
BTreeSet<T> as "BTreeSet"
false; Vec<T> as "Vec"
false; VecDeque<T> as "VecDeque"
false; BinaryHeap<T> as "BinaryHeap"
false; LinkedList<T> as "LinkedList"
true; HashSet<T> as "HashSet"
true; BTreeSet<T> as "BTreeSet"
);

impl<'a, T: Type> Type for &'a [T] {
Expand All @@ -121,6 +121,7 @@ impl<const N: usize, T: Type> Type for [T; N] {
},
),
length: Some(N),
unique: false,
})
}

Expand All @@ -135,6 +136,7 @@ impl<const N: usize, T: Type> Type for [T; N] {
},
),
length: Some(N),
unique: false,
}),
}
}
Expand Down Expand Up @@ -255,7 +257,7 @@ struct Duration {

#[cfg(feature = "indexmap")]
const _: () = {
impl_for_list!(indexmap::IndexSet<T> as "IndexSet");
impl_for_list!(true; indexmap::IndexSet<T> as "IndexSet");
impl_for_map!(indexmap::IndexMap<K, V> as "IndexMap");
impl<K: Type, V: Type> Flatten for indexmap::IndexMap<K, V> {}
};
Expand Down Expand Up @@ -369,10 +371,10 @@ const _: () = {

impl Type for serde_yaml::value::TaggedValue {
fn inline(_: &mut TypeMap, _: &[DataType]) -> DataType {
DataType::Map(Box::new((
DataType::Primitive(PrimitiveType::String),
DataType::Unknown,
)))
DataType::Map(Map {
key_ty: Box::new(DataType::Primitive(PrimitiveType::String)),
value_ty: Box::new(DataType::Unknown),
})
}
}

Expand Down
48 changes: 29 additions & 19 deletions src/type/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ macro_rules! impl_as {
}

macro_rules! impl_for_list {
($($ty:path as $name:expr)+) => {$(
($($unique:expr; $ty:path as $name:expr)+) => {$(
impl<T: Type> Type for $ty {
fn inline(type_map: &mut TypeMap, generics: &[DataType]) -> DataType {
DataType::List(List {
Expand All @@ -108,6 +108,7 @@ macro_rules! impl_for_list {
generics,
))),
length: None,
unique: $unique,
})
}

Expand All @@ -118,6 +119,7 @@ macro_rules! impl_for_list {
|| T::reference(type_map, generics).inner,
)),
length: None,
unique: $unique,
}),
}
}
Expand All @@ -129,30 +131,38 @@ macro_rules! impl_for_map {
($ty:path as $name:expr) => {
impl<K: Type, V: Type> Type for $ty {
fn inline(type_map: &mut TypeMap, generics: &[DataType]) -> DataType {
DataType::Map(Box::new((
generics
.get(0)
.cloned()
.unwrap_or_else(|| K::inline(type_map, generics)),
generics
.get(1)
.cloned()
.unwrap_or_else(|| V::inline(type_map, generics)),
)))
}

fn reference(type_map: &mut TypeMap, generics: &[DataType]) -> Reference {
Reference {
inner: DataType::Map(Box::new((
DataType::Map(crate::datatype::Map {
key_ty: Box::new(
generics
.get(0)
.cloned()
.unwrap_or_else(|| K::reference(type_map, generics).inner),
.unwrap_or_else(|| K::inline(type_map, generics)),
),
value_ty: Box::new(
generics
.get(1)
.cloned()
.unwrap_or_else(|| V::reference(type_map, generics).inner),
))),
.unwrap_or_else(|| V::inline(type_map, generics)),
),
})
}

fn reference(type_map: &mut TypeMap, generics: &[DataType]) -> Reference {
Reference {
inner: DataType::Map(crate::datatype::Map {
key_ty: Box::new(
generics
.get(0)
.cloned()
.unwrap_or_else(|| K::inline(type_map, generics)),
),
value_ty: Box::new(
generics
.get(1)
.cloned()
.unwrap_or_else(|| V::inline(type_map, generics)),
),
}),
}
}
}
Expand Down

0 comments on commit 12a341c

Please sign in to comment.