-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(proc_macro): Minimal and complete conversion to kproc-macros
This commit deserves a bit more attention in terms of its description. I've never been a fan of `syn` because it's a large dependency and too complex for my use case. Additionally, I cannot remove `proc_macro2` if I want to. For this reason, I chose to write `kproc-macros` (https://github.com/vincenzopalazzo/kproc-macros), which implements a very lightweight parser for Rust procedural macros and provides an API to extend the procedural macros API to build your own parser. This commit introduces a basic version of the `kproc-macros` crate that allows me to perform debugging on it. Signed-off-by: Vincenzo Palazzo <[email protected]>
- Loading branch information
1 parent
8823c61
commit c0629bc
Showing
6 changed files
with
419 additions
and
358 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,58 @@ | ||
//! plugin macros usage example. | ||
extern crate clightningrpc_plugin_macros; | ||
use clightningrpc_plugin_macros::{ | ||
add_plugin_rpc, notification, plugin_register_notification, rpc_method, | ||
}; | ||
use serde_json::{json, Value}; | ||
use clightningrpc_plugin_macros::*; | ||
|
||
use serde_json::json; | ||
use serde_json::Value; | ||
|
||
use clightningrpc_plugin::commands::RPCCommand; | ||
use clightningrpc_plugin::errors::PluginError; | ||
use clightningrpc_plugin::plugin::Plugin; | ||
use clightningrpc_plugin::types::LogLevel; | ||
use clightningrpc_plugin::{add_rpc, register_notification}; | ||
|
||
#[derive(Clone)] | ||
struct State; | ||
|
||
#[rpc_method( | ||
rpc_name = "foo_macro", | ||
description = "This is a simple and short description" | ||
)] | ||
pub fn foo_rpc(_plugin: Plugin<()>, _request: Value) -> Result<Value, PluginError> { | ||
/// The name of the parameters can be used only if used, otherwise can be omitted | ||
/// the only rules that the macros require is to have a propriety with the following rules: | ||
/// - Plugin as _plugin | ||
/// - CLN JSON request as _request | ||
/// The function parameter can be specified in any order. | ||
let response = json!({"is_dynamic": _plugin.dynamic, "rpc_request": _request}); | ||
pub fn foo_rpc(plugin: &mut Plugin<State>, request: Value) -> Result<Value, PluginError> { | ||
let response = json!({"is_dynamic": plugin.dynamic, "rpc_request": request}); | ||
Ok(response) | ||
} | ||
|
||
#[notification(on = "rpc_command")] | ||
fn on_rpc(_plugin: Plugin<()>, _request: Value) { | ||
_plugin.log(LogLevel::Info, "received an RPC notification"); | ||
fn on_rpc(plugin: &mut Plugin<State>, request: &Value) { | ||
use clightningrpc_plugin::types::LogLevel; | ||
plugin.log(LogLevel::Info, "received an RPC notification"); | ||
} | ||
|
||
fn main() { | ||
// as fist step you need to make a new plugin instance | ||
// more docs about Plugin struct is provided under the clightning_plugin crate | ||
let mut plugin = Plugin::new((), true); | ||
|
||
// The macros helper that help to register a RPC method with the name | ||
// without worry about all the rules of the library | ||
add_plugin_rpc!(plugin, "foo_macro"); | ||
|
||
// the macros helper that help to register a notification with the | ||
// event name without worry about the rules of the library :) | ||
plugin_register_notification!(plugin, "rpc_command"); | ||
let mut plugin = Plugin::new(State, true); | ||
|
||
// FIXME: this is just for now, we will write a plugin macros | ||
// that define the definition like in the linux kernel a module is | ||
// defined. | ||
// | ||
// ``` | ||
// module! { | ||
// type: RustMinimal, | ||
// name: "rust_minimal", | ||
// author: "Rust for Linux Contributors", | ||
// description: "Rust minimal sample", | ||
// license: "GPL", | ||
// } | ||
// ``` | ||
let call = on_rpc(); | ||
plugin.register_notification(&call.on_event.clone(), call); | ||
let call = foo_rpc(); | ||
plugin.add_rpc_method( | ||
&call.name.clone(), | ||
&call.usage.clone(), | ||
&call.description.clone(), | ||
call, | ||
); | ||
plugin.start(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
//! A custom parser for the attributes | ||
use std::collections::HashMap; | ||
|
||
use kproc_parser::{ | ||
check, | ||
kparser::{KParserError, KParserTracer}, | ||
kproc_macros::KTokenStream, | ||
trace, | ||
}; | ||
|
||
pub(crate) struct AttributeParser {} | ||
|
||
impl AttributeParser { | ||
pub fn parse( | ||
stream: &mut KTokenStream, | ||
tracer: &dyn KParserTracer, | ||
) -> Result<HashMap<String, String>, KParserError> { | ||
parse_key_values(stream, tracer) | ||
} | ||
} | ||
|
||
fn parse_key_values( | ||
stream: &mut KTokenStream, | ||
tracer: &dyn KParserTracer, | ||
) -> Result<HashMap<String, String>, KParserError> { | ||
let mut hash_map = HashMap::new(); | ||
trace!(tracer, "start parsing key values"); | ||
trace!(tracer, "start with tok {}", stream.peek()); | ||
while !stream.is_end() { | ||
let key = stream.advance(); | ||
check!("=", stream.peek())?; | ||
let _ = stream.advance(); | ||
let value = stream.advance(); | ||
if !stream.is_end() && stream.match_tok(",") { | ||
trace!(tracer, "removing the `,` tok"); | ||
check!(",", stream.advance())?; | ||
} | ||
let value = value.to_string().replace("\"", ""); | ||
trace!(tracer, "key {key} = value {value}"); | ||
hash_map.insert(key.to_string(), value.to_string()); | ||
trace!(tracer, "map is {:?}", hash_map); | ||
} | ||
Ok(hash_map) | ||
} |
Oops, something went wrong.