diff --git a/Cargo.toml b/Cargo.toml index 15776240..9c19c973 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ typesense_derive = { path = "./typesense_derive", version = "0.3" } anyhow = "1" base64 = "0.22" bon = "3" +chrono = "0.4" clap = { version = "4", features = ["derive"] } hmac = "0.12" indexmap = { version = "2", features = ["serde"] } diff --git a/typesense/Cargo.toml b/typesense/Cargo.toml index 302dd1d5..d0202aa2 100644 --- a/typesense/Cargo.toml +++ b/typesense/Cargo.toml @@ -9,6 +9,7 @@ description = "Client for typesense" [features] default = ["derive"] +chrono = ["dep:chrono"] # Provide derive(Typesense) macro. derive = ["typesense_derive"] @@ -22,6 +23,7 @@ typesense_derive = { workspace = true, optional = true } anyhow = { workspace = true } base64 = { workspace = true } bon = { workspace = true } +chrono = { workspace = true, optional = true } hmac = { workspace = true } reqwest-retry = { workspace = true } serde = { workspace = true } diff --git a/typesense/src/traits/field_type.rs b/typesense/src/traits/field_type.rs index e994e8d9..032becff 100644 --- a/typesense/src/traits/field_type.rs +++ b/typesense/src/traits/field_type.rs @@ -6,7 +6,7 @@ pub type FieldType = String; /// Trait that should implement each type of a document, in order to properly serialize the /// Collection Schema according to the Typesense reference. pub trait ToTypesenseField { - /// Static function that should implement the types of the typesense documents. + /// Mapping of a Typesense type. fn to_typesense_type() -> &'static str; } /// Generic implementation for any type that is also a Typesense document. @@ -25,22 +25,54 @@ impl ToTypesenseField for Vec { } } +impl ToTypesenseField for Option { + #[inline(always)] + fn to_typesense_type() -> &'static str { + T::to_typesense_type() + } +} + /// macro used internally to add implementations of ToTypesenseField for several rust types. #[macro_export] macro_rules! impl_to_typesense_field ( - ($for:ty, $typesense_variant:expr) => { + ($for:ty, $typesense_type:expr) => { impl $crate::prelude::ToTypesenseField for $for { #[inline(always)] fn to_typesense_type() -> &'static str { - $typesense_variant + $typesense_type + } + } + impl $crate::prelude::ToTypesenseField for Vec<$for> { + #[inline(always)] + fn to_typesense_type() -> &'static str { + concat!($typesense_type, "[]") + } + } + impl $crate::prelude::ToTypesenseField for Vec> { + #[inline(always)] + fn to_typesense_type() -> &'static str { + concat!($typesense_type, "[]") } } }; - ($for:ty, $typesense_variant:expr, $any:ident) => { - impl<$any> $crate::prelude::ToTypesenseField for $for { + + ($for:ty, $typesense_type:expr, $any:ident $(: $any_bound:path)?) => { + impl<$any $(: $any_bound)?> $crate::prelude::ToTypesenseField for $for { + #[inline(always)] + fn to_typesense_type() -> &'static str { + $typesense_type + } + } + impl<$any $(: $any_bound)?> $crate::prelude::ToTypesenseField for Vec<$for> { #[inline(always)] fn to_typesense_type() -> &'static str { - $typesense_variant + concat!($typesense_type, "[]") + } + } + impl<$any $(: $any_bound)?> $crate::prelude::ToTypesenseField for Vec> { + #[inline(always)] + fn to_typesense_type() -> &'static str { + concat!($typesense_type, "[]") } } }; @@ -63,19 +95,10 @@ impl_to_typesense_field!(bool, "bool"); impl_to_typesense_field!(HashMap, "object", T); impl_to_typesense_field!(BTreeMap, "object", T); -impl_to_typesense_field!(Vec, "string[]"); -impl_to_typesense_field!(Vec, "int32[]"); -impl_to_typesense_field!(Vec, "int32[]"); -impl_to_typesense_field!(Vec, "int32[]"); -impl_to_typesense_field!(Vec, "int32[]"); -impl_to_typesense_field!(Vec, "int32[]"); -impl_to_typesense_field!(Vec, "int64[]"); -impl_to_typesense_field!(Vec, "int64[]"); -impl_to_typesense_field!(Vec, "int64[]"); -impl_to_typesense_field!(Vec, "int64[]"); -impl_to_typesense_field!(Vec, "int64[]"); -impl_to_typesense_field!(Vec, "float[]"); -impl_to_typesense_field!(Vec, "float[]"); -impl_to_typesense_field!(Vec, "bool[]"); -impl_to_typesense_field!(Vec>, "object[]", T); -impl_to_typesense_field!(Vec>, "object[]", T); +#[cfg(feature = "chrono")] +mod chrono_support { + impl_to_typesense_field!(chrono::DateTime, "string", T: chrono::TimeZone); + impl_to_typesense_field!(chrono::NaiveDate, "string"); + impl_to_typesense_field!(chrono::NaiveDateTime, "string"); + impl_to_typesense_field!(chrono::NaiveTime, "string"); +} diff --git a/typesense_derive/src/lib.rs b/typesense_derive/src/lib.rs index 0e1b658c..828035ec 100644 --- a/typesense_derive/src/lib.rs +++ b/typesense_derive/src/lib.rs @@ -138,7 +138,7 @@ fn impl_typesense_collection(item: ItemStruct) -> syn::Result { let name_partial = Ident::new(&(ident.to_string() + "Partial"), ident.span()); let generated_code = quote! { - #[derive(Default, Serialize)] + #[derive(Default, ::serde::Serialize)] #vis struct #name_partial { #(#optional_fields)* }