diff --git a/butane/src/lib.rs b/butane/src/lib.rs index 13dfcf40..0e13f259 100644 --- a/butane/src/lib.rs +++ b/butane/src/lib.rs @@ -6,7 +6,7 @@ #![deny(missing_docs)] -pub use butane_codegen::{butane_type, dataresult, model, FieldType}; +pub use butane_codegen::{butane_type, dataresult, model, FieldType, PrimaryKeyType}; pub use butane_core::custom; pub use butane_core::fkey::ForeignKey; pub use butane_core::internal; diff --git a/butane_codegen/src/lib.rs b/butane_codegen/src/lib.rs index f4782f8e..198fcefc 100644 --- a/butane_codegen/src/lib.rs +++ b/butane_codegen/src/lib.rs @@ -433,3 +433,19 @@ fn derive_field_type_with_json(struct_name: &Ident) -> TokenStream { fn derive_field_type_with_json(_struct_name: &Ident) -> TokenStream { panic!("Feature 'json' is required to derive FieldType") } + +/// Derive macro for marker trait `PrimaryKeyType`. +/// E.g. +/// ```ignore +/// #[derive(FieldType, PrimaryKeyType)] +/// pub struct PostId(pub uuid::Uuid); +/// ``` +#[proc_macro_derive(PrimaryKeyType)] +pub fn derive_primary_key_type(input: TokenStream) -> TokenStream { + let derive_input = syn::parse_macro_input!(input as syn::DeriveInput); + let ident = &derive_input.ident; + quote!( + impl butane::PrimaryKeyType for #ident {} + ) + .into() +} diff --git a/docs/newtype.md b/docs/newtype.md index 515327cb..ade64ecd 100644 --- a/docs/newtype.md +++ b/docs/newtype.md @@ -45,17 +45,15 @@ Create `src/models.rs` with a `BlogId` and `PostId` struct wrapping a `uuid`. use butane::{FieldType, PrimaryKeyType}; use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Default, Deserialize, Serialize, FieldType, PartialEq, Eq)] +#[derive(Clone, Debug, Default, Deserialize, Eq, FieldType, PartialEq, PrimaryKeyType, Serialize)] pub struct BlogId(pub uuid::Uuid); -impl PrimaryKeyType for BlogId {} -#[derive(Clone, Debug, Default, Deserialize, Serialize, FieldType, PartialEq, Eq)] +#[derive(Clone, Debug, Default, Deserialize, Eq, FieldType, PartialEq, PrimaryKeyType, Serialize)] pub struct PostId(pub uuid::Uuid); -impl PrimaryKeyType for PostId {} ``` -For each, `FieldType` is derived, and they implement the marker trait `PrimaryKeyType` -to allow their use as a primary key. +For each, `FieldType` is derived to generate code to describe how the field will be stored, and +the marker trait `PrimaryKeyType` is derived to allow their use as a primary key. As Butane natively supports `uuid`, these newtypes will be stored in the butane metadata as "Blob" type, which is stored in the database using an appropriate column type based on the diff --git a/examples/newtype/src/models.rs b/examples/newtype/src/models.rs index e7c2f2e2..d3cd06af 100644 --- a/examples/newtype/src/models.rs +++ b/examples/newtype/src/models.rs @@ -5,14 +5,16 @@ use garde::Validate; use serde::{Deserialize, Serialize}; /// Blog identifier. -#[derive(Clone, Debug, Default, Deserialize, Eq, FieldType, PartialEq, Serialize)] +#[derive( + Clone, Debug, Default, Deserialize, Eq, FieldType, PartialEq, PrimaryKeyType, Serialize, +)] pub struct BlogId(pub uuid::Uuid); -impl PrimaryKeyType for BlogId {} /// Post identifier. -#[derive(Clone, Debug, Default, Deserialize, Eq, FieldType, PartialEq, Serialize)] +#[derive( + Clone, Debug, Default, Deserialize, Eq, FieldType, PartialEq, PrimaryKeyType, Serialize, +)] pub struct PostId(pub uuid::Uuid); -impl PrimaryKeyType for PostId {} /// Blog name. #[derive(Clone, Debug, Default, Deserialize, Eq, FieldType, PartialEq, Serialize, Validate)]