From 0ca86560bf42916c6f3c0a1e2222e6b65487d9bb Mon Sep 17 00:00:00 2001 From: kjuulh Date: Tue, 21 Feb 2023 22:40:42 +0100 Subject: [PATCH] feat(derive): Add derive macro for interface --- Cargo.lock | 12 +++++++++ Cargo.toml | 7 ++++- crates/char_sdk/Cargo.toml | 1 + crates/char_sdk/src/lib.rs | 33 ++++++++++++++++++++--- crates/char_sdk/src/std/dagger/mod.rs | 6 +++-- crates/char_sdk_derive/Cargo.toml | 12 +++++++++ crates/char_sdk_derive/src/lib.rs | 24 +++++++++++++++++ examples/service/char_plan/Cargo.toml | 4 +++ examples/service/char_plan/src/main.rs | 36 +++++++++++++++++++++++--- 9 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 crates/char_sdk_derive/Cargo.toml create mode 100644 crates/char_sdk_derive/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 24d9c5b..0e293bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,15 +79,27 @@ name = "char_plan" version = "0.1.0" dependencies = [ "char_sdk", + "char_sdk_derive", + "eyre", + "tokio", ] [[package]] name = "char_sdk" version = "0.1.0" dependencies = [ + "clap", "eyre", ] +[[package]] +name = "char_sdk_derive" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "clap" version = "4.1.6" diff --git a/Cargo.toml b/Cargo.toml index ed0cf3d..18dbc0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,10 @@ [workspace] -members = ["examples/service/char_plan", "crates/char_cli", "crates/char_sdk"] +members = [ + "examples/service/char_plan", + "crates/char_cli", + "crates/char_sdk", + "crates/char_sdk_derive", +] [workspace.dependencies] eyre = "0.6.8" diff --git a/crates/char_sdk/Cargo.toml b/crates/char_sdk/Cargo.toml index c9b6bf7..d5983d9 100644 --- a/crates/char_sdk/Cargo.toml +++ b/crates/char_sdk/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] eyre = { workspace = true } +clap = "4.1.6" diff --git a/crates/char_sdk/src/lib.rs b/crates/char_sdk/src/lib.rs index c7ab31d..4455d1d 100644 --- a/crates/char_sdk/src/lib.rs +++ b/crates/char_sdk/src/lib.rs @@ -1,20 +1,44 @@ pub mod std; -pub trait Action {} +pub enum ActionArg<'a> { + Required { name: &'a str, description: &'a str }, + Optional { name: &'a str, description: &'a str }, +} + +pub struct InputArg<'a> { + name: &'a str, + value: &'a str, +} + +pub struct ActionArgs<'a> { + pub name: &'a str, + pub args: Vec>, +} + +pub trait Action { + fn action<'a>(&self) -> ActionArgs<'a>; + fn execute(&self, args: &[&InputArg]) -> eyre::Result<()>; +} + pub trait Plugin {} -pub struct CharBuilder; +pub struct CharBuilder { + actions: Vec>, +} impl CharBuilder { pub fn new() -> Self { - CharBuilder + CharBuilder { + actions: Vec::new(), + } } pub fn add_context(mut self, context: C) -> Self { self } - pub fn add_action(mut self, action: impl Action) -> Self { + pub fn add_action(mut self, action: impl Into>) -> Self { + self.actions.push(action.into()); self } @@ -23,6 +47,7 @@ impl CharBuilder { } pub fn execute(mut self) -> eyre::Result<()> { + //clap::Command::new("").arg(a) Ok(()) } } diff --git a/crates/char_sdk/src/std/dagger/mod.rs b/crates/char_sdk/src/std/dagger/mod.rs index aab3ce9..fccba49 100644 --- a/crates/char_sdk/src/std/dagger/mod.rs +++ b/crates/char_sdk/src/std/dagger/mod.rs @@ -1,6 +1,8 @@ -pub struct Context {} +pub struct Plugin {} -impl Default for Context { +impl crate::Plugin for Plugin {} + +impl Default for Plugin { fn default() -> Self { Self {} } diff --git a/crates/char_sdk_derive/Cargo.toml b/crates/char_sdk_derive/Cargo.toml new file mode 100644 index 0000000..19fb65a --- /dev/null +++ b/crates/char_sdk_derive/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "char_sdk_derive" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +syn = "1.0.107" +quote = "1.0.23" +[lib] +proc-macro = true diff --git a/crates/char_sdk_derive/src/lib.rs b/crates/char_sdk_derive/src/lib.rs new file mode 100644 index 0000000..5b35580 --- /dev/null +++ b/crates/char_sdk_derive/src/lib.rs @@ -0,0 +1,24 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; +use quote::quote; + +#[proc_macro_derive(CharAction)] +pub fn derive_char_action_into_box(input: TokenStream) -> TokenStream { + let ast = syn::parse(input).unwrap(); + + // Build the trait implementation + impl_hello_macro(&ast) +} + +fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream { + let name = &ast.ident; + let gen = quote! { + impl Into> for #name { + fn into(self) -> Box { + Box::new(self) + } + } + }; + gen.into() +} diff --git a/examples/service/char_plan/Cargo.toml b/examples/service/char_plan/Cargo.toml index b98dd55..fc2837d 100644 --- a/examples/service/char_plan/Cargo.toml +++ b/examples/service/char_plan/Cargo.toml @@ -7,3 +7,7 @@ edition = "2021" [dependencies] char_sdk = { path = "../../../crates/char_sdk" } +char_sdk_derive = { path = "../../../crates/char_sdk_derive" } + +eyre = { workspace = true } +tokio = { workspace = true } diff --git a/examples/service/char_plan/src/main.rs b/examples/service/char_plan/src/main.rs index f661674..d9bbe21 100644 --- a/examples/service/char_plan/src/main.rs +++ b/examples/service/char_plan/src/main.rs @@ -1,14 +1,42 @@ -struct Run; -impl char_sdk::Action for Run {} +use char_sdk_derive::CharAction; +#[derive(CharAction)] +struct Run; + +impl char_sdk::Action for Run { + fn action<'a>(&self) -> char_sdk::ActionArgs<'a> { + char_sdk::ActionArgs { + name: "run", + args: vec![char_sdk::ActionArg::Required { + name: "profile", + description: "which release profile to use, takes ['release', 'test']", + }], + } + } + + fn execute(&self, args: &[&char_sdk::InputArg]) -> eyre::Result<()> { + todo!() + } +} + +#[derive(CharAction)] struct Build; -impl char_sdk::Action for Build {} + +impl char_sdk::Action for Build { + fn action<'a>(&self) -> char_sdk::ActionArgs<'a> { + todo!() + } + + fn execute(&self, args: &[&char_sdk::InputArg]) -> eyre::Result<()> { + todo!() + } +} fn main() { char_sdk::CharBuilder::new() - .add_context(char_sdk::std::dagger::Context::default()) .add_action(Run {}) .add_action(Build {}) + .add_plugin(char_sdk::std::dagger::Plugin::default()) .add_plugin(char_sdk::std::k8s::Plugin::default()) .execute() .unwrap();