From 9f27a925bd323e8e0864bedeb33a3c6953517ea1 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 19 Nov 2022 15:45:12 +0100 Subject: refactor: reorganize non-public API items --- macros/src/caster.rs | 150 ++++++++++++ macros/src/factory/build_declare_interfaces.rs | 16 +- macros/src/lib.rs | 4 +- macros/src/libs/intertrait_macros/LICENSE-APACHE | 176 -------------- macros/src/libs/intertrait_macros/LICENSE-MIT | 17 -- macros/src/libs/intertrait_macros/gen_caster.rs | 150 ------------ macros/src/libs/intertrait_macros/mod.rs | 14 -- macros/src/libs/mod.rs | 1 - src/castable_factory/blocking.rs | 153 ------------ src/castable_factory/mod.rs | 4 - src/castable_factory/threadsafe.rs | 172 -------------- src/di_container/asynchronous/binding/builder.rs | 8 +- src/di_container/asynchronous/mod.rs | 17 +- src/di_container/blocking/binding/builder.rs | 4 +- src/di_container/blocking/mod.rs | 11 +- src/interfaces/any_factory.rs | 11 - src/interfaces/async_injectable.rs | 2 +- src/interfaces/factory.rs | 23 -- src/interfaces/injectable.rs | 2 +- src/interfaces/mod.rs | 8 - src/lib.rs | 7 +- src/libs/intertrait/LICENSE-APACHE | 176 -------------- src/libs/intertrait/LICENSE-MIT | 17 -- src/libs/intertrait/cast/arc.rs | 93 -------- src/libs/intertrait/cast/box.rs | 87 ------- src/libs/intertrait/cast/error.rs | 20 -- src/libs/intertrait/cast/mod.rs | 20 -- src/libs/intertrait/cast/rc.rs | 87 ------- src/libs/intertrait/mod.rs | 282 ----------------------- src/libs/mod.rs | 3 - src/private/any_factory.rs | 11 + src/private/cast/arc.rs | 93 ++++++++ src/private/cast/boxed.rs | 87 +++++++ src/private/cast/error.rs | 20 ++ src/private/cast/mod.rs | 273 ++++++++++++++++++++++ src/private/cast/rc.rs | 87 +++++++ src/private/castable_factory/blocking.rs | 153 ++++++++++++ src/private/castable_factory/mod.rs | 4 + src/private/castable_factory/threadsafe.rs | 172 ++++++++++++++ src/private/factory.rs | 23 ++ src/private/mod.rs | 15 ++ src/provider/async.rs | 12 +- src/provider/blocking.rs | 12 +- src/test_utils.rs | 2 +- 44 files changed, 1134 insertions(+), 1565 deletions(-) create mode 100644 macros/src/caster.rs delete mode 100644 macros/src/libs/intertrait_macros/LICENSE-APACHE delete mode 100644 macros/src/libs/intertrait_macros/LICENSE-MIT delete mode 100644 macros/src/libs/intertrait_macros/gen_caster.rs delete mode 100644 macros/src/libs/intertrait_macros/mod.rs delete mode 100644 macros/src/libs/mod.rs delete mode 100644 src/castable_factory/blocking.rs delete mode 100644 src/castable_factory/mod.rs delete mode 100644 src/castable_factory/threadsafe.rs delete mode 100644 src/interfaces/any_factory.rs delete mode 100644 src/interfaces/factory.rs delete mode 100644 src/libs/intertrait/LICENSE-APACHE delete mode 100644 src/libs/intertrait/LICENSE-MIT delete mode 100644 src/libs/intertrait/cast/arc.rs delete mode 100644 src/libs/intertrait/cast/box.rs delete mode 100644 src/libs/intertrait/cast/error.rs delete mode 100644 src/libs/intertrait/cast/mod.rs delete mode 100644 src/libs/intertrait/cast/rc.rs delete mode 100644 src/libs/intertrait/mod.rs delete mode 100644 src/libs/mod.rs create mode 100644 src/private/any_factory.rs create mode 100644 src/private/cast/arc.rs create mode 100644 src/private/cast/boxed.rs create mode 100644 src/private/cast/error.rs create mode 100644 src/private/cast/mod.rs create mode 100644 src/private/cast/rc.rs create mode 100644 src/private/castable_factory/blocking.rs create mode 100644 src/private/castable_factory/mod.rs create mode 100644 src/private/castable_factory/threadsafe.rs create mode 100644 src/private/factory.rs create mode 100644 src/private/mod.rs diff --git a/macros/src/caster.rs b/macros/src/caster.rs new file mode 100644 index 0000000..b84bd4d --- /dev/null +++ b/macros/src/caster.rs @@ -0,0 +1,150 @@ +/** + * Originally from Intertrait by CodeChain + * + * + * + * + * Licensed under either of + * + * Apache License, Version 2.0 (LICENSE-APACHE or ) + * MIT license (LICENSE-MIT or ) + + * at your option. +*/ +use std::str::from_utf8; + +use proc_macro2::{Ident, TokenStream}; +use quote::{format_ident, quote, ToTokens}; +use uuid::adapter::Simple; +use uuid::Uuid; + +const CASTER_FN_NAME_PREFIX: &[u8] = b"__"; + +const FN_BUF_LEN: usize = CASTER_FN_NAME_PREFIX.len() + Simple::LENGTH; + +pub fn generate_caster( + ty: &impl ToTokens, + dst_trait: &impl ToTokens, + sync: bool, +) -> TokenStream +{ + let fn_ident = create_caster_fn_ident(Uuid::new_v4()); + + let new_caster = if sync { + quote! { + syrette::private::cast::Caster::<#dst_trait>::new_sync( + |from| { + let concrete = from + .downcast::<#ty>() + .map_err(|_| syrette::private::cast::CasterError::CastBoxFailed)?; + + Ok(concrete as Box<#dst_trait>) + }, + |from| { + let concrete = from + .downcast::<#ty>() + .map_err(|_| syrette::private::cast::CasterError::CastRcFailed)?; + + Ok(concrete as std::rc::Rc<#dst_trait>) + }, + |from| { + let concrete = from + .downcast::<#ty>() + .map_err(|_| syrette::private::cast::CasterError::CastArcFailed)?; + + Ok(concrete as std::sync::Arc<#dst_trait>) + }, + ) + } + } else { + quote! { + syrette::private::cast::Caster::<#dst_trait>::new( + |from| { + let concrete = from + .downcast::<#ty>() + .map_err(|_| syrette::private::cast::CasterError::CastBoxFailed)?; + + Ok(concrete as Box<#dst_trait>) + }, + |from| { + let concrete = from + .downcast::<#ty>() + .map_err(|_| syrette::private::cast::CasterError::CastRcFailed)?; + + Ok(concrete as std::rc::Rc<#dst_trait>) + }, + ) + } + }; + + quote! { + #[syrette::private::linkme::distributed_slice(syrette::private::cast::CASTERS)] + #[linkme(crate = syrette::private::linkme)] + fn #fn_ident() -> (::std::any::TypeId, syrette::private::cast::BoxedCaster) { + (::std::any::TypeId::of::<#ty>(), Box::new(#new_caster)) + } + } +} + +fn create_caster_fn_ident(uuid: impl IUuid) -> Ident +{ + let buf = &mut [0u8; FN_BUF_LEN]; + + buf[..CASTER_FN_NAME_PREFIX.len()].copy_from_slice(CASTER_FN_NAME_PREFIX); + + uuid.encode_simple_lower_into(&mut buf[CASTER_FN_NAME_PREFIX.len()..]); + + let fn_name = + from_utf8(&buf[..FN_BUF_LEN]).expect("Created caster function name is not UTF-8"); + + format_ident!("{}", fn_name) +} + +/// Simple interface for `Uuid`. +/// +/// Created for ease of testing the [`create_caster_fn_ident`] function. +/// +/// [`Uuid`]: uuid::Uuid +#[cfg_attr(test, mockall::automock)] +trait IUuid +{ + /// Writes the Uuid as a simple lower-case string to `buf`. + fn encode_simple_lower_into(self, buf: &mut [u8]); +} + +impl IUuid for Uuid +{ + fn encode_simple_lower_into(self, buf: &mut [u8]) + { + self.to_simple().encode_lower(buf); + } +} + +#[cfg(test)] +mod tests +{ + use pretty_assertions::assert_eq; + use utility_macros::repeat_char; + + use super::*; + + #[test] + fn can_create_caster_fn_ident() + { + let mut uuid_mock = MockIUuid::new(); + + uuid_mock + .expect_encode_simple_lower_into() + .return_once(|buf| { + for index in 0..(FN_BUF_LEN - 2) { + buf[index] = b'f'; + } + }) + .once(); + + assert_eq!( + create_caster_fn_ident(uuid_mock), + format_ident!(concat!("__", repeat_char!('f', 32))) + ); + } +} diff --git a/macros/src/factory/build_declare_interfaces.rs b/macros/src/factory/build_declare_interfaces.rs index 6ab135e..038d29d 100644 --- a/macros/src/factory/build_declare_interfaces.rs +++ b/macros/src/factory/build_declare_interfaces.rs @@ -11,10 +11,10 @@ pub fn build_declare_factory_interfaces( if is_threadsafe { quote! { syrette::declare_interface!( - syrette::castable_factory::threadsafe::ThreadsafeCastableFactory< + syrette::private::castable_factory::threadsafe::ThreadsafeCastableFactory< (std::sync::Arc,), #factory_interface - > -> syrette::interfaces::factory::IThreadsafeFactory< + > -> syrette::private::factory::IThreadsafeFactory< (std::sync::Arc,), #factory_interface >, @@ -22,30 +22,30 @@ pub fn build_declare_factory_interfaces( ); syrette::declare_interface!( - syrette::castable_factory::threadsafe::ThreadsafeCastableFactory< + syrette::private::castable_factory::threadsafe::ThreadsafeCastableFactory< (std::sync::Arc,), #factory_interface - > -> syrette::interfaces::any_factory::AnyThreadsafeFactory, + > -> syrette::private::any_factory::AnyThreadsafeFactory, async = true ); } } else { quote! { syrette::declare_interface!( - syrette::castable_factory::blocking::CastableFactory< + syrette::private::castable_factory::blocking::CastableFactory< (std::rc::Rc,), #factory_interface - > -> syrette::interfaces::factory::IFactory< + > -> syrette::private::factory::IFactory< (std::rc::Rc,), #factory_interface > ); syrette::declare_interface!( - syrette::castable_factory::blocking::CastableFactory< + syrette::private::castable_factory::blocking::CastableFactory< (std::rc::Rc,), #factory_interface - > -> syrette::interfaces::any_factory::AnyFactory + > -> syrette::private::any_factory::AnyFactory ); } } diff --git a/macros/src/lib.rs b/macros/src/lib.rs index ccd38e1..ac0309e 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -20,9 +20,9 @@ use syn::{ TypeTraitObject, }; +mod caster; mod declare_interface_args; mod injectable; -mod libs; mod macro_flag; mod util; @@ -37,11 +37,11 @@ mod fn_trait; #[cfg(test)] mod test_utils; +use crate::caster::generate_caster; use crate::declare_interface_args::DeclareInterfaceArgs; use crate::injectable::dependency::Dependency; use crate::injectable::implementation::InjectableImpl; use crate::injectable::macro_args::InjectableMacroArgs; -use crate::libs::intertrait_macros::gen_caster::generate_caster; /// Makes a struct injectable. Thereby usable with [`DIContainer`] or /// [`AsyncDIContainer`]. diff --git a/macros/src/libs/intertrait_macros/LICENSE-APACHE b/macros/src/libs/intertrait_macros/LICENSE-APACHE deleted file mode 100644 index d9a10c0..0000000 --- a/macros/src/libs/intertrait_macros/LICENSE-APACHE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/macros/src/libs/intertrait_macros/LICENSE-MIT b/macros/src/libs/intertrait_macros/LICENSE-MIT deleted file mode 100644 index 969d061..0000000 --- a/macros/src/libs/intertrait_macros/LICENSE-MIT +++ /dev/null @@ -1,17 +0,0 @@ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/macros/src/libs/intertrait_macros/gen_caster.rs b/macros/src/libs/intertrait_macros/gen_caster.rs deleted file mode 100644 index 06f5aad..0000000 --- a/macros/src/libs/intertrait_macros/gen_caster.rs +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Originally from Intertrait by CodeChain - * - * - * - * - * Licensed under either of - * - * Apache License, Version 2.0 (LICENSE-APACHE or ) - * MIT license (LICENSE-MIT or ) - - * at your option. -*/ -use std::str::from_utf8; - -use proc_macro2::{Ident, TokenStream}; -use quote::{format_ident, quote, ToTokens}; -use uuid::adapter::Simple; -use uuid::Uuid; - -const CASTER_FN_NAME_PREFIX: &[u8] = b"__"; - -const FN_BUF_LEN: usize = CASTER_FN_NAME_PREFIX.len() + Simple::LENGTH; - -pub fn generate_caster( - ty: &impl ToTokens, - dst_trait: &impl ToTokens, - sync: bool, -) -> TokenStream -{ - let fn_ident = create_caster_fn_ident(Uuid::new_v4()); - - let new_caster = if sync { - quote! { - syrette::libs::intertrait::Caster::<#dst_trait>::new_sync( - |from| { - let concrete = from - .downcast::<#ty>() - .map_err(|_| syrette::libs::intertrait::CasterError::CastBoxFailed)?; - - Ok(concrete as Box<#dst_trait>) - }, - |from| { - let concrete = from - .downcast::<#ty>() - .map_err(|_| syrette::libs::intertrait::CasterError::CastRcFailed)?; - - Ok(concrete as std::rc::Rc<#dst_trait>) - }, - |from| { - let concrete = from - .downcast::<#ty>() - .map_err(|_| syrette::libs::intertrait::CasterError::CastArcFailed)?; - - Ok(concrete as std::sync::Arc<#dst_trait>) - }, - ) - } - } else { - quote! { - syrette::libs::intertrait::Caster::<#dst_trait>::new( - |from| { - let concrete = from - .downcast::<#ty>() - .map_err(|_| syrette::libs::intertrait::CasterError::CastBoxFailed)?; - - Ok(concrete as Box<#dst_trait>) - }, - |from| { - let concrete = from - .downcast::<#ty>() - .map_err(|_| syrette::libs::intertrait::CasterError::CastRcFailed)?; - - Ok(concrete as std::rc::Rc<#dst_trait>) - }, - ) - } - }; - - quote! { - #[syrette::libs::linkme::distributed_slice(syrette::libs::intertrait::CASTERS)] - #[linkme(crate = syrette::libs::linkme)] - fn #fn_ident() -> (::std::any::TypeId, syrette::libs::intertrait::BoxedCaster) { - (::std::any::TypeId::of::<#ty>(), Box::new(#new_caster)) - } - } -} - -fn create_caster_fn_ident(uuid: impl IUuid) -> Ident -{ - let buf = &mut [0u8; FN_BUF_LEN]; - - buf[..CASTER_FN_NAME_PREFIX.len()].copy_from_slice(CASTER_FN_NAME_PREFIX); - - uuid.encode_simple_lower_into(&mut buf[CASTER_FN_NAME_PREFIX.len()..]); - - let fn_name = - from_utf8(&buf[..FN_BUF_LEN]).expect("Created caster function name is not UTF-8"); - - format_ident!("{}", fn_name) -} - -/// Simple interface for `Uuid`. -/// -/// Created for ease of testing the [`create_caster_fn_ident`] function. -/// -/// [`Uuid`]: uuid::Uuid -#[cfg_attr(test, mockall::automock)] -trait IUuid -{ - /// Writes the Uuid as a simple lower-case string to `buf`. - fn encode_simple_lower_into(self, buf: &mut [u8]); -} - -impl IUuid for Uuid -{ - fn encode_simple_lower_into(self, buf: &mut [u8]) - { - self.to_simple().encode_lower(buf); - } -} - -#[cfg(test)] -mod tests -{ - use pretty_assertions::assert_eq; - use utility_macros::repeat_char; - - use super::*; - - #[test] - fn can_create_caster_fn_ident() - { - let mut uuid_mock = MockIUuid::new(); - - uuid_mock - .expect_encode_simple_lower_into() - .return_once(|buf| { - for index in 0..(FN_BUF_LEN - 2) { - buf[index] = b'f'; - } - }) - .once(); - - assert_eq!( - create_caster_fn_ident(uuid_mock), - format_ident!(concat!("__", repeat_char!('f', 32))) - ); - } -} diff --git a/macros/src/libs/intertrait_macros/mod.rs b/macros/src/libs/intertrait_macros/mod.rs deleted file mode 100644 index fa8c021..0000000 --- a/macros/src/libs/intertrait_macros/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Originally from Intertrait by CodeChain - * - * - * - * - * Licensed under either of - * - * Apache License, Version 2.0 (LICENSE-APACHE or ) - * MIT license (LICENSE-MIT or ) - - * at your option. -*/ -pub mod gen_caster; diff --git a/macros/src/libs/mod.rs b/macros/src/libs/mod.rs deleted file mode 100644 index e4964de..0000000 --- a/macros/src/libs/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod intertrait_macros; diff --git a/src/castable_factory/blocking.rs b/src/castable_factory/blocking.rs deleted file mode 100644 index f16d86a..0000000 --- a/src/castable_factory/blocking.rs +++ /dev/null @@ -1,153 +0,0 @@ -use std::any::type_name; -use std::fmt::Debug; -use std::marker::Tuple; - -use crate::interfaces::any_factory::AnyFactory; -use crate::interfaces::factory::IFactory; -use crate::ptr::TransientPtr; - -pub struct CastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - func: &'static dyn Fn>, -} - -impl CastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - pub fn new( - func: &'static dyn Fn>, - ) -> Self - { - Self { func } - } -} - -impl IFactory - for CastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ -} - -impl Fn for CastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - extern "rust-call" fn call(&self, args: Args) -> Self::Output - { - self.func.call(args) - } -} - -impl FnMut for CastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output - { - self.call(args) - } -} - -impl FnOnce for CastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - type Output = TransientPtr; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output - { - self.call(args) - } -} - -impl AnyFactory for CastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ -} - -impl Debug for CastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - #[cfg(not(tarpaulin_include))] - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - let mut args = type_name::(); - - if args.len() < 2 { - return Err(std::fmt::Error::default()); - } - - args = args - .get(1..args.len() - 1) - .map_or_else(|| Err(std::fmt::Error::default()), Ok)?; - - if args.ends_with(',') { - args = args - .get(..args.len() - 1) - .map_or_else(|| Err(std::fmt::Error), Ok)?; - } - - let ret = type_name::>(); - - formatter.write_fmt(format_args!("CastableFactory ({}) -> {}", args, ret)) - } -} - -#[cfg(test)] -mod tests -{ - use super::*; - - #[derive(Debug, PartialEq, Eq)] - struct Bacon - { - heal_amount: u32, - } - - #[test] - fn can_call() - { - let castable_factory = - CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount })); - - let output = castable_factory.call((27,)); - - assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); - } - - #[test] - fn can_call_mut() - { - let mut castable_factory = - CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount })); - - let output = castable_factory.call_mut((103,)); - - assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 103 })); - } - - #[test] - fn can_call_once() - { - let castable_factory = - CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount })); - - let output = castable_factory.call_once((19,)); - - assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 19 })); - } -} diff --git a/src/castable_factory/mod.rs b/src/castable_factory/mod.rs deleted file mode 100644 index e81b842..0000000 --- a/src/castable_factory/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod blocking; - -#[cfg(feature = "async")] -pub mod threadsafe; diff --git a/src/castable_factory/threadsafe.rs b/src/castable_factory/threadsafe.rs deleted file mode 100644 index d17a87f..0000000 --- a/src/castable_factory/threadsafe.rs +++ /dev/null @@ -1,172 +0,0 @@ -use std::any::type_name; -use std::fmt::Debug; -use std::marker::Tuple; - -use crate::interfaces::any_factory::{AnyFactory, AnyThreadsafeFactory}; -use crate::interfaces::factory::IThreadsafeFactory; -use crate::ptr::TransientPtr; - -pub struct ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - func: &'static (dyn Fn> + Send + Sync), -} - -impl ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - pub fn new( - func: &'static (dyn Fn> - + Send - + Sync), - ) -> Self - { - Self { func } - } -} - -impl IThreadsafeFactory - for ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ -} - -impl Fn for ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - extern "rust-call" fn call(&self, args: Args) -> Self::Output - { - self.func.call(args) - } -} - -impl FnMut - for ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output - { - self.call(args) - } -} - -impl FnOnce - for ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - type Output = TransientPtr; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output - { - self.call(args) - } -} - -impl AnyFactory - for ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ -} - -impl AnyThreadsafeFactory - for ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ -} - -impl Debug for ThreadsafeCastableFactory -where - Args: Tuple + 'static, - ReturnInterface: 'static + ?Sized, -{ - #[cfg(not(tarpaulin_include))] - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - let mut args = type_name::(); - - if args.len() < 2 { - return Err(std::fmt::Error::default()); - } - - args = args - .get(1..args.len() - 1) - .map_or_else(|| Err(std::fmt::Error::default()), Ok)?; - - if args.ends_with(',') { - args = args - .get(..args.len() - 1) - .map_or_else(|| Err(std::fmt::Error), Ok)?; - } - - let ret = type_name::>(); - - formatter.write_fmt(format_args!( - "ThreadsafeCastableFactory ({}) -> {}", - args, ret - )) - } -} - -#[cfg(test)] -mod tests -{ - use super::*; - - #[derive(Debug, PartialEq, Eq)] - struct Bacon - { - heal_amount: u32, - } - - #[test] - fn can_call() - { - let castable_factory = ThreadsafeCastableFactory::new(&|heal_amount| { - TransientPtr::new(Bacon { heal_amount }) - }); - - let output = castable_factory.call((27,)); - - assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); - } - - #[test] - fn can_call_mut() - { - let mut castable_factory = ThreadsafeCastableFactory::new(&|heal_amount| { - TransientPtr::new(Bacon { heal_amount }) - }); - - let output = castable_factory.call_mut((1092,)); - - assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 1092 })); - } - - #[test] - fn can_call_once() - { - let castable_factory = ThreadsafeCastableFactory::new(&|heal_amount| { - TransientPtr::new(Bacon { heal_amount }) - }); - - let output = castable_factory.call_once((547,)); - - assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 547 })); - } -} diff --git a/src/di_container/asynchronous/binding/builder.rs b/src/di_container/asynchronous/binding/builder.rs index 3ea8a35..8ba5be3 100644 --- a/src/di_container/asynchronous/binding/builder.rs +++ b/src/di_container/asynchronous/binding/builder.rs @@ -191,7 +191,7 @@ where FactoryFunc: Fn<(Arc,), Output = BoxFn> + Send + Sync, { - use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::provider::r#async::AsyncFactoryVariant; if self.di_container.has_binding::(None).await { @@ -288,7 +288,7 @@ where > + Send + Sync, { - use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::provider::r#async::AsyncFactoryVariant; if self.di_container.has_binding::(None).await { @@ -378,7 +378,7 @@ where > + Send + Sync, { - use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::provider::r#async::AsyncFactoryVariant; if self.di_container.has_binding::(None).await { @@ -472,7 +472,7 @@ where > + Send + Sync, { - use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::provider::r#async::AsyncFactoryVariant; if self.di_container.has_binding::(None).await { diff --git a/src/di_container/asynchronous/mod.rs b/src/di_container/asynchronous/mod.rs index 65f5c9e..ad1f44f 100644 --- a/src/di_container/asynchronous/mod.rs +++ b/src/di_container/asynchronous/mod.rs @@ -62,8 +62,9 @@ use crate::di_container::asynchronous::binding::builder::AsyncBindingBuilder; use crate::di_container::binding_storage::DIContainerBindingStorage; use crate::errors::async_di_container::AsyncDIContainerError; use crate::future::BoxFuture; -use crate::libs::intertrait::cast::error::CastError; -use crate::libs::intertrait::cast::{CastArc, CastBox}; +use crate::private::cast::arc::CastArc; +use crate::private::cast::boxed::CastBox; +use crate::private::cast::error::CastError; use crate::provider::r#async::{AsyncProvidable, IAsyncProvider}; use crate::ptr::{SomeThreadsafePtr, TransientPtr}; @@ -286,7 +287,7 @@ impl AsyncDIContainer } #[cfg(feature = "factory")] AsyncProvidable::Factory(factory_binding) => { - use crate::interfaces::factory::IThreadsafeFactory; + use crate::private::factory::IThreadsafeFactory; let factory = factory_binding .cast::,), Interface>>() @@ -315,7 +316,7 @@ impl AsyncDIContainer } #[cfg(feature = "factory")] AsyncProvidable::DefaultFactory(binding) => { - use crate::interfaces::factory::IThreadsafeFactory; + use crate::private::factory::IThreadsafeFactory; let default_factory = Self::cast_factory_binding::< dyn IThreadsafeFactory< @@ -328,7 +329,7 @@ impl AsyncDIContainer } #[cfg(feature = "factory")] AsyncProvidable::AsyncDefaultFactory(binding) => { - use crate::interfaces::factory::IThreadsafeFactory; + use crate::private::factory::IThreadsafeFactory; let async_default_factory = Self::cast_factory_binding::< dyn IThreadsafeFactory< @@ -350,7 +351,7 @@ impl AsyncDIContainer #[cfg(feature = "factory")] fn cast_factory_binding( - factory_binding: Arc, + factory_binding: Arc, binding_kind: &'static str, ) -> Result, AsyncDIContainerError> { @@ -667,7 +668,7 @@ mod tests } use crate as syrette; - use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; #[crate::factory(threadsafe = true)] type IUserManagerFactory = dyn Fn(Vec) -> dyn IUserManager; @@ -762,7 +763,7 @@ mod tests } use crate as syrette; - use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; #[crate::factory(threadsafe = true)] type IUserManagerFactory = dyn Fn(Vec) -> dyn IUserManager; diff --git a/src/di_container/blocking/binding/builder.rs b/src/di_container/blocking/binding/builder.rs index 29422b6..65fa40f 100644 --- a/src/di_container/blocking/binding/builder.rs +++ b/src/di_container/blocking/binding/builder.rs @@ -203,7 +203,7 @@ where Interface: Fn>, Func: Fn<(std::rc::Rc,), Output = Box>, { - use crate::castable_factory::blocking::CastableFactory; + use crate::private::castable_factory::blocking::CastableFactory; if self.di_container.has_binding::(None) { return Err(BindingBuilderError::BindingAlreadyExists(type_name::< @@ -295,7 +295,7 @@ where >, >, { - use crate::castable_factory::blocking::CastableFactory; + use crate::private::castable_factory::blocking::CastableFactory; if self.di_container.has_binding::(None) { return Err(BindingBuilderError::BindingAlreadyExists(type_name::< diff --git a/src/di_container/blocking/mod.rs b/src/di_container/blocking/mod.rs index 97cca59..de7ef67 100644 --- a/src/di_container/blocking/mod.rs +++ b/src/di_container/blocking/mod.rs @@ -58,7 +58,8 @@ use crate::dependency_history::{DependencyHistory, IDependencyHistory}; use crate::di_container::binding_storage::DIContainerBindingStorage; use crate::di_container::blocking::binding::builder::BindingBuilder; use crate::errors::di_container::DIContainerError; -use crate::libs::intertrait::cast::{CastBox, CastRc}; +use crate::private::cast::boxed::CastBox; +use crate::private::cast::rc::CastRc; use crate::provider::blocking::{IProvider, Providable}; use crate::ptr::SomePtr; @@ -243,7 +244,7 @@ impl DIContainer )), #[cfg(feature = "factory")] Providable::Factory(factory_binding) => { - use crate::interfaces::factory::IFactory; + use crate::private::factory::IFactory; let factory = factory_binding .cast::,), Interface>>() @@ -256,7 +257,7 @@ impl DIContainer } #[cfg(feature = "factory")] Providable::DefaultFactory(factory_binding) => { - use crate::interfaces::factory::IFactory; + use crate::private::factory::IFactory; use crate::ptr::TransientPtr; let default_factory = factory_binding @@ -463,7 +464,7 @@ mod tests #[cfg(feature = "factory")] fn can_get_factory() -> Result<(), Box> { - use crate::castable_factory::blocking::CastableFactory; + use crate::private::castable_factory::blocking::CastableFactory; use crate::ptr::FactoryPtr; trait IUserManager @@ -547,7 +548,7 @@ mod tests #[cfg(feature = "factory")] fn can_get_factory_named() -> Result<(), Box> { - use crate::castable_factory::blocking::CastableFactory; + use crate::private::castable_factory::blocking::CastableFactory; use crate::ptr::FactoryPtr; trait IUserManager diff --git a/src/interfaces/any_factory.rs b/src/interfaces/any_factory.rs deleted file mode 100644 index e47018b..0000000 --- a/src/interfaces/any_factory.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Interface for any factory to ever exist. - -use std::fmt::Debug; - -use crate::libs::intertrait::{CastFrom, CastFromSync}; - -/// Interface for any factory to ever exist. -pub trait AnyFactory: CastFrom + Debug {} - -/// Interface for any threadsafe factory to ever exist. -pub trait AnyThreadsafeFactory: CastFromSync + Debug {} diff --git a/src/interfaces/async_injectable.rs b/src/interfaces/async_injectable.rs index 4e614a3..e6a050e 100644 --- a/src/interfaces/async_injectable.rs +++ b/src/interfaces/async_injectable.rs @@ -6,7 +6,7 @@ use crate::dependency_history::IDependencyHistory; use crate::di_container::asynchronous::IAsyncDIContainer; use crate::errors::injectable::InjectableError; use crate::future::BoxFuture; -use crate::libs::intertrait::CastFromSync; +use crate::private::cast::CastFromSync; use crate::ptr::TransientPtr; /// Interface for structs that can be injected into or be injected to. diff --git a/src/interfaces/factory.rs b/src/interfaces/factory.rs deleted file mode 100644 index c67abd6..0000000 --- a/src/interfaces/factory.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::marker::Tuple; - -use crate::libs::intertrait::CastFrom; -use crate::ptr::TransientPtr; - -/// Interface for a factory. -pub trait IFactory: - Fn> + CastFrom -where - Args: Tuple, - ReturnInterface: 'static + ?Sized, -{ -} - -/// Interface for a threadsafe factory. -#[cfg(feature = "async")] -pub trait IThreadsafeFactory: - Fn> + crate::libs::intertrait::CastFromSync -where - Args: Tuple, - ReturnInterface: 'static + ?Sized, -{ -} diff --git a/src/interfaces/injectable.rs b/src/interfaces/injectable.rs index 6130d2b..b70e13f 100644 --- a/src/interfaces/injectable.rs +++ b/src/interfaces/injectable.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use crate::dependency_history::IDependencyHistory; use crate::di_container::blocking::IDIContainer; use crate::errors::injectable::InjectableError; -use crate::libs::intertrait::CastFrom; +use crate::private::cast::CastFrom; use crate::ptr::TransientPtr; /// Interface for structs that can be injected into or be injected to. diff --git a/src/interfaces/mod.rs b/src/interfaces/mod.rs index 9815a11..e7068ad 100644 --- a/src/interfaces/mod.rs +++ b/src/interfaces/mod.rs @@ -2,14 +2,6 @@ pub mod injectable; -#[cfg(feature = "factory")] -#[doc(hidden)] -pub mod any_factory; - -#[cfg(feature = "factory")] -#[doc(hidden)] -pub mod factory; - #[cfg(feature = "async")] #[cfg_attr(doc_cfg, doc(cfg(feature = "async")))] pub mod async_injectable; diff --git a/src/lib.rs b/src/lib.rs index 3bb921b..82a5a9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -108,14 +108,9 @@ pub use di_container::blocking::DIContainer; pub use syrette_macros::{declare_default_factory, factory}; pub use syrette_macros::{declare_interface, injectable, named}; -#[cfg(feature = "factory")] -#[doc(hidden)] -pub mod castable_factory; - #[doc(hidden)] -pub mod libs; +pub mod private; -// Private mod provider; #[cfg(test)] diff --git a/src/libs/intertrait/LICENSE-APACHE b/src/libs/intertrait/LICENSE-APACHE deleted file mode 100644 index d9a10c0..0000000 --- a/src/libs/intertrait/LICENSE-APACHE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/src/libs/intertrait/LICENSE-MIT b/src/libs/intertrait/LICENSE-MIT deleted file mode 100644 index 969d061..0000000 --- a/src/libs/intertrait/LICENSE-MIT +++ /dev/null @@ -1,17 +0,0 @@ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/src/libs/intertrait/cast/arc.rs b/src/libs/intertrait/cast/arc.rs deleted file mode 100644 index a1b2c30..0000000 --- a/src/libs/intertrait/cast/arc.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! Originally from Intertrait by CodeChain -//! -//! -//! -//! -//! Licensed under either of -//! -//! Apache License, Version 2.0 (LICENSE-APACHE or ) -//! MIT license (LICENSE-MIT or ) -//! -//! at your option. -use std::any::type_name; -use std::sync::Arc; - -use crate::libs::intertrait::cast::error::CastError; -use crate::libs::intertrait::{get_caster, CastFromSync}; - -pub trait CastArc -{ - /// Casts an `Arc` with `Self` into an `Arc` with `Dest`. - fn cast(self: Arc) -> Result, CastError>; -} - -/// A blanket implementation of `CastArc` for traits extending `CastFrom`, `Sync`, and -/// `Send`. -impl CastArc for CastFromSelf -{ - fn cast(self: Arc) -> Result, CastError> - { - let caster = - get_caster::((*self).type_id()).map_err(CastError::GetCasterFailed)?; - - let cast_arc = caster - .opt_cast_arc - .ok_or(CastError::NotArcCastable(type_name::()))?; - - cast_arc(self.arc_any()).map_err(|err| CastError::CastFailed { - source: err, - from: type_name::(), - to: type_name::(), - }) - } -} - -#[cfg(test)] -mod tests -{ - use std::any::Any; - use std::fmt::{Debug, Display}; - use std::sync::Arc; - - use super::*; - use crate::test_utils::subjects; - - #[test] - fn can_cast_arc() - { - let concrete_ninja = Arc::new(subjects::Ninja); - - let abstract_ninja: Arc = concrete_ninja; - - let debug_ninja_result = abstract_ninja.cast::(); - - assert!(debug_ninja_result.is_ok()); - } - - #[test] - fn cannot_cast_arc_wrong() - { - let concrete_ninja = Arc::new(subjects::Ninja); - - let abstract_ninja: Arc = concrete_ninja; - - let display_ninja_result = abstract_ninja.cast::(); - - assert!(matches!( - display_ninja_result, - Err(CastError::GetCasterFailed(_)) - )); - } - - #[test] - fn can_cast_arc_from_any() - { - let concrete_ninja = Arc::new(subjects::Ninja); - - let any_ninja: Arc = concrete_ninja; - - let debug_ninja_result = any_ninja.cast::(); - - assert!(debug_ninja_result.is_ok()); - } -} diff --git a/src/libs/intertrait/cast/box.rs b/src/libs/intertrait/cast/box.rs deleted file mode 100644 index fcd5f70..0000000 --- a/src/libs/intertrait/cast/box.rs +++ /dev/null @@ -1,87 +0,0 @@ -//! Originally from Intertrait by CodeChain -//! -//! -//! -//! -//! Licensed under either of -//! -//! Apache License, Version 2.0 (LICENSE-APACHE or ) -//! MIT license (LICENSE-MIT or ) -//! -//! at your option. - -use std::any::type_name; - -use crate::libs::intertrait::cast::error::CastError; -use crate::libs::intertrait::{get_caster, CastFrom}; - -pub trait CastBox -{ - /// Casts a `Box` with `Self` into a `Box` with `Dest`. - fn cast(self: Box) -> Result, CastError>; -} - -/// A blanket implementation of `CastBox` for traits extending `CastFrom`. -impl CastBox for CastFromSelf -{ - fn cast(self: Box) -> Result, CastError> - { - let caster = - get_caster::((*self).type_id()).map_err(CastError::GetCasterFailed)?; - - (caster.cast_box)(self.box_any()).map_err(|err| CastError::CastFailed { - source: err, - from: type_name::(), - to: type_name::(), - }) - } -} - -#[cfg(test)] -mod tests -{ - use std::any::Any; - use std::fmt::{Debug, Display}; - - use super::*; - use crate::test_utils::subjects; - - #[test] - fn can_cast_box() - { - let concrete_ninja = Box::new(subjects::Ninja); - - let abstract_ninja: Box = concrete_ninja; - - let debug_ninja_result = abstract_ninja.cast::(); - - assert!(debug_ninja_result.is_ok()); - } - - #[test] - fn cannot_cast_box_wrong() - { - let concrete_ninja = Box::new(subjects::Ninja); - - let abstract_ninja: Box = concrete_ninja; - - let display_ninja_result = abstract_ninja.cast::(); - - assert!(matches!( - display_ninja_result, - Err(CastError::GetCasterFailed(_)) - )); - } - - #[test] - fn can_cast_box_from_any() - { - let concrete_ninja = Box::new(subjects::Ninja); - - let any_ninja: Box = concrete_ninja; - - let debug_ninja_result = any_ninja.cast::(); - - assert!(debug_ninja_result.is_ok()); - } -} diff --git a/src/libs/intertrait/cast/error.rs b/src/libs/intertrait/cast/error.rs deleted file mode 100644 index d253fc5..0000000 --- a/src/libs/intertrait/cast/error.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::libs::intertrait::{CasterError, GetCasterError}; - -#[derive(thiserror::Error, Debug)] -pub enum CastError -{ - #[error("Failed to get caster")] - GetCasterFailed(#[from] GetCasterError), - - #[error("Failed to cast from {from} to {to}")] - CastFailed - { - #[source] - source: CasterError, - from: &'static str, - to: &'static str, - }, - - #[error("'{0}' can't be cast to an Arc")] - NotArcCastable(&'static str), -} diff --git a/src/libs/intertrait/cast/mod.rs b/src/libs/intertrait/cast/mod.rs deleted file mode 100644 index a0342cf..0000000 --- a/src/libs/intertrait/cast/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Originally from Intertrait by CodeChain -//! -//! -//! -//! -//! Licensed under either of -//! -//! Apache License, Version 2.0 (LICENSE-APACHE or ) -//! MIT license (LICENSE-MIT or ) -//! -//! at your option. -pub mod error; - -mod arc; -mod r#box; -mod rc; - -pub use arc::*; -pub use r#box::*; -pub use rc::*; diff --git a/src/libs/intertrait/cast/rc.rs b/src/libs/intertrait/cast/rc.rs deleted file mode 100644 index 8567d1e..0000000 --- a/src/libs/intertrait/cast/rc.rs +++ /dev/null @@ -1,87 +0,0 @@ -//! Originally from Intertrait by CodeChain -//! -//! -//! -//! -//! Licensed under either of -//! -//! Apache License, Version 2.0 (LICENSE-APACHE or ) -//! MIT license (LICENSE-MIT or ) -//! -//! at your option. -use std::any::type_name; -use std::rc::Rc; - -use crate::libs::intertrait::cast::error::CastError; -use crate::libs::intertrait::{get_caster, CastFrom}; - -pub trait CastRc -{ - /// Casts an `Rc` with `Self `into a `Rc` with `Dest`. - fn cast(self: Rc) -> Result, CastError>; -} - -/// A blanket implementation of `CastRc` for traits extending `CastFrom`. -impl CastRc for CastFromSelf -{ - fn cast(self: Rc) -> Result, CastError> - { - let caster = - get_caster::((*self).type_id()).map_err(CastError::GetCasterFailed)?; - - (caster.cast_rc)(self.rc_any()).map_err(|err| CastError::CastFailed { - source: err, - from: type_name::(), - to: type_name::(), - }) - } -} - -#[cfg(test)] -mod tests -{ - use std::any::Any; - use std::fmt::{Debug, Display}; - - use super::*; - use crate::test_utils::subjects; - - #[test] - fn can_cast_rc() - { - let concrete_ninja = Rc::new(subjects::Ninja); - - let abstract_ninja: Rc = concrete_ninja; - - let debug_ninja_result = abstract_ninja.cast::(); - - assert!(debug_ninja_result.is_ok()); - } - - #[test] - fn cannot_cast_rc_wrong() - { - let concrete_ninja = Rc::new(subjects::Ninja); - - let abstract_ninja: Rc = concrete_ninja; - - let display_ninja_result = abstract_ninja.cast::(); - - assert!(matches!( - display_ninja_result, - Err(CastError::GetCasterFailed(_)) - )); - } - - #[test] - fn can_cast_rc_from_any() - { - let concrete_ninja = Rc::new(subjects::Ninja); - - let any_ninja: Rc = concrete_ninja; - - let debug_ninja_result = any_ninja.cast::(); - - assert!(debug_ninja_result.is_ok()); - } -} diff --git a/src/libs/intertrait/mod.rs b/src/libs/intertrait/mod.rs deleted file mode 100644 index d2ace67..0000000 --- a/src/libs/intertrait/mod.rs +++ /dev/null @@ -1,282 +0,0 @@ -//! A library providing direct casting among trait objects implemented by a type. -//! -//! In Rust, an object of a sub-trait of [`Any`] can be downcast to a concrete type -//! at runtime if the type is known. But no direct casting between two trait objects -//! (i.e. without involving the concrete type of the backing value) is possible -//! (even no coercion from a trait object to that of its super-trait yet). -//! -//! With this crate, any trait object with [`CastFrom`] as its super-trait can be cast -//! directly to another trait object implemented by the underlying type if the target -//! traits are registered beforehand with the macros provided by this crate. -//! -//! -//! Originally from Intertrait by CodeChain -//! -//! -//! -//! -//! Licensed under either of -//! -//! Apache License, Version 2.0 (LICENSE-APACHE or ) -//! MIT license (LICENSE-MIT or ) -//! -//! at your option. -use std::any::{Any, TypeId}; -use std::rc::Rc; -use std::sync::Arc; - -use ahash::AHashMap; -use linkme::distributed_slice; -use once_cell::sync::Lazy; - -pub mod cast; - -pub type BoxedCaster = Box; - -/// A distributed slice gathering constructor functions for [`Caster`]s. -/// -/// A constructor function returns `TypeId` of a concrete type involved in the casting -/// and a `Box` of a type or trait backed by a [`Caster`]. -#[distributed_slice] -pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..]; - -/// A `HashMap` mapping `TypeId` of a [`Caster`] to an instance of it. -static CASTER_MAP: Lazy> = Lazy::new(|| { - CASTERS - .iter() - .map(|caster_fn| { - let (type_id, caster) = caster_fn(); - - ((type_id, (*caster).type_id()), caster) - }) - .collect() -}); - -type CastBoxFn = fn(from: Box) -> Result, CasterError>; - -type CastRcFn = fn(from: Rc) -> Result, CasterError>; - -type CastArcFn = - fn(from: Arc) -> Result, CasterError>; - -/// A `Caster` knows how to cast a type or trait to the type or trait `Dest`. Each -/// `Caster` instance is specific to a concrete type. That is, it knows how to cast to -/// single specific type or trait implemented by single specific type. -pub struct Caster -{ - /// Casts a `Box` holding a type or trait object for `Any` to another `Box` holding a - /// type or trait `Dest`. - pub cast_box: CastBoxFn, - - /// Casts an `Rc` holding a type or trait for `Any` to another `Rc` holding a type or - /// trait `Dest`. - pub cast_rc: CastRcFn, - - /// Casts an `Arc` holding a type or trait for `Any + Sync + Send + 'static` to - /// another `Arc` holding a type or trait for `Dest`. - pub opt_cast_arc: Option>, -} - -impl Caster -{ - pub fn new(cast_box: CastBoxFn, cast_rc: CastRcFn) -> Caster - { - Caster:: { - cast_box, - cast_rc, - opt_cast_arc: None, - } - } - - #[allow(clippy::similar_names)] - pub fn new_sync( - cast_box: CastBoxFn, - cast_rc: CastRcFn, - cast_arc: CastArcFn, - ) -> Caster - { - Caster:: { - cast_box, - cast_rc, - opt_cast_arc: Some(cast_arc), - } - } -} - -#[derive(Debug, thiserror::Error)] -pub enum CasterError -{ - #[error("Failed to cast Box")] - CastBoxFailed, - - #[error("Failed to cast Rc")] - CastRcFailed, - - #[error("Failed to cast Arc")] - CastArcFailed, -} - -/// Returns a `Caster` from a concrete type with the id `type_id` to a type or trait -/// `Dest`. -fn get_caster( - type_id: TypeId, -) -> Result<&'static Caster, GetCasterError> -{ - let any_caster = CASTER_MAP - .get(&(type_id, TypeId::of::>())) - .ok_or(GetCasterError::NotFound)?; - - any_caster - .downcast_ref::>() - .ok_or(GetCasterError::DowncastFailed) -} - -#[derive(Debug, thiserror::Error)] -pub enum GetCasterError -{ - #[error("Caster not found")] - NotFound, - - #[error("Failed to downcast caster")] - DowncastFailed, -} - -/// `CastFrom` must be extended by a trait that wants to allow for casting into another -/// trait. -/// -/// It is used for obtaining a trait object for [`Any`] from a trait object for its -/// sub-trait, and blanket implemented for all `Sized + Any + 'static` types. -/// -/// # Examples -/// ```ignore -/// trait Source: CastFrom { -/// ... -/// } -/// ``` -pub trait CastFrom: Any + 'static -{ - /// Returns a `Box` of `Any`, which is backed by the type implementing this trait. - fn box_any(self: Box) -> Box; - - /// Returns an `Rc` of `Any`, which is backed by the type implementing this trait. - fn rc_any(self: Rc) -> Rc; -} - -/// `CastFromSync` must be extended by a trait that is `Any + Sync + Send + 'static` -/// and wants to allow for casting into another trait behind references and smart pointers -/// especially including `Arc`. -/// -/// It is used for obtaining a trait object for [`Any + Sync + Send + 'static`] from an -/// object for its sub-trait, and blanket implemented for all `Sized + Sync + Send + -/// 'static` types. -/// -/// # Examples -/// ```ignore -/// trait Source: CastFromSync { -/// ... -/// } -/// ``` -pub trait CastFromSync: CastFrom + Sync + Send + 'static -{ - fn arc_any(self: Arc) -> Arc; -} - -impl CastFrom for Source -{ - fn box_any(self: Box) -> Box - { - self - } - - fn rc_any(self: Rc) -> Rc - { - self - } -} - -impl CastFrom for dyn Any + 'static -{ - fn box_any(self: Box) -> Box - { - self - } - - fn rc_any(self: Rc) -> Rc - { - self - } -} - -impl CastFromSync for Source -{ - fn arc_any(self: Arc) -> Arc - { - self - } -} - -impl CastFrom for dyn Any + Sync + Send + 'static -{ - fn box_any(self: Box) -> Box - { - self - } - - fn rc_any(self: Rc) -> Rc - { - self - } -} - -impl CastFromSync for dyn Any + Sync + Send + 'static -{ - fn arc_any(self: Arc) -> Arc - { - self - } -} - -#[cfg(test)] -mod tests -{ - use std::any::TypeId; - use std::fmt::Debug; - - use linkme::distributed_slice; - - use super::*; - use crate::test_utils::subjects; - - #[distributed_slice(super::CASTERS)] - static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster; - - fn create_test_caster() -> (TypeId, BoxedCaster) - { - let type_id = TypeId::of::(); - - let caster = Box::new(Caster:: { - cast_box: |from| { - let concrete = from - .downcast::() - .map_err(|_| CasterError::CastBoxFailed)?; - - Ok(concrete as Box) - }, - cast_rc: |from| { - let concrete = from - .downcast::() - .map_err(|_| CasterError::CastRcFailed)?; - - Ok(concrete as Rc) - }, - opt_cast_arc: Some(|from| { - let concrete = from - .downcast::() - .map_err(|_| CasterError::CastArcFailed)?; - - Ok(concrete as Arc) - }), - }); - (type_id, caster) - } -} diff --git a/src/libs/mod.rs b/src/libs/mod.rs deleted file mode 100644 index 8d5583d..0000000 --- a/src/libs/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod intertrait; - -pub extern crate linkme; diff --git a/src/private/any_factory.rs b/src/private/any_factory.rs new file mode 100644 index 0000000..bdd68a6 --- /dev/null +++ b/src/private/any_factory.rs @@ -0,0 +1,11 @@ +//! Interface for any factory to ever exist. + +use std::fmt::Debug; + +use crate::private::cast::{CastFrom, CastFromSync}; + +/// Interface for any factory to ever exist. +pub trait AnyFactory: CastFrom + Debug {} + +/// Interface for any threadsafe factory to ever exist. +pub trait AnyThreadsafeFactory: CastFromSync + Debug {} diff --git a/src/private/cast/arc.rs b/src/private/cast/arc.rs new file mode 100644 index 0000000..7ea8b49 --- /dev/null +++ b/src/private/cast/arc.rs @@ -0,0 +1,93 @@ +//! Originally from Intertrait by CodeChain +//! +//! +//! +//! +//! Licensed under either of +//! +//! Apache License, Version 2.0 (LICENSE-APACHE or ) +//! MIT license (LICENSE-MIT or ) +//! +//! at your option. +use std::any::type_name; +use std::sync::Arc; + +use crate::private::cast::error::CastError; +use crate::private::cast::{get_caster, CastFromSync}; + +pub trait CastArc +{ + /// Casts an `Arc` with `Self` into an `Arc` with `Dest`. + fn cast(self: Arc) -> Result, CastError>; +} + +/// A blanket implementation of `CastArc` for traits extending `CastFrom`, `Sync`, and +/// `Send`. +impl CastArc for CastFromSelf +{ + fn cast(self: Arc) -> Result, CastError> + { + let caster = + get_caster::((*self).type_id()).map_err(CastError::GetCasterFailed)?; + + let cast_arc = caster + .opt_cast_arc + .ok_or(CastError::NotArcCastable(type_name::()))?; + + cast_arc(self.arc_any()).map_err(|err| CastError::CastFailed { + source: err, + from: type_name::(), + to: type_name::(), + }) + } +} + +#[cfg(test)] +mod tests +{ + use std::any::Any; + use std::fmt::{Debug, Display}; + use std::sync::Arc; + + use super::*; + use crate::test_utils::subjects; + + #[test] + fn can_cast_arc() + { + let concrete_ninja = Arc::new(subjects::Ninja); + + let abstract_ninja: Arc = concrete_ninja; + + let debug_ninja_result = abstract_ninja.cast::(); + + assert!(debug_ninja_result.is_ok()); + } + + #[test] + fn cannot_cast_arc_wrong() + { + let concrete_ninja = Arc::new(subjects::Ninja); + + let abstract_ninja: Arc = concrete_ninja; + + let display_ninja_result = abstract_ninja.cast::(); + + assert!(matches!( + display_ninja_result, + Err(CastError::GetCasterFailed(_)) + )); + } + + #[test] + fn can_cast_arc_from_any() + { + let concrete_ninja = Arc::new(subjects::Ninja); + + let any_ninja: Arc = concrete_ninja; + + let debug_ninja_result = any_ninja.cast::(); + + assert!(debug_ninja_result.is_ok()); + } +} diff --git a/src/private/cast/boxed.rs b/src/private/cast/boxed.rs new file mode 100644 index 0000000..074346c --- /dev/null +++ b/src/private/cast/boxed.rs @@ -0,0 +1,87 @@ +//! Originally from Intertrait by CodeChain +//! +//! +//! +//! +//! Licensed under either of +//! +//! Apache License, Version 2.0 (LICENSE-APACHE or ) +//! MIT license (LICENSE-MIT or ) +//! +//! at your option. + +use std::any::type_name; + +use crate::private::cast::error::CastError; +use crate::private::cast::{get_caster, CastFrom}; + +pub trait CastBox +{ + /// Casts a `Box` with `Self` into a `Box` with `Dest`. + fn cast(self: Box) -> Result, CastError>; +} + +/// A blanket implementation of `CastBox` for traits extending `CastFrom`. +impl CastBox for CastFromSelf +{ + fn cast(self: Box) -> Result, CastError> + { + let caster = + get_caster::((*self).type_id()).map_err(CastError::GetCasterFailed)?; + + (caster.cast_box)(self.box_any()).map_err(|err| CastError::CastFailed { + source: err, + from: type_name::(), + to: type_name::(), + }) + } +} + +#[cfg(test)] +mod tests +{ + use std::any::Any; + use std::fmt::{Debug, Display}; + + use super::*; + use crate::test_utils::subjects; + + #[test] + fn can_cast_box() + { + let concrete_ninja = Box::new(subjects::Ninja); + + let abstract_ninja: Box = concrete_ninja; + + let debug_ninja_result = abstract_ninja.cast::(); + + assert!(debug_ninja_result.is_ok()); + } + + #[test] + fn cannot_cast_box_wrong() + { + let concrete_ninja = Box::new(subjects::Ninja); + + let abstract_ninja: Box = concrete_ninja; + + let display_ninja_result = abstract_ninja.cast::(); + + assert!(matches!( + display_ninja_result, + Err(CastError::GetCasterFailed(_)) + )); + } + + #[test] + fn can_cast_box_from_any() + { + let concrete_ninja = Box::new(subjects::Ninja); + + let any_ninja: Box = concrete_ninja; + + let debug_ninja_result = any_ninja.cast::(); + + assert!(debug_ninja_result.is_ok()); + } +} diff --git a/src/private/cast/error.rs b/src/private/cast/error.rs new file mode 100644 index 0000000..c6ed01d --- /dev/null +++ b/src/private/cast/error.rs @@ -0,0 +1,20 @@ +use crate::private::cast::{CasterError, GetCasterError}; + +#[derive(thiserror::Error, Debug)] +pub enum CastError +{ + #[error("Failed to get caster")] + GetCasterFailed(#[from] GetCasterError), + + #[error("Failed to cast from {from} to {to}")] + CastFailed + { + #[source] + source: CasterError, + from: &'static str, + to: &'static str, + }, + + #[error("'{0}' can't be cast to an Arc")] + NotArcCastable(&'static str), +} diff --git a/src/private/cast/mod.rs b/src/private/cast/mod.rs new file mode 100644 index 0000000..0b80057 --- /dev/null +++ b/src/private/cast/mod.rs @@ -0,0 +1,273 @@ +//! Originally from Intertrait by CodeChain +//! +//! +//! +//! +//! Licensed under either of +//! +//! Apache License, Version 2.0 (LICENSE-APACHE or ) +//! MIT license (LICENSE-MIT or ) +//! +//! at your option. +use std::any::{Any, TypeId}; +use std::rc::Rc; +use std::sync::Arc; + +use ahash::AHashMap; +use linkme::distributed_slice; +use once_cell::sync::Lazy; + +pub mod arc; +pub mod boxed; +pub mod error; +pub mod rc; + +pub type BoxedCaster = Box; + +/// A distributed slice gathering constructor functions for [`Caster`]s. +/// +/// A constructor function returns `TypeId` of a concrete type involved in the casting +/// and a `Box` of a type or trait backed by a [`Caster`]. +#[distributed_slice] +pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..]; + +/// A `HashMap` mapping `TypeId` of a [`Caster`] to an instance of it. +static CASTER_MAP: Lazy> = Lazy::new(|| { + CASTERS + .iter() + .map(|caster_fn| { + let (type_id, caster) = caster_fn(); + + ((type_id, (*caster).type_id()), caster) + }) + .collect() +}); + +type CastBoxFn = fn(from: Box) -> Result, CasterError>; + +type CastRcFn = fn(from: Rc) -> Result, CasterError>; + +type CastArcFn = + fn(from: Arc) -> Result, CasterError>; + +/// A `Caster` knows how to cast a type or trait to the type or trait `Dest`. Each +/// `Caster` instance is specific to a concrete type. That is, it knows how to cast to +/// single specific type or trait implemented by single specific type. +pub struct Caster +{ + /// Casts a `Box` holding a type or trait object for `Any` to another `Box` holding a + /// type or trait `Dest`. + pub cast_box: CastBoxFn, + + /// Casts an `Rc` holding a type or trait for `Any` to another `Rc` holding a type or + /// trait `Dest`. + pub cast_rc: CastRcFn, + + /// Casts an `Arc` holding a type or trait for `Any + Sync + Send + 'static` to + /// another `Arc` holding a type or trait for `Dest`. + pub opt_cast_arc: Option>, +} + +impl Caster +{ + pub fn new(cast_box: CastBoxFn, cast_rc: CastRcFn) -> Caster + { + Caster:: { + cast_box, + cast_rc, + opt_cast_arc: None, + } + } + + #[allow(clippy::similar_names)] + pub fn new_sync( + cast_box: CastBoxFn, + cast_rc: CastRcFn, + cast_arc: CastArcFn, + ) -> Caster + { + Caster:: { + cast_box, + cast_rc, + opt_cast_arc: Some(cast_arc), + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum CasterError +{ + #[error("Failed to cast Box")] + CastBoxFailed, + + #[error("Failed to cast Rc")] + CastRcFailed, + + #[error("Failed to cast Arc")] + CastArcFailed, +} + +/// Returns a `Caster` from a concrete type with the id `type_id` to a type or trait +/// `Dest`. +fn get_caster( + type_id: TypeId, +) -> Result<&'static Caster, GetCasterError> +{ + let any_caster = CASTER_MAP + .get(&(type_id, TypeId::of::>())) + .ok_or(GetCasterError::NotFound)?; + + any_caster + .downcast_ref::>() + .ok_or(GetCasterError::DowncastFailed) +} + +#[derive(Debug, thiserror::Error)] +pub enum GetCasterError +{ + #[error("Caster not found")] + NotFound, + + #[error("Failed to downcast caster")] + DowncastFailed, +} + +/// `CastFrom` must be extended by a trait that wants to allow for casting into another +/// trait. +/// +/// It is used for obtaining a trait object for [`Any`] from a trait object for its +/// sub-trait, and blanket implemented for all `Sized + Any + 'static` types. +/// +/// # Examples +/// ```ignore +/// trait Source: CastFrom { +/// ... +/// } +/// ``` +pub trait CastFrom: Any + 'static +{ + /// Returns a `Box` of `Any`, which is backed by the type implementing this trait. + fn box_any(self: Box) -> Box; + + /// Returns an `Rc` of `Any`, which is backed by the type implementing this trait. + fn rc_any(self: Rc) -> Rc; +} + +/// `CastFromSync` must be extended by a trait that is `Any + Sync + Send + 'static` +/// and wants to allow for casting into another trait behind references and smart pointers +/// especially including `Arc`. +/// +/// It is used for obtaining a trait object for [`Any + Sync + Send + 'static`] from an +/// object for its sub-trait, and blanket implemented for all `Sized + Sync + Send + +/// 'static` types. +/// +/// # Examples +/// ```ignore +/// trait Source: CastFromSync { +/// ... +/// } +/// ``` +pub trait CastFromSync: CastFrom + Sync + Send + 'static +{ + fn arc_any(self: Arc) -> Arc; +} + +impl CastFrom for Source +{ + fn box_any(self: Box) -> Box + { + self + } + + fn rc_any(self: Rc) -> Rc + { + self + } +} + +impl CastFrom for dyn Any + 'static +{ + fn box_any(self: Box) -> Box + { + self + } + + fn rc_any(self: Rc) -> Rc + { + self + } +} + +impl CastFromSync for Source +{ + fn arc_any(self: Arc) -> Arc + { + self + } +} + +impl CastFrom for dyn Any + Sync + Send + 'static +{ + fn box_any(self: Box) -> Box + { + self + } + + fn rc_any(self: Rc) -> Rc + { + self + } +} + +impl CastFromSync for dyn Any + Sync + Send + 'static +{ + fn arc_any(self: Arc) -> Arc + { + self + } +} + +#[cfg(test)] +mod tests +{ + use std::any::TypeId; + use std::fmt::Debug; + + use linkme::distributed_slice; + + use super::*; + use crate::test_utils::subjects; + + #[distributed_slice(super::CASTERS)] + static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster; + + fn create_test_caster() -> (TypeId, BoxedCaster) + { + let type_id = TypeId::of::(); + + let caster = Box::new(Caster:: { + cast_box: |from| { + let concrete = from + .downcast::() + .map_err(|_| CasterError::CastBoxFailed)?; + + Ok(concrete as Box) + }, + cast_rc: |from| { + let concrete = from + .downcast::() + .map_err(|_| CasterError::CastRcFailed)?; + + Ok(concrete as Rc) + }, + opt_cast_arc: Some(|from| { + let concrete = from + .downcast::() + .map_err(|_| CasterError::CastArcFailed)?; + + Ok(concrete as Arc) + }), + }); + (type_id, caster) + } +} diff --git a/src/private/cast/rc.rs b/src/private/cast/rc.rs new file mode 100644 index 0000000..11d137a --- /dev/null +++ b/src/private/cast/rc.rs @@ -0,0 +1,87 @@ +//! Originally from Intertrait by CodeChain +//! +//! +//! +//! +//! Licensed under either of +//! +//! Apache License, Version 2.0 (LICENSE-APACHE or ) +//! MIT license (LICENSE-MIT or ) +//! +//! at your option. +use std::any::type_name; +use std::rc::Rc; + +use crate::private::cast::error::CastError; +use crate::private::cast::{get_caster, CastFrom}; + +pub trait CastRc +{ + /// Casts an `Rc` with `Self `into a `Rc` with `Dest`. + fn cast(self: Rc) -> Result, CastError>; +} + +/// A blanket implementation of `CastRc` for traits extending `CastFrom`. +impl CastRc for CastFromSelf +{ + fn cast(self: Rc) -> Result, CastError> + { + let caster = + get_caster::((*self).type_id()).map_err(CastError::GetCasterFailed)?; + + (caster.cast_rc)(self.rc_any()).map_err(|err| CastError::CastFailed { + source: err, + from: type_name::(), + to: type_name::(), + }) + } +} + +#[cfg(test)] +mod tests +{ + use std::any::Any; + use std::fmt::{Debug, Display}; + + use super::*; + use crate::test_utils::subjects; + + #[test] + fn can_cast_rc() + { + let concrete_ninja = Rc::new(subjects::Ninja); + + let abstract_ninja: Rc = concrete_ninja; + + let debug_ninja_result = abstract_ninja.cast::(); + + assert!(debug_ninja_result.is_ok()); + } + + #[test] + fn cannot_cast_rc_wrong() + { + let concrete_ninja = Rc::new(subjects::Ninja); + + let abstract_ninja: Rc = concrete_ninja; + + let display_ninja_result = abstract_ninja.cast::(); + + assert!(matches!( + display_ninja_result, + Err(CastError::GetCasterFailed(_)) + )); + } + + #[test] + fn can_cast_rc_from_any() + { + let concrete_ninja = Rc::new(subjects::Ninja); + + let any_ninja: Rc = concrete_ninja; + + let debug_ninja_result = any_ninja.cast::(); + + assert!(debug_ninja_result.is_ok()); + } +} diff --git a/src/private/castable_factory/blocking.rs b/src/private/castable_factory/blocking.rs new file mode 100644 index 0000000..abc3e26 --- /dev/null +++ b/src/private/castable_factory/blocking.rs @@ -0,0 +1,153 @@ +use std::any::type_name; +use std::fmt::Debug; +use std::marker::Tuple; + +use crate::private::any_factory::AnyFactory; +use crate::private::factory::IFactory; +use crate::ptr::TransientPtr; + +pub struct CastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + func: &'static dyn Fn>, +} + +impl CastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + pub fn new( + func: &'static dyn Fn>, + ) -> Self + { + Self { func } + } +} + +impl IFactory + for CastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ +} + +impl Fn for CastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + extern "rust-call" fn call(&self, args: Args) -> Self::Output + { + self.func.call(args) + } +} + +impl FnMut for CastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output + { + self.call(args) + } +} + +impl FnOnce for CastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + type Output = TransientPtr; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output + { + self.call(args) + } +} + +impl AnyFactory for CastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ +} + +impl Debug for CastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + #[cfg(not(tarpaulin_include))] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + let mut args = type_name::(); + + if args.len() < 2 { + return Err(std::fmt::Error::default()); + } + + args = args + .get(1..args.len() - 1) + .map_or_else(|| Err(std::fmt::Error::default()), Ok)?; + + if args.ends_with(',') { + args = args + .get(..args.len() - 1) + .map_or_else(|| Err(std::fmt::Error), Ok)?; + } + + let ret = type_name::>(); + + formatter.write_fmt(format_args!("CastableFactory ({}) -> {}", args, ret)) + } +} + +#[cfg(test)] +mod tests +{ + use super::*; + + #[derive(Debug, PartialEq, Eq)] + struct Bacon + { + heal_amount: u32, + } + + #[test] + fn can_call() + { + let castable_factory = + CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount })); + + let output = castable_factory.call((27,)); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); + } + + #[test] + fn can_call_mut() + { + let mut castable_factory = + CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount })); + + let output = castable_factory.call_mut((103,)); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 103 })); + } + + #[test] + fn can_call_once() + { + let castable_factory = + CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount })); + + let output = castable_factory.call_once((19,)); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 19 })); + } +} diff --git a/src/private/castable_factory/mod.rs b/src/private/castable_factory/mod.rs new file mode 100644 index 0000000..e81b842 --- /dev/null +++ b/src/private/castable_factory/mod.rs @@ -0,0 +1,4 @@ +pub mod blocking; + +#[cfg(feature = "async")] +pub mod threadsafe; diff --git a/src/private/castable_factory/threadsafe.rs b/src/private/castable_factory/threadsafe.rs new file mode 100644 index 0000000..3d2b653 --- /dev/null +++ b/src/private/castable_factory/threadsafe.rs @@ -0,0 +1,172 @@ +use std::any::type_name; +use std::fmt::Debug; +use std::marker::Tuple; + +use crate::private::any_factory::{AnyFactory, AnyThreadsafeFactory}; +use crate::private::factory::IThreadsafeFactory; +use crate::ptr::TransientPtr; + +pub struct ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + func: &'static (dyn Fn> + Send + Sync), +} + +impl ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + pub fn new( + func: &'static (dyn Fn> + + Send + + Sync), + ) -> Self + { + Self { func } + } +} + +impl IThreadsafeFactory + for ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ +} + +impl Fn for ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + extern "rust-call" fn call(&self, args: Args) -> Self::Output + { + self.func.call(args) + } +} + +impl FnMut + for ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output + { + self.call(args) + } +} + +impl FnOnce + for ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + type Output = TransientPtr; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output + { + self.call(args) + } +} + +impl AnyFactory + for ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ +} + +impl AnyThreadsafeFactory + for ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ +} + +impl Debug for ThreadsafeCastableFactory +where + Args: Tuple + 'static, + ReturnInterface: 'static + ?Sized, +{ + #[cfg(not(tarpaulin_include))] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + let mut args = type_name::(); + + if args.len() < 2 { + return Err(std::fmt::Error::default()); + } + + args = args + .get(1..args.len() - 1) + .map_or_else(|| Err(std::fmt::Error::default()), Ok)?; + + if args.ends_with(',') { + args = args + .get(..args.len() - 1) + .map_or_else(|| Err(std::fmt::Error), Ok)?; + } + + let ret = type_name::>(); + + formatter.write_fmt(format_args!( + "ThreadsafeCastableFactory ({}) -> {}", + args, ret + )) + } +} + +#[cfg(test)] +mod tests +{ + use super::*; + + #[derive(Debug, PartialEq, Eq)] + struct Bacon + { + heal_amount: u32, + } + + #[test] + fn can_call() + { + let castable_factory = ThreadsafeCastableFactory::new(&|heal_amount| { + TransientPtr::new(Bacon { heal_amount }) + }); + + let output = castable_factory.call((27,)); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); + } + + #[test] + fn can_call_mut() + { + let mut castable_factory = ThreadsafeCastableFactory::new(&|heal_amount| { + TransientPtr::new(Bacon { heal_amount }) + }); + + let output = castable_factory.call_mut((1092,)); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 1092 })); + } + + #[test] + fn can_call_once() + { + let castable_factory = ThreadsafeCastableFactory::new(&|heal_amount| { + TransientPtr::new(Bacon { heal_amount }) + }); + + let output = castable_factory.call_once((547,)); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 547 })); + } +} diff --git a/src/private/factory.rs b/src/private/factory.rs new file mode 100644 index 0000000..8b8354d --- /dev/null +++ b/src/private/factory.rs @@ -0,0 +1,23 @@ +use std::marker::Tuple; + +use crate::private::cast::CastFrom; +use crate::ptr::TransientPtr; + +/// Interface for a factory. +pub trait IFactory: + Fn> + CastFrom +where + Args: Tuple, + ReturnInterface: 'static + ?Sized, +{ +} + +/// Interface for a threadsafe factory. +#[cfg(feature = "async")] +pub trait IThreadsafeFactory: + Fn> + crate::private::cast::CastFromSync +where + Args: Tuple, + ReturnInterface: 'static + ?Sized, +{ +} diff --git a/src/private/mod.rs b/src/private/mod.rs new file mode 100644 index 0000000..8b20333 --- /dev/null +++ b/src/private/mod.rs @@ -0,0 +1,15 @@ +//! This module contains items that's not in the public API but is used by the +//! library user with the expansions of the macros in the syrette_macros crate. + +pub mod cast; + +pub extern crate linkme; + +#[cfg(feature = "factory")] +pub mod any_factory; + +#[cfg(feature = "factory")] +pub mod factory; + +#[cfg(feature = "factory")] +pub mod castable_factory; diff --git a/src/provider/async.rs b/src/provider/async.rs index 557617b..da42c7b 100644 --- a/src/provider/async.rs +++ b/src/provider/async.rs @@ -24,19 +24,19 @@ where #[cfg(feature = "factory")] Factory( crate::ptr::ThreadsafeFactoryPtr< - dyn crate::interfaces::any_factory::AnyThreadsafeFactory, + dyn crate::private::any_factory::AnyThreadsafeFactory, >, ), #[cfg(feature = "factory")] DefaultFactory( crate::ptr::ThreadsafeFactoryPtr< - dyn crate::interfaces::any_factory::AnyThreadsafeFactory, + dyn crate::private::any_factory::AnyThreadsafeFactory, >, ), #[cfg(feature = "factory")] AsyncDefaultFactory( crate::ptr::ThreadsafeFactoryPtr< - dyn crate::interfaces::any_factory::AnyThreadsafeFactory, + dyn crate::private::any_factory::AnyThreadsafeFactory, >, ), } @@ -228,7 +228,7 @@ pub enum AsyncFactoryVariant pub struct AsyncFactoryProvider { factory: crate::ptr::ThreadsafeFactoryPtr< - dyn crate::interfaces::any_factory::AnyThreadsafeFactory, + dyn crate::private::any_factory::AnyThreadsafeFactory, >, variant: AsyncFactoryVariant, } @@ -238,7 +238,7 @@ impl AsyncFactoryProvider { pub fn new( factory: crate::ptr::ThreadsafeFactoryPtr< - dyn crate::interfaces::any_factory::AnyThreadsafeFactory, + dyn crate::private::any_factory::AnyThreadsafeFactory, >, variant: AsyncFactoryVariant, ) -> Self @@ -354,7 +354,7 @@ mod tests #[cfg(feature = "factory")] async fn async_factory_provider_works() -> Result<(), Box> { - use crate::interfaces::any_factory::AnyThreadsafeFactory; + use crate::private::any_factory::AnyThreadsafeFactory; use crate::ptr::ThreadsafeFactoryPtr; #[derive(Debug)] diff --git a/src/provider/blocking.rs b/src/provider/blocking.rs index ebe0c37..ea506ab 100644 --- a/src/provider/blocking.rs +++ b/src/provider/blocking.rs @@ -16,11 +16,9 @@ where Transient(TransientPtr>), Singleton(SingletonPtr>), #[cfg(feature = "factory")] - Factory(crate::ptr::FactoryPtr), + Factory(crate::ptr::FactoryPtr), #[cfg(feature = "factory")] - DefaultFactory( - crate::ptr::FactoryPtr, - ), + DefaultFactory(crate::ptr::FactoryPtr), } #[cfg_attr(test, mockall::automock, allow(dead_code))] @@ -135,7 +133,7 @@ where #[cfg(feature = "factory")] pub struct FactoryProvider { - factory: crate::ptr::FactoryPtr, + factory: crate::ptr::FactoryPtr, is_default_factory: bool, } @@ -143,7 +141,7 @@ pub struct FactoryProvider impl FactoryProvider { pub fn new( - factory: crate::ptr::FactoryPtr, + factory: crate::ptr::FactoryPtr, is_default_factory: bool, ) -> Self { @@ -239,7 +237,7 @@ mod tests #[cfg(feature = "factory")] fn factory_provider_works() -> Result<(), Box> { - use crate::interfaces::any_factory::AnyFactory; + use crate::private::any_factory::AnyFactory; use crate::ptr::FactoryPtr; #[derive(Debug)] diff --git a/src/test_utils.rs b/src/test_utils.rs index db055d4..6fba778 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -10,7 +10,7 @@ pub mod subjects use crate::dependency_history::IDependencyHistory; use crate::di_container::blocking::IDIContainer; use crate::interfaces::injectable::Injectable; - use crate::libs::intertrait::CastFromSync; + use crate::private::cast::CastFromSync; use crate::ptr::TransientPtr; pub trait IUserManager -- cgit v1.2.3-18-g5258