another way to initialize the api tree

This commit is contained in:
Dietmar Maurer 2018-11-03 10:42:48 +01:00
parent 0e6967d648
commit 504b359724
5 changed files with 91 additions and 90 deletions

View File

@ -18,3 +18,4 @@ serde_json = "1.0.32"
serde_derive = "1.0.80" serde_derive = "1.0.80"
url = "1.7.1" url = "1.7.1"
hyper = "0.12.13" hyper = "0.12.13"
lazy_static = "1.1.0"

60
src/api3.rs Normal file
View File

@ -0,0 +1,60 @@
use failure::*;
use std::collections::HashMap;
use crate::json_schema::*;
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);
// let force: Option<bool> = Some(false);
//if let Some(force) = param.force {
//}
let _force = param["force"].as_bool()
.ok_or_else(|| format_err!("missing parameter 'force'"))?;
if let Some(_force) = param["force"].as_bool() {
}
Ok(json!(null))
}
pub fn get_api_definition() -> MethodInfo {
let subdir1 = methodinfo!{
get => &GET
};
let info = methodinfo!{
get => &GET,
subdirs => {
let mut map = HashMap::new();
map.insert(String::from("subdir"), subdir1);
map
}
};
info
}

View File

@ -3,46 +3,35 @@ use failure::*;
use crate::json_schema::*; use crate::json_schema::*;
use serde_json::{Value}; use serde_json::{Value};
use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]
pub struct ApiMethod<'a> { pub struct ApiMethod<'a> {
pub description: &'a str, pub description: &'a str,
pub properties: &'a PropertyMap<'a>, pub parameters: &'a Jss<'a>,
pub returns: &'a Jss<'a>, pub returns: &'a Jss<'a>,
pub handler: fn(Value) -> Result<Value, Error>, pub handler: fn(Value) -> Result<Value, Error>,
} }
pub type SubdirMap<'a> = crate::static_map::StaticMap<'a, &'a str, &'a MethodInfo<'a>>;
#[macro_export]
macro_rules! subdirmap {
($($name:ident => $e:expr),*) => {{
SubdirMap {
entries: &[
$( ( stringify!($name), $e), )*
]
}
}}
}
#[derive(Debug)] #[derive(Debug)]
pub struct MethodInfo<'a> { pub struct MethodInfo {
pub get: Option<&'a ApiMethod<'a>>, pub get: Option<&'static ApiMethod<'static>>,
pub put: Option<&'a ApiMethod<'a>>, pub put: Option<&'static ApiMethod<'static>>,
pub post: Option<&'a ApiMethod<'a>>, pub post: Option<&'static ApiMethod<'static>>,
pub delete: Option<&'a ApiMethod<'a>>, pub delete: Option<&'static ApiMethod<'static>>,
pub subdirs: Option<&'a SubdirMap<'a>>, pub subdirs: Option<HashMap<String, MethodInfo>>,
} }
impl<'a> MethodInfo<'a> { impl MethodInfo {
pub fn find_method(&'a self, components: &[&str]) -> Option<&'a MethodInfo<'a>> { pub fn find_method<'a>(&'a self, components: &[&str]) -> Option<&'a MethodInfo> {
if components.len() == 0 { return Some(self); }; if components.len() == 0 { return Some(self); };
let (dir, rest) = (components[0], &components[1..]); let (dir, rest) = (components[0], &components[1..]);
if let Some(ref dirmap) = self.subdirs { if let Some(ref dirmap) = self.subdirs {
if let Some(info) = dirmap.get(&dir) { if let Some(ref info) = dirmap.get(dir) {
return info.find_method(rest); return info.find_method(rest);
} }
} }
@ -51,7 +40,7 @@ impl<'a> MethodInfo<'a> {
} }
} }
pub static METHOD_INFO_DEFAULTS: MethodInfo = MethodInfo { pub const METHOD_INFO_DEFAULTS: MethodInfo = MethodInfo {
get: None, get: None,
put: None, put: None,
post: None, post: None,
@ -61,8 +50,8 @@ pub static METHOD_INFO_DEFAULTS: MethodInfo = MethodInfo {
#[macro_export] #[macro_export]
macro_rules! methodinfo { macro_rules! methodinfo {
($name:ident, $($option:ident => $e:expr),*) => { ($($option:ident => $e:expr),*) => {
static $name: MethodInfo = MethodInfo { MethodInfo {
$( $option: Some($e), )* $( $option: Some($e), )*
..METHOD_INFO_DEFAULTS ..METHOD_INFO_DEFAULTS
}; };

View File

@ -1,3 +1,10 @@
pub mod static_map; pub mod static_map;
#[macro_use]
pub mod json_schema; pub mod json_schema;
#[macro_use]
pub mod api_info; pub mod api_info;
pub mod api3;

View File

@ -1,15 +1,14 @@
#[macro_use]
extern crate apitest; extern crate apitest;
use failure::*; //use failure::*;
use std::collections::HashMap; use std::collections::HashMap;
use lazy_static::lazy_static;
//use apitest::json_schema::*;
use apitest::json_schema::*;
use apitest::api_info::*; use apitest::api_info::*;
use serde_derive::{Serialize, Deserialize}; //use serde_derive::{Serialize, Deserialize};
use serde_json::{json, Value}; use serde_json::{json, Value};
use url::form_urlencoded; use url::form_urlencoded;
@ -18,65 +17,6 @@ use hyper::{Method, Body, Request, Response, Server, StatusCode};
use hyper::rt::Future; use hyper::rt::Future;
use hyper::service::service_fn_ok; use hyper::service::service_fn_ok;
#[derive(Serialize, Deserialize)]
struct Myparam {
test: bool,
}
fn test_api_handler(param: Value) -> Result<Value, Error> {
println!("This is a test {}", param);
// let force: Option<bool> = Some(false);
//if let Some(force) = param.force {
//}
let _force = param["force"].as_bool()
.ok_or_else(|| format_err!("missing parameter 'force'"))?;
if let Some(_force) = param["force"].as_bool() {
}
let _tmp: Myparam = serde_json::from_value(param)?;
Ok(json!(null))
}
static TEST_API_METHOD: ApiMethod = ApiMethod {
description: "This is a simple test.",
properties: &propertymap!{
force => &Boolean!{
optional => Some(true),
description => "Test for boolean options."
}
},
returns: &Jss::Null,
handler: test_api_handler,
};
methodinfo!{
API3_TEST,
}
methodinfo!{
API3_NODES,
get => &TEST_API_METHOD
}
methodinfo!{
API_ROOT,
get => &TEST_API_METHOD,
subdirs => &subdirmap!{
test => &API3_TEST,
nodes => &API3_NODES
}
}
macro_rules! http_error { macro_rules! http_error {
($status:ident, $msg:expr) => {{ ($status:ident, $msg:expr) => {{
let mut resp = Response::new(Body::from($msg)); let mut resp = Response::new(Body::from($msg));
@ -160,6 +100,10 @@ fn handle_request(req: Request<Body>) -> Response<Body> {
Response::new(Body::from("RETURN WEB GUI\n")) Response::new(Body::from("RETURN WEB GUI\n"))
} }
lazy_static!{
static ref API_ROOT: MethodInfo = apitest::api3::get_api_definition();
}
fn main() { fn main() {
println!("Fast Static Type Definitions 1"); println!("Fast Static Type Definitions 1");