mirror of
https://github.com/TECHNOFAB11/aerosol.git
synced 2025-12-10 23:20:06 +01:00
Initial commit
This commit is contained in:
commit
37a4b43a29
8 changed files with 555 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "aerosol"
|
||||
version = "0.1.0"
|
||||
authors = ["Diggory Blake <diggsey@googlemail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
tt-call = "1.0"
|
||||
failure = "0.1"
|
||||
155
src/context.rs
Normal file
155
src/context.rs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! private_define_context {
|
||||
{
|
||||
$caller:tt
|
||||
input = [{
|
||||
$name:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
}]
|
||||
} => {
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ private_define_context }]
|
||||
rest = [{ $($body)* }]
|
||||
~~> private_define_context! {
|
||||
$caller
|
||||
name = [{ $name }]
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
name = [{ $name:ident }]
|
||||
$(auto_field = [{ $auto_field:ident, $auto_t:ty, $factory:ty }])*
|
||||
$(field = [{ $field:ident, $t:ty }])*
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
result = [{
|
||||
#[derive(Clone, Debug)]
|
||||
struct $name {
|
||||
$($auto_field: $auto_t,)*
|
||||
$($field: $t,)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
fn new($($field: $t,)*) -> Result<Self, $crate::failure::Error> {
|
||||
Ok(Self {
|
||||
$($auto_field: <$factory as $crate::Factory>::build()?,)*
|
||||
$($field,)*
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
impl $crate::Provide<$auto_t> for $name {
|
||||
fn provide(&self) -> $auto_t {
|
||||
self.$auto_field.clone()
|
||||
}
|
||||
}
|
||||
impl $crate::ProvideWith<$auto_t> for $name {
|
||||
fn provide_with<E, F: FnOnce($auto_t) -> Result<$auto_t, E>>(&self, f: F) -> Result<Self, E> {
|
||||
let mut result = self.clone();
|
||||
result.$auto_field = f(result.$auto_field)?;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
$(
|
||||
impl $crate::Provide<$t> for $name {
|
||||
fn provide(&self) -> $t {
|
||||
self.$field.clone()
|
||||
}
|
||||
}
|
||||
impl $crate::ProvideWith<$t> for $name {
|
||||
fn provide_with<E, F: FnOnce($t) -> Result<$t, E>>(&self, f: F) -> Result<Self, E> {
|
||||
let mut result = self.clone();
|
||||
result.$field = f(result.$field)?;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
)*
|
||||
}]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
$(auto_field = [{ $($auto_field:tt)* }])*
|
||||
$(field = [{ $($field:tt)* }])*
|
||||
rest = [{ $field_name:ident: $t:ty [ $factory:ty ], $($rest:tt)* }]
|
||||
} => {
|
||||
private_define_context! {
|
||||
$caller
|
||||
$(auto_field = [{ $($auto_field)* }])*
|
||||
auto_field = [{ $field_name, $t, $factory }]
|
||||
$(field = [{ $($field)* }])*
|
||||
rest = [{ $($rest)+ }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
$(auto_field = [{ $($auto_field:tt)* }])*
|
||||
$(field = [{ $($field:tt)* }])*
|
||||
rest = [{ $field_name:ident: $t:ty [ $factory:ty ] }]
|
||||
} => {
|
||||
private_define_context! {
|
||||
$caller
|
||||
$(auto_field = [{ $($auto_field)* }])*
|
||||
auto_field = [{ $field_name, $t, $factory }]
|
||||
$(field = [{ $($field)* }])*
|
||||
rest = [{ }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
$(auto_field = [{ $($auto_field:tt)* }])*
|
||||
$(field = [{ $($field:tt)* }])*
|
||||
rest = [{ $field_name:ident: $t:ty, $($rest:tt)* }]
|
||||
} => {
|
||||
private_define_context! {
|
||||
$caller
|
||||
$(auto_field = [{ $($auto_field)* }])*
|
||||
$(field = [{ $($field)* }])*
|
||||
field = [{ $field_name, $t }]
|
||||
rest = [{ $($rest)+ }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
$(auto_field = [{ $($auto_field:tt)* }])*
|
||||
$(field = [{ $($field:tt)* }])*
|
||||
rest = [{ $field_name:ident: $t:ty }]
|
||||
} => {
|
||||
private_define_context! {
|
||||
$caller
|
||||
$(auto_field = [{ $($auto_field)* }])*
|
||||
$(field = [{ $($field)* }])*
|
||||
field = [{ $field_name, $t }]
|
||||
rest = [{ }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
$(auto_field = [{ $($auto_field:tt)* }])*
|
||||
$(field = [{ $($field:tt)* }])*
|
||||
rest = [{ }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
$(auto_field = [{ $($auto_field)* }])*
|
||||
$(field = [{ $($field)* }])*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! define_context {
|
||||
($($input:tt)*) => (
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ private_define_context }]
|
||||
input = [{ $($input)* }]
|
||||
}
|
||||
);
|
||||
}
|
||||
140
src/interface.rs
Normal file
140
src/interface.rs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! generate_trait_def {
|
||||
{
|
||||
$caller:tt
|
||||
name = [{ $name:ident }]
|
||||
bounds = [{ $($bounds:tt)+ }]
|
||||
getters = [{ $(
|
||||
{ $getter:ident $t:ty }
|
||||
)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
trait_def = [{
|
||||
pub trait $name: $($bounds)+ {
|
||||
$(fn $getter(&self) -> $t;)*
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! generate_trait_impl {
|
||||
{
|
||||
$caller:tt
|
||||
name = [{ $name:ident }]
|
||||
bounds = [{ $($bounds:tt)+ }]
|
||||
getters = [{ $(
|
||||
{ $getter:ident $t:ty }
|
||||
)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
trait_impl = [{
|
||||
impl<T: $($bounds)+> $name for T {
|
||||
$(fn $getter(&self) -> $t {
|
||||
$crate::Provide::<$t>::provide(self)
|
||||
})*
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! private_define_interface {
|
||||
{
|
||||
$caller:tt
|
||||
input = [{ $($input:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ parse_trait_def }]
|
||||
input = [{ $($input)* }]
|
||||
~~> private_define_interface! {
|
||||
$caller
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
name = [{ $name:ident }]
|
||||
body = [{ $(
|
||||
fn $getter:ident(&self) -> $t:ty;
|
||||
)* }]
|
||||
$(bound = [{ $($bound:tt)* }])*
|
||||
} => {
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ join }]
|
||||
sep = [{ + }]
|
||||
$(item = [{ $($bound)* }])*
|
||||
$(item = [{ $crate::Provide<$t> }])*
|
||||
~~> private_define_interface! {
|
||||
$caller
|
||||
name = [{ $name }]
|
||||
getters = [{ $(
|
||||
{ $getter $t }
|
||||
)* }]
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
name = [{ $name:ident }]
|
||||
getters = [{ $($getters:tt)* }]
|
||||
joined = [{ $($joined:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ generate_trait_def }]
|
||||
name = [{ $name }]
|
||||
bounds = [{ $($joined)* }]
|
||||
getters = [{ $($getters)* }]
|
||||
~~> private_define_interface! {
|
||||
$caller
|
||||
name = [{ $name }]
|
||||
getters = [{ $($getters)* }]
|
||||
bounds = [{ $($joined)* }]
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
name = [{ $name:ident }]
|
||||
getters = [{ $($getters:tt)* }]
|
||||
bounds = [{ $($bounds:tt)* }]
|
||||
trait_def = [{ $($trait_def:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ generate_trait_impl }]
|
||||
name = [{ $name }]
|
||||
bounds = [{ $($bounds)* }]
|
||||
getters = [{ $($getters)* }]
|
||||
~~> private_define_interface! {
|
||||
$caller
|
||||
trait_def = [{ $($trait_def)* }]
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
trait_def = [{ $($trait_def:tt)* }]
|
||||
trait_impl = [{ $($trait_impl:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
result = [{ $($trait_def)* $($trait_impl)* }]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! define_interface {
|
||||
($($input:tt)*) => (
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ private_define_interface }]
|
||||
input = [{ $($input)* }]
|
||||
}
|
||||
);
|
||||
}
|
||||
53
src/join.rs
Normal file
53
src/join.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! join {
|
||||
{
|
||||
$caller:tt
|
||||
sep = [{ $($sep:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
joined = [{ }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
sep = [{ $($sep:tt)* }]
|
||||
item = [{ $($head:tt)* }]
|
||||
$(
|
||||
item = [{ $($tail:tt)* }]
|
||||
)+
|
||||
} => {
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ $crate::join }]
|
||||
sep = [{ $($sep)* }]
|
||||
$(
|
||||
item = [{ $($tail)* }]
|
||||
)+
|
||||
~~> $crate::join! {
|
||||
$caller
|
||||
prepend = [{ $($head)* $($sep)* }]
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
sep = [{ $($sep:tt)* }]
|
||||
item = [{ $($head:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
joined = [{ $($head)* }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
prepend = [{ $($prepend:tt)* }]
|
||||
joined = [{ $($joined:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
joined = [{ $($prepend)* $($joined)* }]
|
||||
}
|
||||
};
|
||||
}
|
||||
31
src/lib.rs
Normal file
31
src/lib.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
pub extern crate tt_call;
|
||||
pub extern crate failure;
|
||||
|
||||
mod join;
|
||||
mod parse;
|
||||
mod interface;
|
||||
mod context;
|
||||
|
||||
|
||||
pub trait Provide<T> {
|
||||
fn provide(&self) -> T;
|
||||
}
|
||||
|
||||
pub trait Factory {
|
||||
type Object;
|
||||
fn build() -> Result<Self::Object, failure::Error>;
|
||||
}
|
||||
|
||||
pub trait ProvideWith<T>: Provide<T> + Sized {
|
||||
fn provide_with<E, F: FnOnce(T) -> Result<T, E>>(&self, f: F) -> Result<Self, E>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
72
src/main.rs
Normal file
72
src/main.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#![recursion_limit="512"]
|
||||
#![feature(trace_macros)]
|
||||
|
||||
extern crate aerosol;
|
||||
#[macro_use]
|
||||
extern crate tt_call;
|
||||
extern crate failure;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! tt_debug2 {
|
||||
{
|
||||
$(
|
||||
$output:ident = [{ $($tokens:tt)* }]
|
||||
)*
|
||||
} => {
|
||||
$(
|
||||
println!("{}",
|
||||
concat!(
|
||||
stringify!($output),
|
||||
" = [{ ",
|
||||
stringify!($($tokens)*),
|
||||
" }]",
|
||||
)
|
||||
);
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
aerosol::define_interface!(
|
||||
TestInterface {
|
||||
fn test_get(&self) -> Vec<u8>;
|
||||
}
|
||||
);
|
||||
|
||||
struct FooFactory;
|
||||
#[derive(Clone, Debug)]
|
||||
struct Foo;
|
||||
#[derive(Clone, Debug)]
|
||||
struct Bar;
|
||||
|
||||
impl aerosol::Factory for FooFactory {
|
||||
type Object = Foo;
|
||||
fn build() -> Result<Foo, failure::Error> { Ok(Foo) }
|
||||
}
|
||||
|
||||
aerosol::define_context!(
|
||||
TestContext {
|
||||
foo: Foo [FooFactory],
|
||||
bar: Bar
|
||||
}
|
||||
);
|
||||
|
||||
fn main() {
|
||||
|
||||
//trace_macros!(true);
|
||||
//aerosol::test_macro!();
|
||||
tt_call! {
|
||||
macro = [{ aerosol::private_define_interface }]
|
||||
input = [{ TestInterface {
|
||||
fn test_get(&self) -> Vec<u8>;
|
||||
} }]
|
||||
~~> tt_debug2
|
||||
}
|
||||
tt_call! {
|
||||
macro = [{ aerosol::private_define_context }]
|
||||
input = [{ TestContext {
|
||||
db: MyDatabase [PostgresFactory<MyDatabase>],
|
||||
pusher: PusherClient
|
||||
} }]
|
||||
~~> tt_debug2
|
||||
}
|
||||
}
|
||||
92
src/parse.rs
Normal file
92
src/parse.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! parse_bound {
|
||||
{
|
||||
$caller:tt
|
||||
input = [{ $($input:tt)* }]
|
||||
} => {
|
||||
parse_bound! {
|
||||
$caller
|
||||
rest = [{ $($input)* }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
$(bound = [{ $($bound:tt)* }])*
|
||||
rest = [{ $($rest:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ $crate::tt_call::parse_type }]
|
||||
input = [{ $($rest)* }]
|
||||
~~> parse_bound! {
|
||||
$caller
|
||||
$(bound = [{ $($bound)* }])*
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
$(bound = [{ $($bound:tt)* }])*
|
||||
type = [{ $($type:tt)* }]
|
||||
rest = [{ + $($rest:tt)* }]
|
||||
} => {
|
||||
parse_bound! {
|
||||
$caller
|
||||
$(bound = [{ $($bound)* }])*
|
||||
bound = [{ $($type)* }]
|
||||
rest = [{ $($rest)* }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
$(bound = [{ $($bound:tt)* }])*
|
||||
type = [{ $($type:tt)* }]
|
||||
rest = [{ $($rest:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
$(bound = [{ $($bound)* }])*
|
||||
bound = [{ $($type)* }]
|
||||
rest = [{ $($rest)* }]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! parse_trait_def {
|
||||
{
|
||||
$caller:tt
|
||||
input = [{ $name:ident { $($body:tt)* } }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
name = [{ $name }]
|
||||
body = [{ $($body)* }]
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
input = [{ $name:ident: $($rest:tt)* }]
|
||||
} => {
|
||||
$crate::tt_call::tt_call! {
|
||||
macro = [{ parse_bound }]
|
||||
input = [{ $($rest)* }]
|
||||
~~> parse_trait_def! {
|
||||
$caller
|
||||
name = [{ $name }]
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
$caller:tt
|
||||
name = [{ $name:ident }]
|
||||
$(bound = [{ $($bound:tt)* }])*
|
||||
rest = [{ { $($body:tt)* } }]
|
||||
} => {
|
||||
$crate::tt_call::tt_return! {
|
||||
$caller
|
||||
name = [{ $name }]
|
||||
body = [{ $($body)* }]
|
||||
$(bound = [{ $($bound)* }])*
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue