From 82df76fff0606a46e6891d530e77995ffc543cb0 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Fri, 23 Nov 2018 09:33:41 +0100 Subject: [PATCH] start using builder pattern instead of macros --- src/api/registry.rs | 24 +++-- src/api/schema.rs | 223 +++++++++++++++++++++++++++++++------------- src/api3.rs | 7 +- src/getopts.rs | 6 +- src/main.rs | 4 +- 5 files changed, 176 insertions(+), 88 deletions(-) diff --git a/src/api/registry.rs b/src/api/registry.rs index c2bcc28e..6725cdaf 100644 --- a/src/api/registry.rs +++ b/src/api/registry.rs @@ -27,7 +27,7 @@ impl Registry { pub fn register_format(&mut self, name: &'static str, format: ApiStringFormat) { - if let Some(format) = self.formats.get(name) { + if let Some(_format) = self.formats.get(name) { panic!("standard format '{}' already registered.", name); // fixme: really panic? } @@ -42,13 +42,13 @@ impl Registry { None } - pub fn register_option(&mut self, name: &'static str, schema: Schema) { + pub fn register_option>(&mut self, name: &'static str, schema: S) { - if let Some(schema) = self.options.get(name) { + if let Some(_schema) = self.options.get(name) { panic!("standard option '{}' already registered.", name); // fixme: really panic? } - self.options.insert(name, Arc::new(schema)); + self.options.insert(name, Arc::new(schema.into())); } pub fn lookup_option(&self, name: &str) -> Option> { @@ -69,18 +69,16 @@ impl Registry { self.register_option( "pve-vmid", - Integer!{ - description => "The (unique) ID of the VM.", - minimum => Some(1), - optional => false - }); + IntegerSchema::new("The (unique) ID of the VM.") + .minimum(1) + .optional(false) + ); self.register_option( "pve-node", - ApiString!{ - description => "The cluster node name.", - format => self.lookup_format("pve-node") - }); + StringSchema::new("The cluster node name.") + .format(self.lookup_format("pve-node").unwrap()) //fixme: unwrap? + ); } } diff --git a/src/api/schema.rs b/src/api/schema.rs index 2f8f6409..a61de4ed 100644 --- a/src/api/schema.rs +++ b/src/api/schema.rs @@ -45,6 +45,31 @@ pub struct BooleanSchema { pub default: Option, } +impl BooleanSchema { + + pub fn new(description: &'static str) -> Self { + BooleanSchema { + description: description, + optional: false, + default: None, + } + } + + pub fn optional(mut self, optional: bool) -> Self { + self.optional = optional; + self + } + + pub fn default(mut self, default: bool) -> Self { + self.default = Some(default); + self + } + + pub fn arc(self) -> Arc { + Arc::new(self.into()) + } +} + #[derive(Debug)] pub struct IntegerSchema { pub description: &'static str, @@ -54,6 +79,44 @@ pub struct IntegerSchema { pub default: Option, } +impl IntegerSchema { + + pub fn new(description: &'static str) -> Self { + IntegerSchema { + description: description, + optional: false, + default: None, + minimum: None, + maximum: None, + } + } + + pub fn optional(mut self, optional: bool) -> Self { + self.optional = optional; + self + } + + pub fn default(mut self, default: isize) -> Self { + self.default = Some(default); + self + } + + pub fn minimum(mut self, minimum: isize) -> Self { + self.minimum = Some(minimum); + self + } + + pub fn maximum(mut self, maximium: isize) -> Self { + self.maximum = Some(maximium); + self + } + + pub fn arc(self) -> Arc { + Arc::new(self.into()) + } +} + + #[derive(Debug)] pub struct StringSchema { pub description: &'static str, @@ -64,6 +127,49 @@ pub struct StringSchema { pub format: Option>, } +impl StringSchema { + + pub fn new(description: &'static str) -> Self { + StringSchema { + description: description, + optional: false, + default: None, + min_length: None, + max_length: None, + format: None, + } + } + + pub fn optional(mut self, optional: bool) -> Self { + self.optional = optional; + self + } + + pub fn default(mut self, text: &'static str) -> Self { + self.default = Some(text); + self + } + + pub fn format(mut self, format: Arc) -> Self { + self.format = Some(format); + self + } + + pub fn min_length(mut self, min_length: usize) -> Self { + self.min_length = Some(min_length); + self + } + + pub fn max_length(mut self, max_length: usize) -> Self { + self.max_length = Some(max_length); + self + } + + pub fn arc(self) -> Arc { + Arc::new(self.into()) + } +} + #[derive(Debug)] pub struct ArraySchema { pub description: &'static str, @@ -89,42 +195,23 @@ pub enum Schema { Array(ArraySchema), } -pub const DEFAULTBOOL: BooleanSchema = BooleanSchema { - description: "", - optional: false, - default: None, -}; - -#[macro_export] -macro_rules! Boolean { - ($($name:ident => $e:expr),*) => {{ - Schema::Boolean(BooleanSchema { $($name: $e, )* ..DEFAULTBOOL}) - }} +impl From for Schema { + fn from(string_schema: StringSchema) -> Self { + Schema::String(string_schema) + } } -pub const DEFAULTINTEGER: IntegerSchema = IntegerSchema { - description: "", - optional: false, - default: None, - minimum: None, - maximum: None, -}; - -#[macro_export] -macro_rules! Integer { - ($($name:ident => $e:expr),*) => {{ - Schema::Integer(IntegerSchema { $($name: $e, )* ..DEFAULTINTEGER}) - }} +impl From for Schema { + fn from(boolean_schema: BooleanSchema) -> Self { + Schema::Boolean(boolean_schema) + } } -pub const DEFAULTSTRING: StringSchema = StringSchema { - description: "", - optional: false, - default: None, - min_length: None, - max_length: None, - format: None, -}; +impl From for Schema { + fn from(integer_schema: IntegerSchema) -> Self { + Schema::Integer(integer_schema) + } +} pub enum ApiStringFormat { Enum(Vec), @@ -152,13 +239,6 @@ impl std::fmt::Debug for ApiStringFormat { } } -#[macro_export] -macro_rules! ApiString { - ($($name:ident => $e:expr),*) => {{ - Schema::String(StringSchema { $($name: $e, )* ..DEFAULTSTRING}) - }} -} - #[macro_export] macro_rules! parameter { @@ -377,24 +457,25 @@ fn test_schema1() { #[test] fn test_query_string() { - let schema = parameter!{name => Arc::new(ApiString!{ optional => false })}; + let schema = parameter!{name => StringSchema::new("Name.").optional(false).arc()}; let res = parse_query_string("", &schema, true); assert!(res.is_err()); - let schema = parameter!{name => Arc::new(ApiString!{ optional => true })}; + let schema = parameter!{name => StringSchema::new("Name.").optional(true).arc()}; let res = parse_query_string("", &schema, true); assert!(res.is_ok()); // TEST min_length and max_length - let schema = parameter!{name => Arc::new(ApiString!{ - optional => false, - min_length => Some(5), - max_length => Some(10) - - })}; + let schema = parameter!{ + name => StringSchema::new("Name.") + .optional(false) + .min_length(5) + .max_length(10) + .arc() + }; let res = parse_query_string("name=abcd", &schema, true); assert!(res.is_err()); @@ -410,10 +491,12 @@ fn test_query_string() { // TEST regex pattern - let schema = parameter!{name => Arc::new(ApiString!{ - optional => false, - format => Some(Arc::new(ApiStringFormat::Pattern(Box::new(Regex::new("test").unwrap())))) - })}; + let schema = parameter!{ + name => StringSchema::new("Name.") + .optional(false) + .format(Arc::new(ApiStringFormat::Pattern(Box::new(Regex::new("test").unwrap())))) + .arc() + }; let res = parse_query_string("name=abcd", &schema, true); assert!(res.is_err()); @@ -421,10 +504,12 @@ fn test_query_string() { let res = parse_query_string("name=ateststring", &schema, true); assert!(res.is_ok()); - let schema = parameter!{name => Arc::new(ApiString!{ - optional => false, - format => Some(Arc::new(ApiStringFormat::Pattern(Box::new(Regex::new("^test$").unwrap())))) - })}; + let schema = parameter!{ + name => StringSchema::new("Name.") + .optional(false) + .format(Arc::new(ApiStringFormat::Pattern(Box::new(Regex::new("^test$").unwrap())))) + .arc() + }; let res = parse_query_string("name=ateststring", &schema, true); assert!(res.is_err()); @@ -434,10 +519,12 @@ fn test_query_string() { // TEST string enums - let schema = parameter!{name => Arc::new(ApiString!{ - optional => false, - format => Some(Arc::new(ApiStringFormat::Enum(vec!["ev1".into(), "ev2".into()]))) - })}; + let schema = parameter!{ + name => StringSchema::new("Name.") + .optional(false) + .format(Arc::new(ApiStringFormat::Enum(vec!["ev1".into(), "ev2".into()]))) + .arc() + }; let res = parse_query_string("name=noenum", &schema, true); assert!(res.is_err()); @@ -456,16 +543,18 @@ fn test_query_string() { #[test] fn test_query_integer() { - let schema = parameter!{count => Arc::new(Integer!{ optional => false })}; + let schema = parameter!{count => IntegerSchema::new("Count.").optional(false).arc()}; let res = parse_query_string("", &schema, true); assert!(res.is_err()); - let schema = parameter!{count => Arc::new(Integer!{ - optional => true, - minimum => Some(-3), - maximum => Some(50) - })}; + let schema = parameter!{ + count => IntegerSchema::new("Count.") + .optional(true) + .minimum(-3) + .maximum(50) + .arc() + }; let res = parse_query_string("", &schema, true); assert!(res.is_ok()); @@ -495,12 +584,12 @@ fn test_query_integer() { #[test] fn test_query_boolean() { - let schema = parameter!{force => Arc::new(Boolean!{ optional => false })}; + let schema = parameter!{force => BooleanSchema::new("Force.").optional(false).arc()}; let res = parse_query_string("", &schema, true); assert!(res.is_err()); - let schema = parameter!{force => Arc::new(Boolean!{ optional => true })}; + let schema = parameter!{force => BooleanSchema::new("Force.").optional(true).arc()}; let res = parse_query_string("", &schema, true); assert!(res.is_ok()); diff --git a/src/api3.rs b/src/api3.rs index abc97134..96d2dc92 100644 --- a/src/api3.rs +++ b/src/api3.rs @@ -45,10 +45,9 @@ pub fn router() -> Router { handler: test_sync_api_handler, description: "This is a simple test.", parameters: parameter!{ - force => Arc::new(Boolean!{ - optional => true, - description => "Test for boolean options." - }) + force => BooleanSchema::new("Test for boolean options") + .optional(true) + .arc() }, returns: Schema::Null, }) diff --git a/src/getopts.rs b/src/getopts.rs index 0628f581..e88e3fa1 100644 --- a/src/getopts.rs +++ b/src/getopts.rs @@ -156,7 +156,7 @@ pub fn parse_arguments( #[test] fn test_boolean_arg() { - let schema = parameter!{enable => Arc::new(Boolean!{ optional => false })}; + let schema = parameter!{enable => BooleanSchema::new("Enable").optional(false).arc()}; let mut variants: Vec<(Vec<&str>, bool)> = vec![]; variants.push((vec!["-enable"], true)); @@ -187,8 +187,8 @@ fn test_boolean_arg() { fn test_argument_paramenter() { let schema = parameter!{ - enable => Arc::new(Boolean!{ optional => false }), - storage => Arc::new(ApiString!{ optional => false }) + enable => BooleanSchema::new("Enable.").optional(false).arc(), + storage => StringSchema::new("Storatge:").optional(false).arc() }; let args = vec!["-enable", "local"]; diff --git a/src/main.rs b/src/main.rs index 073b40ca..8f060193 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,9 @@ use hyper; fn main() { println!("Proxmox REST Server example."); - let prop = Arc::new(ApiString!{ optional => true }); + let prop = StringSchema::new("This is a test").arc(); + + //let prop = Arc::new(ApiString!{ optional => true }); let schema = parameter!{ name1 => prop.clone(), name2 => prop.clone()