hampusmat / syrette Goto Github PK
View Code? Open in Web Editor NEWThe convenient dependency injection library for Rust. Mirror of https://git.hampusmat.com/syrette
Home Page: https://git.hampusmat.com/syrette
License: Apache License 2.0
The convenient dependency injection library for Rust. Mirror of https://git.hampusmat.com/syrette
Home Page: https://git.hampusmat.com/syrette
License: Apache License 2.0
Currently, error handling in macros is basically just the use of .unwrap()
.
This has worked fine but produces unclear error messages. So it should be improved on.
One alternative is using the proc-macro-error crate.
The need to explicitly make injectables async compatible should be removed.
This would be simple if not for the fact that having the async
crate feature enable this by default would make it have a non-additive change. More about that here.
An alternative approach to this would be to only implement AsyncInjectable
when the type, dependencies and interface are Send + Sync + 'static
. This however is not possible (as far as i know) as long as trivial constraints is not stabilized. And even if it becomes stabilized, using it would break the 1.62.1 MSRV.
More research needs to be done about this
Having a test return a Result
makes it a major pain the butt to find out were Err
s occur. No line number is printed as it is when unwrap
or expect
is used.
Currently, constructors are expected to be functions called "new".
A flag could be added to the injectable
macro that overrides this.
It would look like this
#[injectable(IFoo, constructor = create)]
impl Foo
{
fn create(bar: TransientPtr<dyn IBar>) -> Self
{
Self { bar }
}
}
Add support for async constructors when the async
crate feature is enabled.
Support for stack allocation of Injectable
s could probably be implemented.
Stack allocation is to be possible if the interface is a concrete type.
This will require
get
to be able to return either a heap allocated value (like Box) or a stack allocated value.resolve
method of Injectable
s to figure out whether dependencies should be used as heap or stack valuesTo be able to pass the DI container as a reference in the future
The Injectable
and AsyncInjectable
traits can be implemented for all types which implement the Default
trait.
This could look something like this:
impl<T: Default, DIContainerT> Injectable<DIContainerT> for T
{
fn resolve(
_: &DIContainerT,
_: DependencyHistory,
) -> Result<TransientPtr<Self>, InjectableError>
{
Ok(TransientPtr::new(Self::default()))
}
}
This would make a type only be resolved if certain properties has specific values. Like naming it, but with arbitrary stuff.
Types could maybe a problem.
The IFactory
trait is completely useless. AnyFactory
can just be downcasted to CastableFactory
. This would completely remove the need for the factory
attribute macro.
It would be splendid if the dependency on Linkme was gotten rid of. This would make Syrette more portable.
However, more investigating needs to be made in order to know if this is even feasible.
For example in src/di_container/asynchronous/binding/scope_configurator.rs
/// Scope configurator for a binding for type 'Interface' inside a [`IAsyncDIContainer`].
' is used when ` should be used.
This is a problem in both the async & blocking binding configurators.
The traits IDIContainer
and IAsyncDIContainer
should be removed. They were created so that DIContainer
and AsyncDIContainer
can be mocked but it's much more ergonomic to just replace the whole struct. I don't know why i didn't do it that way.
This would be a great feature. It's complicated however.
The methods new
, push
and contains
of DependencyHistory
should be exposed to the public API. I don't know why i didn't do it that way to begin with
I don't know why i didn't make it thread-safe in the first place
The expansion of the injectable
attribute currently unwraps the Result
of retrieving the correct pointer type from SomePtr
macros/src/injectable/implementation.rs:283
Ok(quote! {
#do_method_call.map_err(|err| #resolve_failed_error {
reason: Box::new(err),
affected: self_type_name
})?.#to_ptr().unwrap()
})
I have no idea why i made it this way.
Replace it with the ?
operator.
And possibly rename it too
Version: 0.4.1
Problem:
Error: BindingResolveFailed { reason: ResolveFailed { reason: BindingResolveFailed { reason: ResolveFailed { reason: BindingResolveFailed { reason: DetectedCircular { dependency_history: DependencyHistory { inner: ["creditor::Foo", "creditor::Bar", "creditor::Foo"] } }, interface: "creditor::Foo" }, affected: "creditor::Bar" }, interface: "creditor::Bar" }, affected: "creditor::Foo" }, interface: "creditor::Foo" }
How to reproduce: This is the code I copied exactly from the example (https://git.hampusmat.com/syrette/tree/examples/prevent-circular)
#![deny(clippy::all)]
#![deny(clippy::pedantic)]
#![allow(clippy::disallowed_names)]
use std::error::Error;
use syrette::di_container::blocking::prelude::*;
use syrette::injectable;
use syrette::ptr::TransientPtr;
struct Foo
{
bar: TransientPtr<Bar>,
}
#[injectable]
impl Foo
{
fn new(bar: TransientPtr<Bar>) -> Self
{
Self { bar }
}
}
struct Bar
{
foo: TransientPtr<Foo>,
}
#[injectable]
impl Bar
{
fn new(foo: TransientPtr<Foo>) -> Self
{
Self { foo }
}
}
fn main() -> Result<(), anyhow::Error>
{
let mut di_container = DIContainer::new();
di_container.bind::<Foo>().to::<Foo>()?;
di_container.bind::<Bar>().to::<Bar>()?;
let foo = di_container.get::<Foo>()?.transient()?;
Ok(())
}
Singletons with a concrete type interface does not work with the async DI container.
File to reproduce:
Partially originally posted by @dotai2012 in #1 (comment)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.