diff --git a/crates/bonsaidb-client/Cargo.toml b/crates/bonsaidb-client/Cargo.toml index 9e2630f5700..b4c7b7b8a65 100644 --- a/crates/bonsaidb-client/Cargo.toml +++ b/crates/bonsaidb-client/Cargo.toml @@ -22,6 +22,7 @@ password-hashing = ["bonsaidb-core/password-hashing"] [dependencies] bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0-dev.4", default-features = false, features = [ "networking", + "included-from-client" ] } bonsaidb-utils = { path = "../bonsaidb-utils", version = "0.1.0-dev.4" } thiserror = "1" diff --git a/crates/bonsaidb-core/Cargo.toml b/crates/bonsaidb-core/Cargo.toml index 3151b670ae2..b1be9a40999 100644 --- a/crates/bonsaidb-core/Cargo.toml +++ b/crates/bonsaidb-core/Cargo.toml @@ -21,6 +21,10 @@ instrument = ["pot/tracing"] multiuser = ["zeroize"] encryption = [] password-hashing = ["multiuser"] +included-from-omnibus = ["bonsaidb-macros/omnibus-path"] +included-from-server = ["bonsaidb-macros/server-path"] +included-from-local = ["bonsaidb-macros/local-path"] +included-from-client = ["bonsaidb-macros/client-path"] [dependencies] bonsaidb-macros = { path = "../bonsaidb-macros", version = "0.1.0-dev.4" } diff --git a/crates/bonsaidb-local/Cargo.toml b/crates/bonsaidb-local/Cargo.toml index 531bc4cd662..146ade70a8a 100644 --- a/crates/bonsaidb-local/Cargo.toml +++ b/crates/bonsaidb-local/Cargo.toml @@ -39,7 +39,7 @@ included-from-omnibus = [] [dependencies] async-trait = "0.1" -bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0-dev.4" } +bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0-dev.4", features = ["included-from-local"]} bonsaidb-utils = { path = "../bonsaidb-utils", version = "0.1.0-dev.4" } nebari = { version = "0.2" } thiserror = "1" diff --git a/crates/bonsaidb-macros/Cargo.toml b/crates/bonsaidb-macros/Cargo.toml index ce4f31580c8..c5c6937facf 100644 --- a/crates/bonsaidb-macros/Cargo.toml +++ b/crates/bonsaidb-macros/Cargo.toml @@ -20,6 +20,7 @@ proc-macro2 = "1.0.36" quote = "1" syn = "1" trybuild = "1.0.54" +proc-macro-crate = "1.1.0" # TODO change this to version after release of attribute-derive [dependencies.attribute-derive] @@ -35,3 +36,9 @@ path = "../bonsaidb/" [dev-dependencies.serde] version = "1.0.133" features = ["derive"] + +[features] +omnibus-path = [] +server-path = [] +local-path = [] +client-path = [] diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index 893b843f33c..5dc5a18c2d9 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -13,14 +13,43 @@ #![cfg_attr(doc, deny(rustdoc::all))] use attribute_derive::Attribute; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; +use proc_macro_crate::{crate_name, FoundCrate}; use proc_macro_error::{proc_macro_error, ResultExt}; use quote::quote; use syn::{ - parse_macro_input, punctuated::Punctuated, token::Paren, DeriveInput, LitStr, Path, Type, - TypeTuple, + parse_macro_input, parse_quote, punctuated::Punctuated, token::Paren, DeriveInput, Ident, + LitStr, Path, Type, TypeTuple, }; +fn core_path() -> Path { + match crate_name("bonsaidb") + .or_else(|_| crate_name("bonsaidb_server")) + .or_else(|_| crate_name("bonsaidb_local")) + .or_else(|_| crate_name("bonsaidb_client")) + { + Ok(FoundCrate::Name(name)) => { + let ident = Ident::new(&name, Span::call_site()); + parse_quote!(::#ident::core) + } + Ok(FoundCrate::Itself) => parse_quote!(crate), + Err(_) => match crate_name("bonsaidb_core") { + Ok(FoundCrate::Name(name)) => { + let ident = Ident::new(&name, Span::call_site()); + parse_quote!(::#ident::core) + } + Ok(FoundCrate::Itself) => parse_quote!(crate), + Err(_) => match () { + () if cfg!(feature = "omnibus-path") => parse_quote!(::bonsaidb::core), + () if cfg!(feature = "server-path") => parse_quote!(::bonsaidb_server::core), + () if cfg!(feature = "local-path") => parse_quote!(::bonsaidb_local::core), + () if cfg!(feature = "client-path") => parse_quote!(::bonsaidb_client::core), + _ => parse_quote!(::bonsaidb_core), + }, + }, + } +} + #[derive(Attribute)] #[attribute(ident = "collection")] #[attribute( @@ -38,8 +67,12 @@ struct CollectionAttribute { #[attribute(default)] #[attribute(expected = r#"Specify the `views` like so: `view = [SomeView, AnotherView]`"#)] views: Vec, - #[attribute(expected = r#"Specify the `serialization` like so: `serialization = Format` or `serialization = None` to disable deriving it"#)] + #[attribute( + expected = r#"Specify the `serialization` like so: `serialization = Format` or `serialization = None` to disable deriving it"# + )] serialization: Option, + #[attribute(expected = r#"Specify the the path to `core` like so: `core = bosaidb::core`"#)] + core: Option, } /// Derives the `bonsaidb::core::schema::Collection` trait. @@ -59,14 +92,17 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr name, views, serialization, + core, } = CollectionAttribute::from_attributes(attrs).unwrap_or_abort(); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let core = core.unwrap_or_else(core_path); + let serialization = match serialization { Some(serialization) if serialization.is_ident("None") => TokenStream::new(), Some(serialization) => quote! { - impl #impl_generics ::bonsaidb::core::schema::SerializedCollection for #ident #ty_generics #where_clause { + impl #impl_generics #core::schema::SerializedCollection for #ident #ty_generics #where_clause { type Contents = #ident #ty_generics; type Format = #serialization; @@ -76,16 +112,16 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr } }, None => quote! { - impl #impl_generics ::bonsaidb::core::schema::DefaultSerialization for #ident #ty_generics #where_clause {} + impl #impl_generics #core::schema::DefaultSerialization for #ident #ty_generics #where_clause {} }, }; quote! { - impl #impl_generics ::bonsaidb::core::schema::Collection for #ident #ty_generics #where_clause { - fn collection_name() -> ::bonsaidb::core::schema::CollectionName { - ::bonsaidb::core::schema::CollectionName::new(#authority, #name) + impl #impl_generics #core::schema::Collection for #ident #ty_generics #where_clause { + fn collection_name() -> #core::schema::CollectionName { + #core::schema::CollectionName::new(#authority, #name) } - fn define_views(schema: &mut ::bonsaidb::core::schema::Schematic) -> ::core::result::Result<(), ::bonsaidb::core::Error>{ + fn define_views(schema: &mut #core::schema::Schematic) -> ::core::result::Result<(), #core::Error>{ #( schema.define_view(#views)?; )* ::core::result::Result::Ok(()) } @@ -104,7 +140,9 @@ struct ViewAttribute { #[attribute( missing = r#"You need to specify the collection type via `#[view(collection = CollectionType)]`"# )] - #[attribute(expected = r#"Specify the collection type like so: `collection = CollectionType`"#)] + #[attribute( + expected = r#"Specify the collection type like so: `collection = CollectionType`"# + )] collection: Type, #[attribute(missing = r#"You need to specify the key type via `#[view(key = KeyType)]`"#)] #[attribute(expected = r#"Specify the key type like so: `key = KeyType`"#)] @@ -112,6 +150,8 @@ struct ViewAttribute { name: Option, #[attribute(expected = r#"Specify the value type like so: `value = ValueType`"#)] value: Option, + #[attribute(expected = r#"Specify the the path to `core` like so: `core = bosaidb::core`"#)] + core: Option, } /// Derives the `bonsaidb::core::schema::View` trait. @@ -132,8 +172,11 @@ pub fn view_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { key, name, value, + core } = ViewAttribute::from_attributes(attrs).unwrap_or_abort(); + let core = core.unwrap_or_else(core_path); + let value = value.unwrap_or_else(|| { Type::Tuple(TypeTuple { paren_token: Paren::default(), @@ -147,13 +190,13 @@ pub fn view_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); quote! { - impl #impl_generics ::bonsaidb::core::schema::View for #ident #ty_generics #where_clause { + impl #impl_generics #core::schema::View for #ident #ty_generics #where_clause { type Collection = #collection; type Key = #key; type Value = #value; - fn name(&self) -> ::bonsaidb::core::schema::Name { - ::bonsaidb::core::schema::Name::new(#name) + fn name(&self) -> #core::schema::Name { + #core::schema::Name::new(#name) } } } diff --git a/crates/bonsaidb-macros/tests/collection.rs b/crates/bonsaidb-macros/tests/collection.rs index 5cc0b6cde68..b88ecfe15d9 100644 --- a/crates/bonsaidb-macros/tests/collection.rs +++ b/crates/bonsaidb-macros/tests/collection.rs @@ -1,12 +1,12 @@ use core::fmt::Debug; -use bonsaidb::core::schema::Schematic; +use bonsaidb::core::{schema::Schematic, document::CollectionDocument}; #[test] fn name_only() { use bonsaidb::core::schema::Collection; #[derive(Collection, Debug)] - #[collection(name = "Name", authority = "Authority")] + #[collection(name = "Name", authority = "Authority", core = ::bonsaidb::core)] struct Test(T); assert_eq!( @@ -17,8 +17,7 @@ fn name_only() { #[test] fn views() { use bonsaidb::core::schema::{ - Collection, CollectionDocument, CollectionViewSchema, DefaultViewSerialization, Name, View, - ViewMapResult, + Collection, CollectionViewSchema, DefaultViewSerialization, Name, View, ViewMapResult, }; use serde::{Deserialize, Serialize}; diff --git a/crates/bonsaidb-server/Cargo.toml b/crates/bonsaidb-server/Cargo.toml index 277afe00fe0..cc914ae4e15 100644 --- a/crates/bonsaidb-server/Cargo.toml +++ b/crates/bonsaidb-server/Cargo.toml @@ -38,6 +38,7 @@ bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0-dev.4", default-fe "networking", "actionable-traits", "multiuser", + "included-from-server" ] } bonsaidb-local = { path = "../bonsaidb-local", version = "0.1.0-dev.4", default-features = false, features = [ "internal-apis", diff --git a/crates/bonsaidb/Cargo.toml b/crates/bonsaidb/Cargo.toml index 16e4b0fa734..c5a3eb83f0d 100644 --- a/crates/bonsaidb/Cargo.toml +++ b/crates/bonsaidb/Cargo.toml @@ -103,7 +103,7 @@ client-password-hashing = [ ] [dependencies] -bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0-dev.4", default-features = false } +bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0-dev.4", default-features = false, features=["included-from-omnibus"] } bonsaidb-local = { path = "../bonsaidb-local", version = "0.1.0-dev.4", default-features = false, optional = true } bonsaidb-client = { path = "../bonsaidb-client", version = "0.1.0-dev.4", default-features = false, optional = true } bonsaidb-server = { path = "../bonsaidb-server", version = "0.1.0-dev.4", default-features = false, optional = true }