Skip to content

Commit

Permalink
fixes #142
Browse files Browse the repository at this point in the history
and make `DataTypeFrom` suck more!
  • Loading branch information
oscartbeaumont committed Sep 21, 2023
1 parent 3ea7502 commit 14a2aa6
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 45 deletions.
10 changes: 5 additions & 5 deletions examples/datatype.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This file show how to use an advanced API of Specta.
//! You probably shouldn't be using this in application code but if you're building a library on Specta it will be useful.
use specta::{datatype::LiteralType, ts, DataType, DataTypeFrom, StructType, TupleType};
use specta::{datatype::LiteralType, ts, DataType, DataTypeFrom, StructType};

#[derive(Clone, DataTypeFrom)]
pub struct MyEnum(pub Vec<DataType>);
Expand All @@ -15,16 +15,15 @@ fn main() {
//
// Enum
//
let val: TupleType = MyEnum(vec![
let val: DataType = MyEnum(vec![
LiteralType::String("A".to_string()).into(),
LiteralType::String("B".to_string()).into(),
])
.into();

let anon = val.clone().to_anonymous();
let named = val.to_named("MyEnum");
let named = val.clone().to_named("MyEnum");

let anon = ts::datatype(&Default::default(), &anon, &Default::default()).unwrap();
let anon = ts::datatype(&Default::default(), &val, &Default::default()).unwrap();
let named_export =
ts::export_named_datatype(&Default::default(), &named, &Default::default()).unwrap();

Expand All @@ -45,6 +44,7 @@ fn main() {
}
.into();

// TODO: It's wacky we have `.to_anonymous` on struct types but not enum types. `DataTypeFrom` kinda needs some rethinking.
let anon = val.clone().to_anonymous();
let named = val.to_named("MyObject");

Expand Down
19 changes: 10 additions & 9 deletions macros/src/data_type_from/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,21 @@ pub fn derive(input: proc_macro::TokenStream) -> syn::Result<proc_macro::TokenSt
})
.collect::<Vec<_>>();

quote! {
#[automatically_derived]
impl From<#ident> for #crate_ref::TupleType {
fn from(t: #ident) -> #crate_ref::TupleType {
#crate_ref::internal::construct::tuple(
vec![#(#fields),*]
)
}
let implementation = if fields.len() == 1 {
fields[0].clone()
} else {
quote! {
DataType::Tuple(#crate_ref::internal::construct::tuple(
vec![#(#fields),*]
))
}
};

quote! {
#[automatically_derived]
impl From<#ident> for #crate_ref::DataType {
fn from(t: #ident) -> #crate_ref::DataType {
Self::Tuple(t.into())
#implementation
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/datatype/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,19 @@ impl DataType {
_ => None,
}
}

/// convert a [`DataType`] to a named [`NamedDataType`].
///
/// This is perfect if you want to export a type as a named type.
pub fn to_named(self, name: impl Into<Cow<'static, str>>) -> NamedDataType {
NamedDataType {
name: name.into(),
comments: vec![],
deprecated: None,
ext: None,
inner: self,
}
}
}

/// A reference to a [`DataType`] that can be used before a type is resolved in order to
Expand Down
1 change: 0 additions & 1 deletion src/lang/ts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ fn unnamed_fields_datatype(ctx: ExportContext, fields: &[Field], type_map: &Type
fn tuple_datatype(ctx: ExportContext, tuple: &TupleType, type_map: &TypeMap) -> Output {
match &tuple.fields[..] {
[] => Ok(NULL.to_string()),
[ty] => datatype_inner(ctx, ty, type_map),
tys => Ok(format!(
"[{}]",
tys.iter()
Expand Down
8 changes: 3 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,12 @@ pub use specta_macros::Type;
/// // Enum
/// //
///
/// let val: TupleType = MyEnum(vec![
/// let val: DataType = MyEnum(vec![
/// LiteralType::String("A".to_string()).into(),
/// LiteralType::String("B".to_string()).into(),
/// ])
/// .into();
/// ]).into();
///
/// let anon = val.clone().to_anonymous();
/// let anon = ts::datatype(&Default::default(), &anon, &Default::default()).unwrap();
/// let anon = ts::datatype(&Default::default(), &val, &Default::default()).unwrap();
/// assert_eq!(anon, "\"A\" | \"B\"");
///
/// let named = val.to_named("MyEnum");
Expand Down
2 changes: 1 addition & 1 deletion src/type/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ impl_primitives!(
String
);

impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13); // Technically we only support 12-tuples but the `T13` is required due to how the macro works

const _: () = {
use std::{cell::*, rc::Rc, sync::*};
Expand Down
7 changes: 2 additions & 5 deletions src/type/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@ macro_rules! impl_primitives {
}

macro_rules! impl_tuple {
( impl $i:ident ) => {
impl_tuple!(impl); // This does tuple struct
}; // T = (T1)
( impl $($i:ident),* ) => {
#[allow(non_snake_case)]
impl<$($i: Type + 'static),*> Type for ($($i),*) {
impl<$($i: Type + 'static),*> Type for ($($i,)*) {
#[allow(unused)]
fn inline(opts: DefOpts, generics: &[DataType]) -> DataType {
let mut _generics = generics.iter();
Expand All @@ -38,7 +35,7 @@ macro_rules! impl_tuple {
}
};
( $i2:ident $(, $i:ident)* ) => {
impl_tuple!(impl $i2 $(, $i)* );
impl_tuple!(impl $($i),* );
impl_tuple!($($i),*);
};
() => {};
Expand Down
36 changes: 17 additions & 19 deletions tests/datatype.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use specta::{ts, DataType, DataTypeFrom, LiteralType, StructType, TupleType};
use specta::{ts, DataType, DataTypeFrom, LiteralType, PrimitiveType, StructType, TupleType};

use crate::ts::assert_ts;

Expand Down Expand Up @@ -35,19 +35,18 @@ struct Procedures7();
#[derive(DataTypeFrom)]
struct Procedures8 {}

#[derive(DataTypeFrom)]
struct Procedures9(DataType, DataType);

#[test]
fn test_datatype() {
let val: TupleType = Procedures1(vec![
let val: DataType = Procedures1(vec![
LiteralType::String("A".to_string()).into(),
LiteralType::String("B".to_string()).into(),
])
.into();
assert_eq!(
ts::datatype(
&Default::default(),
&val.clone().to_anonymous(),
&Default::default()
),
ts::datatype(&Default::default(), &val, &Default::default()),
Ok("\"A\" | \"B\"".into())
);
assert_eq!(
Expand Down Expand Up @@ -126,29 +125,21 @@ fn test_datatype() {
Ok("{ queries: { queries: \"A\" | \"B\" } }".into())
);

let val: TupleType = Procedures5(vec![Procedures2 {
let val: DataType = Procedures5(vec![Procedures2 {
queries: vec![
LiteralType::String("A".to_string()).into(),
LiteralType::String("B".to_string()).into(),
],
}])
.into();
assert_eq!(
ts::datatype(
&Default::default(),
&val.clone().to_anonymous(),
&Default::default()
),
ts::datatype(&Default::default(), &val, &Default::default()),
Ok("{ queries: \"A\" | \"B\" }".into())
);

let val: TupleType = Procedures7().into();
let val: DataType = Procedures7().into();
assert_eq!(
ts::datatype(
&Default::default(),
&val.clone().to_anonymous(),
&Default::default()
),
ts::datatype(&Default::default(), &val, &Default::default()),
Ok("null".into()) // This is equivalent of `()` Because this is a `TupleType` not an `EnumType`.
);

Expand All @@ -161,4 +152,11 @@ fn test_datatype() {
),
Ok("Record<string, never>".into())
);

let val: DataType =
Procedures9(DataType::Any, DataType::Primitive(PrimitiveType::String)).into();
assert_eq!(
ts::datatype(&Default::default(), &val, &Default::default()),
Ok("[any, string]".into())
);
}
7 changes: 7 additions & 0 deletions tests/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,13 @@ fn typescript_types() {
"export type MyEmptyInput = Record<string, never>"
);

// https://github.com/oscartbeaumont/specta/issues/142
#[allow(unused_parens)]
{
assert_ts!((String), r#"string"#);
assert_ts!((String,), r#"[string]"#);
}

// assert_ts_export!(DeprecatedType, "");
// assert_ts_export!(DeprecatedTypeWithMsg, "");
// assert_ts_export!(DeprecatedFields, "");
Expand Down

0 comments on commit 14a2aa6

Please sign in to comment.