diff --git a/proxmox-api-macro/src/api.rs b/proxmox-api-macro/src/api.rs index 5f0acb6b..4fa2365c 100644 --- a/proxmox-api-macro/src/api.rs +++ b/proxmox-api-macro/src/api.rs @@ -336,19 +336,28 @@ impl SchemaItem { #[derive(Default)] /// Contains a sorted list of properties: pub struct SchemaObject { - properties: Vec<(FieldName, bool, Schema)>, + properties_: Vec<(FieldName, bool, Schema)>, } impl SchemaObject { pub fn new() -> Self { Self { - properties: Vec::new(), + properties_: Vec::new(), } } + #[inline] + fn properties_mut(&mut self) -> &mut [(FieldName, bool, Schema)] { + &mut self.properties_ + } + + fn sort_properties(&mut self) { + self.properties_.sort_by(|a, b| (a.0).cmp(&b.0)); + } + fn try_extract_from(obj: &mut JSONObject) -> Result { - Ok(Self { - properties: obj + let mut this = Self { + properties_: obj .remove_required_element("properties")? .into_object("object field definition")? .into_iter() @@ -371,17 +380,14 @@ impl SchemaObject { Ok(properties) }, - ) - // This must be kept sorted! - .map(|mut properties| { - properties.sort_by(|a, b| (a.0).cmp(&b.0)); - properties - })?, - }) + )?, + }; + this.sort_properties(); + Ok(this) } fn to_schema_inner(&self, ts: &mut TokenStream) -> Result<(), Error> { - for element in self.properties.iter() { + for element in self.properties_.iter() { let key = element.0.as_str(); let optional = element.1; let mut schema = TokenStream::new(); @@ -393,23 +399,28 @@ impl SchemaObject { fn find_property_by_ident(&self, key: &str) -> Option<&(FieldName, bool, Schema)> { match self - .properties + .properties_ .binary_search_by(|p| p.0.as_ident_str().cmp(key)) { - Ok(idx) => Some(&self.properties[idx]), + Ok(idx) => Some(&self.properties_[idx]), Err(_) => None, } } fn find_property_by_ident_mut(&mut self, key: &str) -> Option<&mut (FieldName, bool, Schema)> { match self - .properties + .properties_ .binary_search_by(|p| p.0.as_ident_str().cmp(key)) { - Ok(idx) => Some(&mut self.properties[idx]), + Ok(idx) => Some(&mut self.properties_[idx]), Err(_) => None, } } + + fn extend_properties(&mut self, new_fields: Vec<(FieldName, bool, Schema)>) { + self.properties_.extend(new_fields); + self.sort_properties(); + } } pub struct SchemaArray { diff --git a/proxmox-api-macro/src/api/structs.rs b/proxmox-api-macro/src/api/structs.rs index c8926dc8..18e79e99 100644 --- a/proxmox-api-macro/src/api/structs.rs +++ b/proxmox-api-macro/src/api/structs.rs @@ -73,7 +73,7 @@ fn handle_regular_struct( // We also keep a reference to the SchemaObject around since we derive missing fields // automatically. if let api::SchemaItem::Object(ref mut obj) = &mut schema.item { - for field in &mut obj.properties { + for field in obj.properties_mut() { schema_fields.insert(field.0.as_str().to_string(), field); } } else { @@ -140,7 +140,7 @@ fn handle_regular_struct( // add the fields we derived: if let api::SchemaItem::Object(ref mut obj) = &mut schema.item { - obj.properties.extend(new_fields); + obj.extend_properties(new_fields); } else { unreachable!(); } diff --git a/proxmox-api-macro/tests/types.rs b/proxmox-api-macro/tests/types.rs index efa7a814..8c8b5ddf 100644 --- a/proxmox-api-macro/tests/types.rs +++ b/proxmox-api-macro/tests/types.rs @@ -43,11 +43,6 @@ fn test_struct() { &::proxmox::api::schema::ObjectSchema::new( "An example of a simple struct type.", &[ - ( - "test_string", - false, - &::proxmox::api::schema::StringSchema::new("A test string.").schema(), - ), ( "another", true, @@ -56,6 +51,11 @@ fn test_struct() { ) .schema(), ), + ( + "test_string", + false, + &::proxmox::api::schema::StringSchema::new("A test string.").schema(), + ), ], ) .schema(); @@ -82,11 +82,6 @@ fn renamed_struct() { &::proxmox::api::schema::ObjectSchema::new( "An example of a struct with renamed fields.", &[ - ( - "test-string", - false, - &::proxmox::api::schema::StringSchema::new("A test string.").schema(), - ), ( "SomeOther", true, @@ -95,6 +90,11 @@ fn renamed_struct() { ) .schema(), ), + ( + "test-string", + false, + &::proxmox::api::schema::StringSchema::new("A test string.").schema(), + ), ], ) .schema();