/api/schema.rs: implement Schema::Option
This commit is contained in:
parent
fdb95d92dd
commit
0a35462c1e
@ -251,7 +251,7 @@ impl ArraySchema {
|
|||||||
pub struct ObjectSchema {
|
pub struct ObjectSchema {
|
||||||
pub description: &'static str,
|
pub description: &'static str,
|
||||||
pub additional_properties: bool,
|
pub additional_properties: bool,
|
||||||
pub properties: HashMap<&'static str, (bool, Arc<Schema>)>,
|
pub properties: HashMap<&'static str, Arc<Schema>>,
|
||||||
pub default_key: Option<&'static str>,
|
pub default_key: Option<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,12 +278,12 @@ impl ObjectSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn required<S: Into<Arc<Schema>>>(mut self, name: &'static str, schema: S) -> Self {
|
pub fn required<S: Into<Arc<Schema>>>(mut self, name: &'static str, schema: S) -> Self {
|
||||||
self.properties.insert(name, (false, schema.into()));
|
self.properties.insert(name, schema.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn optional<S: Into<Arc<Schema>>>(mut self, name: &'static str, schema: S) -> Self {
|
pub fn optional<S: Into<Arc<Schema>>>(mut self, name: &'static str, schema: S) -> Self {
|
||||||
self.properties.insert(name, (true, schema.into()));
|
self.properties.insert(name, Arc::new(Schema::Option(schema.into())));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,6 +296,7 @@ pub enum Schema {
|
|||||||
String(StringSchema),
|
String(StringSchema),
|
||||||
Object(ObjectSchema),
|
Object(ObjectSchema),
|
||||||
Array(ArraySchema),
|
Array(ArraySchema),
|
||||||
|
Option(Arc<Schema>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StringSchema> for Schema {
|
impl From<StringSchema> for Schema {
|
||||||
@ -455,6 +456,9 @@ pub fn parse_simple_value(value_str: &str, schema: &Schema) -> Result<Value, Err
|
|||||||
string_schema.check_constraints(value_str)?;
|
string_schema.check_constraints(value_str)?;
|
||||||
Value::String(value_str.into())
|
Value::String(value_str.into())
|
||||||
}
|
}
|
||||||
|
Schema::Option(option_schema) => {
|
||||||
|
parse_simple_value(value_str, option_schema)?
|
||||||
|
}
|
||||||
_ => bail!("unable to parse complex (sub) objects."),
|
_ => bail!("unable to parse complex (sub) objects."),
|
||||||
};
|
};
|
||||||
Ok(value)
|
Ok(value)
|
||||||
@ -472,7 +476,7 @@ pub fn parse_parameter_strings(data: &Vec<(String, String)>, schema: &ObjectSche
|
|||||||
let additional_properties = schema.additional_properties;
|
let additional_properties = schema.additional_properties;
|
||||||
|
|
||||||
for (key, value) in data {
|
for (key, value) in data {
|
||||||
if let Some((_optional, prop_schema)) = properties.get::<str>(key) {
|
if let Some(prop_schema) = properties.get::<str>(key) {
|
||||||
match prop_schema.as_ref() {
|
match prop_schema.as_ref() {
|
||||||
Schema::Array(array_schema) => {
|
Schema::Array(array_schema) => {
|
||||||
if params[key] == Value::Null {
|
if params[key] == Value::Null {
|
||||||
@ -523,9 +527,14 @@ pub fn parse_parameter_strings(data: &Vec<(String, String)>, schema: &ObjectSche
|
|||||||
}
|
}
|
||||||
|
|
||||||
if test_required && errors.len() == 0 {
|
if test_required && errors.len() == 0 {
|
||||||
for (name, (optional, _prop_schema)) in properties {
|
for (name, prop_schema) in properties {
|
||||||
if *optional == false && params[name] == Value::Null {
|
match prop_schema.as_ref() {
|
||||||
errors.push(format_err!("parameter '{}': parameter is missing and it is not optional.", name));
|
Schema::Option(_) => {},
|
||||||
|
_ => {
|
||||||
|
if params[name] == Value::Null {
|
||||||
|
errors.push(format_err!("parameter '{}': parameter is missing and it is not optional.", name));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -554,6 +563,11 @@ pub fn verify_json(data: &Value, schema: &Schema) -> Result<(), Error> {
|
|||||||
Schema::Array(array_schema) => {
|
Schema::Array(array_schema) => {
|
||||||
verify_json_array(data, &array_schema)?;
|
verify_json_array(data, &array_schema)?;
|
||||||
}
|
}
|
||||||
|
Schema::Option(option_schema) => {
|
||||||
|
if !data.is_null() {
|
||||||
|
verify_json(data, option_schema)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
Schema::Null => {
|
Schema::Null => {
|
||||||
if !data.is_null() {
|
if !data.is_null() {
|
||||||
bail!("Expected Null, but value is not Null.");
|
bail!("Expected Null, but value is not Null.");
|
||||||
@ -618,7 +632,7 @@ pub fn verify_json_object(data: &Value, schema: &ObjectSchema) -> Result<(), Err
|
|||||||
let additional_properties = schema.additional_properties;
|
let additional_properties = schema.additional_properties;
|
||||||
|
|
||||||
for (key, value) in map {
|
for (key, value) in map {
|
||||||
if let Some((_optional, prop_schema)) = properties.get::<str>(key) {
|
if let Some(prop_schema) = properties.get::<str>(key) {
|
||||||
match prop_schema.as_ref() {
|
match prop_schema.as_ref() {
|
||||||
Schema::Object(object_schema) => {
|
Schema::Object(object_schema) => {
|
||||||
verify_json_object(value, object_schema)?;
|
verify_json_object(value, object_schema)?;
|
||||||
@ -635,9 +649,14 @@ pub fn verify_json_object(data: &Value, schema: &ObjectSchema) -> Result<(), Err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, (optional, _prop_schema)) in properties {
|
for (name, prop_schema) in properties {
|
||||||
if *optional == false && data[name] == Value::Null {
|
match prop_schema.as_ref() {
|
||||||
bail!("property '{}': property is missing and it is not optional.", name);
|
Schema::Option(_) => {},
|
||||||
|
_ => {
|
||||||
|
if data[name] == Value::Null {
|
||||||
|
bail!("property '{}': property is missing and it is not optional.", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ fn record_done_arguments(done: &mut HashSet<String>, parameters: &ObjectSchema,
|
|||||||
for arg in list {
|
for arg in list {
|
||||||
if arg.starts_with("--") && arg.len() > 2 {
|
if arg.starts_with("--") && arg.len() > 2 {
|
||||||
let prop_name = arg[2..].to_owned();
|
let prop_name = arg[2..].to_owned();
|
||||||
if let Some((_, schema)) = parameters.properties.get::<str>(&prop_name) {
|
if let Some(schema) = parameters.properties.get::<str>(&prop_name) {
|
||||||
match schema.as_ref() {
|
match schema.as_ref() {
|
||||||
Schema::Array(_) => { /* do nothing */ }
|
Schema::Array(_) => { /* do nothing */ }
|
||||||
_ => { done.insert(prop_name); }
|
_ => { done.insert(prop_name); }
|
||||||
@ -147,7 +147,7 @@ fn print_simple_completion(
|
|||||||
print_simple_completion(cli_cmd, done, &arg_param[1..], args);
|
print_simple_completion(cli_cmd, done, &arg_param[1..], args);
|
||||||
return;
|
return;
|
||||||
} else if args.len() == 1 {
|
} else if args.len() == 1 {
|
||||||
if let Some((_, schema)) = cli_cmd.info.parameters.properties.get(prop_name) {
|
if let Some(schema) = cli_cmd.info.parameters.properties.get(prop_name) {
|
||||||
print_property_completion(schema, prop_name, &cli_cmd.completion_functions, &args[0]);
|
print_property_completion(schema, prop_name, &cli_cmd.completion_functions, &args[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,14 +164,14 @@ fn print_simple_completion(
|
|||||||
let last = &args[args.len()-1];
|
let last = &args[args.len()-1];
|
||||||
if last.starts_with("--") && last.len() > 2 {
|
if last.starts_with("--") && last.len() > 2 {
|
||||||
let prop_name = &last[2..];
|
let prop_name = &last[2..];
|
||||||
if let Some((_, schema)) = cli_cmd.info.parameters.properties.get(prop_name) {
|
if let Some(schema) = cli_cmd.info.parameters.properties.get(prop_name) {
|
||||||
print_property_completion(schema, prop_name, &cli_cmd.completion_functions, &prefix);
|
print_property_completion(schema, prop_name, &cli_cmd.completion_functions, &prefix);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, (_optional, _schema)) in &cli_cmd.info.parameters.properties {
|
for (name, _schema) in &cli_cmd.info.parameters.properties {
|
||||||
if done.contains(*name) { continue; }
|
if done.contains(*name) { continue; }
|
||||||
let option = String::from("--") + name;
|
let option = String::from("--") + name;
|
||||||
if option.starts_with(&prefix) {
|
if option.starts_with(&prefix) {
|
||||||
|
@ -75,7 +75,7 @@ pub fn parse_arguments<T: AsRef<str>>(
|
|||||||
None => {
|
None => {
|
||||||
let mut want_bool = false;
|
let mut want_bool = false;
|
||||||
let mut can_default = false;
|
let mut can_default = false;
|
||||||
if let Some((_optional, param_schema)) = properties.get::<str>(&name) {
|
if let Some(param_schema) = properties.get::<str>(&name) {
|
||||||
if let Schema::Boolean(boolean_schema) = param_schema.as_ref() {
|
if let Schema::Boolean(boolean_schema) = param_schema.as_ref() {
|
||||||
want_bool = true;
|
want_bool = true;
|
||||||
if let Some(default) = boolean_schema.default {
|
if let Some(default) = boolean_schema.default {
|
||||||
|
@ -150,9 +150,14 @@ impl SectionConfig {
|
|||||||
let mut state = ParseState::BeforeHeader;
|
let mut state = ParseState::BeforeHeader;
|
||||||
|
|
||||||
let test_required_properties = |value: &Value, schema: &ObjectSchema| -> Result<(), Error> {
|
let test_required_properties = |value: &Value, schema: &ObjectSchema| -> Result<(), Error> {
|
||||||
for (name, (optional, _prop_schema)) in &schema.properties {
|
for (name, prop_schema) in &schema.properties {
|
||||||
if *optional == false && value[name] == Value::Null {
|
match prop_schema.as_ref() {
|
||||||
return Err(format_err!("property '{}' is missing and it is not optional.", name));
|
Schema::Option(_) => {},
|
||||||
|
_ => {
|
||||||
|
if value[name] == Value::Null {
|
||||||
|
return Err(format_err!("property '{}' is missing and it is not optional.", name));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -204,7 +209,7 @@ impl SectionConfig {
|
|||||||
if let Some((key, value)) = (self.parse_section_content)(line) {
|
if let Some((key, value)) = (self.parse_section_content)(line) {
|
||||||
//println!("CONTENT: key: {} value: {}", key, value);
|
//println!("CONTENT: key: {} value: {}", key, value);
|
||||||
|
|
||||||
if let Some((_optional, prop_schema)) = plugin.properties.properties.get::<str>(&key) {
|
if let Some(prop_schema) = plugin.properties.properties.get::<str>(&key) {
|
||||||
match parse_simple_value(&value, prop_schema) {
|
match parse_simple_value(&value, prop_schema) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
if config[&key] == Value::Null {
|
if config[&key] == Value::Null {
|
||||||
|
Loading…
Reference in New Issue
Block a user