mirror of
https://github.com/TECHNOFAB11/aerosol.git
synced 2025-12-11 23:50:07 +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