avoid static references

This commit is contained in:
Dietmar Maurer 2018-11-03 15:10:21 +01:00
parent 331ab992d7
commit 0dde2f04d0
4 changed files with 107 additions and 116 deletions

View File

@ -7,20 +7,6 @@ use crate::api_info::*;
use serde_json::{json, Value}; use serde_json::{json, Value};
static GET: ApiMethod = ApiMethod {
handler: test_api_handler,
description: "This is a simple test.",
parameters: &Object!{
properties => &propertymap!{
force => &Boolean!{
optional => Some(true),
description => "Test for boolean options."
}
}
},
returns: &Jss::Null,
};
fn test_api_handler(param: Value) -> Result<Value, Error> { fn test_api_handler(param: Value) -> Result<Value, Error> {
println!("This is a test {}", param); println!("This is a test {}", param);
@ -39,22 +25,23 @@ fn test_api_handler(param: Value) -> Result<Value, Error> {
Ok(json!(null)) Ok(json!(null))
} }
pub fn get_api_definition() -> MethodInfo {
let subdir1 = methodinfo!{ pub fn router() -> MethodInfo {
get => &GET
};
let info = methodinfo!{
get => &GET,
subdirs => {
let mut map = HashMap::new();
map.insert(String::from("subdir"), subdir1); let route = MethodInfo::new()
.get(ApiMethod {
map handler: test_api_handler,
} description: "This is a simple test.",
}; parameters: parameter!{
force => Boolean!{
optional => Some(true),
description => "Test for boolean options."
}
},
returns: Jss::Null,
});
info route
} }

View File

@ -6,25 +6,40 @@ use serde_json::{Value};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]
pub struct ApiMethod<'a> { pub struct ApiMethod {
pub description: &'a str, pub description: &'static str,
pub parameters: &'a Jss<'a>, pub parameters: Jss,
pub returns: &'a Jss<'a>, pub returns: Jss,
pub handler: fn(Value) -> Result<Value, Error>, pub handler: fn(Value) -> Result<Value, Error>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct MethodInfo { pub struct MethodInfo {
pub get: Option<&'static ApiMethod<'static>>, pub get: Option<ApiMethod>,
pub put: Option<&'static ApiMethod<'static>>, pub put: Option<ApiMethod>,
pub post: Option<&'static ApiMethod<'static>>, pub post: Option<ApiMethod>,
pub delete: Option<&'static ApiMethod<'static>>, pub delete: Option<ApiMethod>,
pub subdirs: Option<HashMap<String, MethodInfo>>, pub subdirs: Option<HashMap<String, MethodInfo>>,
} }
impl MethodInfo { impl MethodInfo {
pub fn find_method<'a>(&'a self, components: &[&str]) -> Option<&'a MethodInfo> { pub fn new() -> Self {
Self {
get: None,
put: None,
post: None,
delete: None,
subdirs: None
}
}
pub fn get(mut self, m: ApiMethod) -> Self {
self.get = Some(m);
self
}
pub fn find_method(&self, components: &[&str]) -> Option<&MethodInfo> {
if components.len() == 0 { return Some(self); }; if components.len() == 0 { return Some(self); };
@ -40,20 +55,16 @@ impl MethodInfo {
} }
} }
pub const METHOD_INFO_DEFAULTS: MethodInfo = MethodInfo { // fixme: remove - not required?
get: None,
put: None,
post: None,
delete: None,
subdirs: None,
};
#[macro_export] #[macro_export]
macro_rules! methodinfo { macro_rules! methodinfo {
($($option:ident => $e:expr),*) => { ($($option:ident => $e:expr),*) => {{
MethodInfo { let info = MethodInfo::new();
$( $option: Some($e), )*
..METHOD_INFO_DEFAULTS $(
}; info.$option = Some($e);
} )*
info
}}
} }

View File

@ -1,17 +1,17 @@
use crate::static_map::StaticMap; use std::collections::HashMap;
pub type PropertyMap<'a> = StaticMap<'a, &'a str, &'a Jss<'a>>; pub type PropertyMap = HashMap<&'static str, Jss>;
#[derive(Debug)] #[derive(Debug)]
pub struct JssBoolean<'a> { pub struct JssBoolean {
pub description: &'a str, pub description: &'static str,
pub optional: Option<bool>, pub optional: Option<bool>,
pub default: Option<bool>, pub default: Option<bool>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct JssInteger<'a> { pub struct JssInteger {
pub description: &'a str, pub description: &'static str,
pub optional: Option<bool>, pub optional: Option<bool>,
pub minimum: Option<usize>, pub minimum: Option<usize>,
pub maximum: Option<usize>, pub maximum: Option<usize>,
@ -19,37 +19,37 @@ pub struct JssInteger<'a> {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct JssString<'a> { pub struct JssString {
pub description: &'a str, pub description: &'static str,
pub optional: Option<bool>, pub optional: Option<bool>,
pub default: Option<&'a str>, pub default: Option<&'static str>,
pub min_length: Option<usize>, pub min_length: Option<usize>,
pub max_length: Option<usize>, pub max_length: Option<usize>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct JssArray<'a> { pub struct JssArray {
pub description: &'a str, pub description: &'static str,
pub optional: Option<bool>, pub optional: Option<bool>,
pub items: &'a Jss<'a>, pub items: Box<Jss>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct JssObject<'a> { pub struct JssObject {
pub description: &'a str, pub description: &'static str,
pub optional: Option<bool>, pub optional: Option<bool>,
pub additional_properties: Option<bool>, pub additional_properties: Option<bool>,
pub properties: &'a PropertyMap<'a>, pub properties: Box<HashMap<&'static str, Jss>>,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum Jss<'a> { pub enum Jss {
Null, Null,
Boolean(JssBoolean<'a>), Boolean(JssBoolean),
Integer(JssInteger<'a>), Integer(JssInteger),
String(JssString<'a>), String(JssString),
Object(JssObject<'a>), Object(JssObject),
Array(JssArray<'a>), Array(JssArray),
} }
pub const DEFAULTBOOL: JssBoolean = JssBoolean { pub const DEFAULTBOOL: JssBoolean = JssBoolean {
@ -95,53 +95,45 @@ macro_rules! ApiString {
}} }}
} }
pub const DEFAULTARRAY: JssArray = JssArray {
description: "",
optional: None,
items: &Jss::Null, // is this a reasonable default??
};
#[macro_export] #[macro_export]
macro_rules! Array { macro_rules! parameter {
($($name:ident => $e:expr),*) => {{ ($($name:ident => $e:expr),*) => {{
Jss::Array(JssArray { $($name: $e, )* ..DEFAULTARRAY}) let inner = JssObject {
}} description: "",
} optional: None,
additional_properties: None,
properties: {
let mut map = HashMap::<&'static str, Jss>::new();
$(
map.insert(stringify!($name), $e);
)*
Box::new(map)
}
};
pub const EMPTYOBJECT: PropertyMap = PropertyMap { entries: &[] }; Jss::Object(inner)
pub const DEFAULTOBJECT: JssObject = JssObject {
description: "",
optional: None,
additional_properties: None,
properties: &EMPTYOBJECT, // is this a reasonable default??
};
#[macro_export]
macro_rules! Object {
($($name:ident => $e:expr),*) => {{
Jss::Object(JssObject { $($name: $e, )* ..DEFAULTOBJECT})
}} }}
} }
// Standard Option Definitions
pub static PVE_VMID: Jss = Integer!{
description => "The (unique) ID of the VM.",
minimum => Some(1)
};
#[macro_export] #[test]
macro_rules! propertymap { fn test_shema1() {
($($name:ident => $e:expr),*) => { let schema = Jss::Object(JssObject {
PropertyMap { description: "TEST",
entries: &[ optional: None,
$( ( stringify!($name), $e), )* additional_properties: None,
] properties: {
let map = HashMap::new();
Box::new(map)
} }
} });
println!("TEST Schema: {:?}", schema);
} }
/*
#[test] #[test]
fn test_shema1() { fn test_shema1() {
static PARAMETERS1: PropertyMap = propertymap!{ static PARAMETERS1: PropertyMap = propertymap!{
@ -186,3 +178,4 @@ fn test_shema1() {
} }
*/

View File

@ -59,14 +59,14 @@ fn handle_request(req: Request<Body>) -> Response<Body> {
http_error!(NOT_FOUND, format!("Unsupported format '{}'\n", format)) http_error!(NOT_FOUND, format!("Unsupported format '{}'\n", format))
} }
if let Some(info) = API_ROOT.find_method(&components[2..]) { if let Some(info) = ROUTER.find_method(&components[2..]) {
println!("FOUND INFO"); println!("FOUND INFO");
let api_method_opt = match method { let api_method_opt = match method {
&Method::GET => info.get, &Method::GET => &info.get,
&Method::PUT => info.put, // &Method::PUT => info.put,
&Method::POST => info.post, // &Method::POST => info.post,
&Method::DELETE => info.delete, // &Method::DELETE => info.delete,
_ => None, _ => &None,
}; };
let api_method = match api_method_opt { let api_method = match api_method_opt {
Some(m) => m, Some(m) => m,
@ -101,7 +101,7 @@ fn handle_request(req: Request<Body>) -> Response<Body> {
} }
lazy_static!{ lazy_static!{
static ref API_ROOT: MethodInfo = apitest::api3::get_api_definition(); static ref ROUTER: MethodInfo = apitest::api3::router();
} }
fn main() { fn main() {