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};
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> {
println!("This is a test {}", param);
@ -39,22 +25,23 @@ fn test_api_handler(param: Value) -> Result<Value, Error> {
Ok(json!(null))
}
pub fn get_api_definition() -> MethodInfo {
let subdir1 = methodinfo!{
get => &GET
};
pub fn router() -> MethodInfo {
let info = methodinfo!{
get => &GET,
subdirs => {
let mut map = HashMap::new();
let route = MethodInfo::new()
.get(ApiMethod {
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,
});
map.insert(String::from("subdir"), subdir1);
map
}
};
info
route
}

View File

@ -6,25 +6,40 @@ use serde_json::{Value};
use std::collections::HashMap;
#[derive(Debug)]
pub struct ApiMethod<'a> {
pub description: &'a str,
pub parameters: &'a Jss<'a>,
pub returns: &'a Jss<'a>,
pub struct ApiMethod {
pub description: &'static str,
pub parameters: Jss,
pub returns: Jss,
pub handler: fn(Value) -> Result<Value, Error>,
}
#[derive(Debug)]
pub struct MethodInfo {
pub get: Option<&'static ApiMethod<'static>>,
pub put: Option<&'static ApiMethod<'static>>,
pub post: Option<&'static ApiMethod<'static>>,
pub delete: Option<&'static ApiMethod<'static>>,
pub get: Option<ApiMethod>,
pub put: Option<ApiMethod>,
pub post: Option<ApiMethod>,
pub delete: Option<ApiMethod>,
pub subdirs: Option<HashMap<String, 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); };
@ -40,20 +55,16 @@ impl MethodInfo {
}
}
pub const METHOD_INFO_DEFAULTS: MethodInfo = MethodInfo {
get: None,
put: None,
post: None,
delete: None,
subdirs: None,
};
// fixme: remove - not required?
#[macro_export]
macro_rules! methodinfo {
($($option:ident => $e:expr),*) => {
MethodInfo {
$( $option: Some($e), )*
..METHOD_INFO_DEFAULTS
};
}
($($option:ident => $e:expr),*) => {{
let info = MethodInfo::new();
$(
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)]
pub struct JssBoolean<'a> {
pub description: &'a str,
pub struct JssBoolean {
pub description: &'static str,
pub optional: Option<bool>,
pub default: Option<bool>,
}
#[derive(Debug)]
pub struct JssInteger<'a> {
pub description: &'a str,
pub struct JssInteger {
pub description: &'static str,
pub optional: Option<bool>,
pub minimum: Option<usize>,
pub maximum: Option<usize>,
@ -19,37 +19,37 @@ pub struct JssInteger<'a> {
}
#[derive(Debug)]
pub struct JssString<'a> {
pub description: &'a str,
pub struct JssString {
pub description: &'static str,
pub optional: Option<bool>,
pub default: Option<&'a str>,
pub default: Option<&'static str>,
pub min_length: Option<usize>,
pub max_length: Option<usize>,
}
#[derive(Debug)]
pub struct JssArray<'a> {
pub description: &'a str,
pub struct JssArray {
pub description: &'static str,
pub optional: Option<bool>,
pub items: &'a Jss<'a>,
pub items: Box<Jss>,
}
#[derive(Debug)]
pub struct JssObject<'a> {
pub description: &'a str,
pub struct JssObject {
pub description: &'static str,
pub optional: Option<bool>,
pub additional_properties: Option<bool>,
pub properties: &'a PropertyMap<'a>,
pub properties: Box<HashMap<&'static str, Jss>>,
}
#[derive(Debug)]
pub enum Jss<'a> {
pub enum Jss {
Null,
Boolean(JssBoolean<'a>),
Integer(JssInteger<'a>),
String(JssString<'a>),
Object(JssObject<'a>),
Array(JssArray<'a>),
Boolean(JssBoolean),
Integer(JssInteger),
String(JssString),
Object(JssObject),
Array(JssArray),
}
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_rules! Array {
macro_rules! parameter {
($($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: &[] };
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})
Jss::Object(inner)
}}
}
// Standard Option Definitions
pub static PVE_VMID: Jss = Integer!{
description => "The (unique) ID of the VM.",
minimum => Some(1)
};
#[macro_export]
macro_rules! propertymap {
($($name:ident => $e:expr),*) => {
PropertyMap {
entries: &[
$( ( stringify!($name), $e), )*
]
#[test]
fn test_shema1() {
let schema = Jss::Object(JssObject {
description: "TEST",
optional: None,
additional_properties: None,
properties: {
let map = HashMap::new();
Box::new(map)
}
}
});
println!("TEST Schema: {:?}", schema);
}
/*
#[test]
fn test_shema1() {
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))
}
if let Some(info) = API_ROOT.find_method(&components[2..]) {
if let Some(info) = ROUTER.find_method(&components[2..]) {
println!("FOUND INFO");
let api_method_opt = match method {
&Method::GET => info.get,
&Method::PUT => info.put,
&Method::POST => info.post,
&Method::DELETE => info.delete,
_ => None,
&Method::GET => &info.get,
// &Method::PUT => info.put,
// &Method::POST => info.post,
// &Method::DELETE => info.delete,
_ => &None,
};
let api_method = match api_method_opt {
Some(m) => m,
@ -101,7 +101,7 @@ fn handle_request(req: Request<Body>) -> Response<Body> {
}
lazy_static!{
static ref API_ROOT: MethodInfo = apitest::api3::get_api_definition();
static ref ROUTER: MethodInfo = apitest::api3::router();
}
fn main() {