From f47743f3cfdbcc141c6a5890ae5db9045b17d39f Mon Sep 17 00:00:00 2001 From: HideBa Date: Sat, 21 Dec 2024 17:14:03 +0100 Subject: [PATCH 01/19] feat: add type to boundaries --- src/lib.rs | 320 ++++++++++++++++++++--------------------------------- 1 file changed, 123 insertions(+), 197 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0f28db5..ef12892 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use serde_json::{json, Error, Value}; +use serde_json::{json, Error, Number, Value}; use std::collections::HashMap; const DEFAULT_CRS_BASE_URL: &str = "http://www.opengis.net/def/crs"; @@ -503,13 +503,107 @@ pub enum GeometryType { GeometryInstance, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Boundaries { + Indices(Vec), + Nested(Vec), +} + +impl Boundaries { + fn update_indices_recursively(&mut self, violdnew: &mut HashMap) { + match self { + Boundaries::Indices(arr) => { + for i in 0..arr.len() { + let old_idx = arr[i]; + let new_idx = { + let len = violdnew.len(); + *violdnew.entry(old_idx as usize).or_insert_with(|| len) + }; + arr[i] = new_idx as u32; + } + } + Boundaries::Nested(nested_vec) => { + for sub in nested_vec { + sub.update_indices_recursively(violdnew); + } + } + } + } + fn offset_geometry_boundaries(&mut self, offset: usize) { + match self { + Boundaries::Indices(indices) => { + for i in 0..indices.len() { + indices[i] += offset as u32; + } + } + Boundaries::Nested(nested) => { + for sub in nested { + sub.offset_geometry_boundaries(offset); + } + } + } + } +} + +fn parse_boundaries_from_value(v: &Value) -> Boundaries { + match v { + Value::Array(elems) => { + if elems.is_empty() { + return Boundaries::Indices(Vec::new()); + } + match &elems[0] { + Value::Array(_) => { + let mut nested = Vec::with_capacity(elems.len()); + for sub in elems { + nested.push(parse_boundaries_from_value(&sub)); + } + Boundaries::Nested(nested) + } + Value::Number(_) => { + let mut indices = Vec::with_capacity(elems.len()); + for num_val in elems { + if let Some(u) = num_val.as_u64() { + indices.push(u as u32); + } else if let Some(i) = num_val.as_i64() { + indices.push(i as u32); + } + } + Boundaries::Indices(indices) + } + _ => { + return Boundaries::Indices(Vec::new()); + } + } + } + _ => { + return Boundaries::Indices(Vec::new()); + } + } +} + +fn boundaries_to_value(b: &Boundaries) -> Value { + match b { + Boundaries::Indices(indices) => { + let arr = indices + .iter() + .map(|x| Value::Number(Number::from(*x as u64))) + .collect(); + Value::Array(arr) + } + Boundaries::Nested(nested) => { + let arr = nested.iter().map(|x| boundaries_to_value(x)).collect(); + Value::Array(arr) + } + } +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Geometry { #[serde(rename = "type")] pub thetype: GeometryType, #[serde(skip_serializing_if = "Option::is_none")] pub lod: Option, - pub boundaries: Value, + pub boundaries: Boundaries, #[serde(skip_serializing_if = "Option::is_none")] pub semantics: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -524,205 +618,41 @@ pub struct Geometry { } impl Geometry { fn update_geometry_boundaries(&mut self, violdnew: &mut HashMap) { - match self.thetype { - GeometryType::MultiPoint => { - let a: Vec = serde_json::from_value(self.boundaries.clone()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - let kk = violdnew.get(&x); - if kk.is_none() { - let l = violdnew.len(); - violdnew.insert(*x, l); - a2[i] = l; - } else { - let kk = kk.unwrap(); - a2[i] = *kk; - } - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::MultiLineString => { - let a: Vec> = serde_json::from_value(self.boundaries.take()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - for (j, y) in x.iter().enumerate() { - // r.push(z); - let kk = violdnew.get(&y); - if kk.is_none() { - let l = violdnew.len(); - violdnew.insert(*y, l); - a2[i][j] = l; - } else { - let kk = kk.unwrap(); - a2[i][j] = *kk; - } - } + match &mut self.boundaries { + Boundaries::Indices(indices) => { + for index in indices { + let old_idx = *index; + let new_idx = { + let len = violdnew.len(); + *violdnew.entry(old_idx as usize).or_insert_with(|| len) + }; + *index = new_idx as u32; } - self.boundaries = serde_json::to_value(&a2).unwrap(); } - GeometryType::MultiSurface | GeometryType::CompositeSurface => { - let a: Vec>> = - serde_json::from_value(self.boundaries.take()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - for (j, y) in x.iter().enumerate() { - for (k, z) in y.iter().enumerate() { - let kk = violdnew.get(&z); - if kk.is_none() { - let l = violdnew.len(); - violdnew.insert(*z, l); - a2[i][j][k] = l; - } else { - let kk = kk.unwrap(); - a2[i][j][k] = *kk; + Boundaries::Nested(nested) => { + for sub in nested { + match sub { + Boundaries::Indices(r) => { + for index in r { + let old_idx = *index; + let new_idx = { + let len = violdnew.len(); + *violdnew.entry(old_idx as usize).or_insert_with(|| len) + }; + *index = new_idx as u32; } } - } - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::Solid => { - let a: Vec>>> = - serde_json::from_value(self.boundaries.take()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - for (j, y) in x.iter().enumerate() { - for (k, z) in y.iter().enumerate() { - for (l, zz) in z.iter().enumerate() { - let kk = violdnew.get(&zz); - if kk.is_none() { - let l2 = violdnew.len(); - violdnew.insert(*zz, l2); - a2[i][j][k][l] = l2; - } else { - let kk = kk.unwrap(); - a2[i][j][k][l] = *kk; - } - } - } - } - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::MultiSolid | GeometryType::CompositeSolid => { - let a: Vec>>>> = - serde_json::from_value(self.boundaries.take()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - for (j, y) in x.iter().enumerate() { - for (k, z) in y.iter().enumerate() { - for (l, zz) in z.iter().enumerate() { - for (m, zzz) in zz.iter().enumerate() { - let kk = violdnew.get(&zzz); - if kk.is_none() { - let l2 = violdnew.len(); - violdnew.insert(*zzz, l2); - a2[i][j][k][l][m] = l2; - } else { - let kk = kk.unwrap(); - a2[i][j][k][l][m] = *kk; - } - } - } + Boundaries::Nested(_) => { + sub.update_indices_recursively(violdnew); } } } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::GeometryInstance => { - let a: Vec = serde_json::from_value(self.boundaries.clone()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - let kk = violdnew.get(&x); - if kk.is_none() { - let l = violdnew.len(); - violdnew.insert(*x, l); - a2[i] = l; - } else { - let kk = kk.unwrap(); - a2[i] = *kk; - } - } - self.boundaries = serde_json::to_value(&a2).unwrap(); } } } fn offset_geometry_boundaries(&mut self, offset: usize) { - match self.thetype { - GeometryType::MultiPoint => { - let a: Vec = serde_json::from_value(self.boundaries.clone()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - a2[i] = *x + offset; - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::MultiLineString => { - let a: Vec> = serde_json::from_value(self.boundaries.take()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - for (j, y) in x.iter().enumerate() { - // r.push(z); - a2[i][j] = *y + offset; - } - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::MultiSurface | GeometryType::CompositeSurface => { - let a: Vec>> = - serde_json::from_value(self.boundaries.take()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - for (j, y) in x.iter().enumerate() { - for (k, z) in y.iter().enumerate() { - a2[i][j][k] = *z + offset; - } - } - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::Solid => { - let a: Vec>>> = - serde_json::from_value(self.boundaries.take()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - for (j, y) in x.iter().enumerate() { - for (k, z) in y.iter().enumerate() { - for (l, zz) in z.iter().enumerate() { - a2[i][j][k][l] = *zz + offset; - } - } - } - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::MultiSolid | GeometryType::CompositeSolid => { - let a: Vec>>>> = - serde_json::from_value(self.boundaries.take()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - for (j, y) in x.iter().enumerate() { - for (k, z) in y.iter().enumerate() { - for (l, zz) in z.iter().enumerate() { - for (m, zzz) in zz.iter().enumerate() { - a2[i][j][k][l][m] = *zzz + offset; - } - } - } - } - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - GeometryType::GeometryInstance => { - let a: Vec = serde_json::from_value(self.boundaries.clone()).unwrap(); - let mut a2 = a.clone(); - for (i, x) in a.iter().enumerate() { - a2[i] = *x + offset; - } - self.boundaries = serde_json::to_value(&a2).unwrap(); - } - } + self.boundaries.offset_geometry_boundaries(offset); } fn update_material(&mut self, m_oldnew: &mut HashMap) { @@ -1012,15 +942,11 @@ impl ReferenceSystem { pub fn from_url(url: &str) -> Result { let parts: Vec<&str> = url.split("/").collect(); - if parts.len() != 4 { - return Err("Invalid reference system URL"); - } - Ok(ReferenceSystem { - base_url: parts[0].to_string(), - authority: parts[1].to_string(), - version: parts[2].to_string(), - code: parts[3].to_string(), + base_url: parts[..parts.len() - 3].join("/"), + authority: parts[parts.len() - 3].to_string(), + version: parts[parts.len() - 2].to_string(), + code: parts[parts.len() - 1].to_string(), }) } } From 7077028547dac4b4a5c6ca8c46c900caba987f8a Mon Sep 17 00:00:00 2001 From: HideBa Date: Sat, 21 Dec 2024 17:51:08 +0100 Subject: [PATCH 02/19] feat: serialize/deserialize boundaries --- src/lib.rs | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ef12892..4393bdf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -503,7 +503,7 @@ pub enum GeometryType { GeometryInstance, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone)] pub enum Boundaries { Indices(Vec), Nested(Vec), @@ -513,13 +513,13 @@ impl Boundaries { fn update_indices_recursively(&mut self, violdnew: &mut HashMap) { match self { Boundaries::Indices(arr) => { - for i in 0..arr.len() { - let old_idx = arr[i]; + for index in arr { + let old_idx = *index; let new_idx = { let len = violdnew.len(); *violdnew.entry(old_idx as usize).or_insert_with(|| len) }; - arr[i] = new_idx as u32; + *index = new_idx as u32; } } Boundaries::Nested(nested_vec) => { @@ -532,8 +532,8 @@ impl Boundaries { fn offset_geometry_boundaries(&mut self, offset: usize) { match self { Boundaries::Indices(indices) => { - for i in 0..indices.len() { - indices[i] += offset as u32; + for index in indices { + *index += offset as u32; } } Boundaries::Nested(nested) => { @@ -545,6 +545,25 @@ impl Boundaries { } } +impl Serialize for Boundaries { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + boundaries_to_value(self).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Boundaries { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let v = Value::deserialize(deserializer)?; + Ok(parse_boundaries_from_value(&v)) + } +} + fn parse_boundaries_from_value(v: &Value) -> Boundaries { match v { Value::Array(elems) => { @@ -591,7 +610,7 @@ fn boundaries_to_value(b: &Boundaries) -> Value { Value::Array(arr) } Boundaries::Nested(nested) => { - let arr = nested.iter().map(|x| boundaries_to_value(x)).collect(); + let arr = nested.iter().map(boundaries_to_value).collect(); Value::Array(arr) } } From dff1c02813ce3e23fc23dae819f7a93b9ec6b9ce Mon Sep 17 00:00:00 2001 From: HideBa Date: Sat, 21 Dec 2024 17:53:11 +0100 Subject: [PATCH 03/19] fix: change ref's ref to ref --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 4393bdf..085f82d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -574,7 +574,7 @@ fn parse_boundaries_from_value(v: &Value) -> Boundaries { Value::Array(_) => { let mut nested = Vec::with_capacity(elems.len()); for sub in elems { - nested.push(parse_boundaries_from_value(&sub)); + nested.push(parse_boundaries_from_value(sub)); } Boundaries::Nested(nested) } From bf6fca01b1ba2fe6b2c23897398bc4c7fd2b3dea Mon Sep 17 00:00:00 2001 From: HideBa Date: Sat, 21 Dec 2024 17:59:14 +0100 Subject: [PATCH 04/19] feat: add semantics type --- src/lib.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 085f82d..4ee386a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -504,11 +504,14 @@ pub enum GeometryType { } #[derive(Debug, Clone)] -pub enum Boundaries { +pub enum NestedArray { Indices(Vec), - Nested(Vec), + Nested(Vec), } +pub type Boundaries = NestedArray; +pub type Semantics = NestedArray; + impl Boundaries { fn update_indices_recursively(&mut self, violdnew: &mut HashMap) { match self { @@ -545,7 +548,7 @@ impl Boundaries { } } -impl Serialize for Boundaries { +impl Serialize for NestedArray { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -554,7 +557,7 @@ impl Serialize for Boundaries { } } -impl<'de> Deserialize<'de> for Boundaries { +impl<'de> Deserialize<'de> for NestedArray { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -564,11 +567,11 @@ impl<'de> Deserialize<'de> for Boundaries { } } -fn parse_boundaries_from_value(v: &Value) -> Boundaries { +fn parse_boundaries_from_value(v: &Value) -> NestedArray { match v { Value::Array(elems) => { if elems.is_empty() { - return Boundaries::Indices(Vec::new()); + return NestedArray::Indices(Vec::new()); } match &elems[0] { Value::Array(_) => { @@ -576,7 +579,7 @@ fn parse_boundaries_from_value(v: &Value) -> Boundaries { for sub in elems { nested.push(parse_boundaries_from_value(sub)); } - Boundaries::Nested(nested) + NestedArray::Nested(nested) } Value::Number(_) => { let mut indices = Vec::with_capacity(elems.len()); @@ -587,29 +590,29 @@ fn parse_boundaries_from_value(v: &Value) -> Boundaries { indices.push(i as u32); } } - Boundaries::Indices(indices) + NestedArray::Indices(indices) } _ => { - return Boundaries::Indices(Vec::new()); + return NestedArray::Indices(Vec::new()); } } } _ => { - return Boundaries::Indices(Vec::new()); + return NestedArray::Indices(Vec::new()); } } } -fn boundaries_to_value(b: &Boundaries) -> Value { +fn boundaries_to_value(b: &NestedArray) -> Value { match b { - Boundaries::Indices(indices) => { + NestedArray::Indices(indices) => { let arr = indices .iter() .map(|x| Value::Number(Number::from(*x as u64))) .collect(); Value::Array(arr) } - Boundaries::Nested(nested) => { + NestedArray::Nested(nested) => { let arr = nested.iter().map(boundaries_to_value).collect(); Value::Array(arr) } @@ -624,7 +627,7 @@ pub struct Geometry { pub lod: Option, pub boundaries: Boundaries, #[serde(skip_serializing_if = "Option::is_none")] - pub semantics: Option, + pub semantics: Option, #[serde(skip_serializing_if = "Option::is_none")] pub material: Option>, #[serde(skip_serializing_if = "Option::is_none")] From 7db2949b44cc34df0d2f289530bf5eb7f8003cd9 Mon Sep 17 00:00:00 2001 From: HideBa Date: Sun, 22 Dec 2024 11:08:06 +0100 Subject: [PATCH 05/19] fix: serde of semantics of geometric primitives --- src/lib.rs | 97 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4ee386a..828b86e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -509,45 +509,6 @@ pub enum NestedArray { Nested(Vec), } -pub type Boundaries = NestedArray; -pub type Semantics = NestedArray; - -impl Boundaries { - fn update_indices_recursively(&mut self, violdnew: &mut HashMap) { - match self { - Boundaries::Indices(arr) => { - for index in arr { - let old_idx = *index; - let new_idx = { - let len = violdnew.len(); - *violdnew.entry(old_idx as usize).or_insert_with(|| len) - }; - *index = new_idx as u32; - } - } - Boundaries::Nested(nested_vec) => { - for sub in nested_vec { - sub.update_indices_recursively(violdnew); - } - } - } - } - fn offset_geometry_boundaries(&mut self, offset: usize) { - match self { - Boundaries::Indices(indices) => { - for index in indices { - *index += offset as u32; - } - } - Boundaries::Nested(nested) => { - for sub in nested { - sub.offset_geometry_boundaries(offset); - } - } - } - } -} - impl Serialize for NestedArray { fn serialize(&self, serializer: S) -> Result where @@ -619,6 +580,64 @@ fn boundaries_to_value(b: &NestedArray) -> Value { } } +pub type Boundaries = NestedArray; + +impl Boundaries { + fn update_indices_recursively(&mut self, violdnew: &mut HashMap) { + match self { + Boundaries::Indices(arr) => { + for index in arr { + let old_idx = *index; + let new_idx = { + let len = violdnew.len(); + *violdnew.entry(old_idx as usize).or_insert_with(|| len) + }; + *index = new_idx as u32; + } + } + Boundaries::Nested(nested_vec) => { + for sub in nested_vec { + sub.update_indices_recursively(violdnew); + } + } + } + } + fn offset_geometry_boundaries(&mut self, offset: usize) { + match self { + Boundaries::Indices(indices) => { + for index in indices { + *index += offset as u32; + } + } + Boundaries::Nested(nested) => { + for sub in nested { + sub.offset_geometry_boundaries(offset); + } + } + } + } +} + +type SemanticsValues = NestedArray; + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct SemanticsSurface { + #[serde(rename = "type")] + thetype: String, + #[serde(skip_serializing_if = "Option::is_none")] + parent: Option, + #[serde(skip_serializing_if = "Option::is_none")] + children: Option>, + #[serde(flatten)] + other: serde_json::Value, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Semantics { + values: SemanticsValues, + surface: SemanticsSurface, +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Geometry { #[serde(rename = "type")] From 36a4aec8b4144264feb02057978f409bb94dbf5b Mon Sep 17 00:00:00 2001 From: HideBa Date: Sun, 22 Dec 2024 11:29:40 +0100 Subject: [PATCH 06/19] chore: make sematics field public --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 44ffbff..aa7887e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -618,10 +618,10 @@ impl Boundaries { } } -type SemanticsValues = NestedArray; +pub type SemanticsValues = NestedArray; #[derive(Debug, Clone, Serialize, Deserialize)] -struct SemanticsSurface { +pub struct SemanticsSurface { #[serde(rename = "type")] thetype: String, #[serde(skip_serializing_if = "Option::is_none")] @@ -634,8 +634,8 @@ struct SemanticsSurface { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Semantics { - values: SemanticsValues, - surface: SemanticsSurface, + pub values: SemanticsValues, + pub surface: SemanticsSurface, } #[derive(Serialize, Deserialize, Debug, Clone)] From d37b6842a627ce9bad4676729d2f72eee74777f2 Mon Sep 17 00:00:00 2001 From: HideBa Date: Sun, 22 Dec 2024 16:31:45 +0100 Subject: [PATCH 07/19] fix: semantics --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index aa7887e..034e697 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -635,7 +635,7 @@ pub struct SemanticsSurface { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Semantics { pub values: SemanticsValues, - pub surface: SemanticsSurface, + pub surface: Vec, } #[derive(Serialize, Deserialize, Debug, Clone)] From c9f1628e3709bad1926cdb67ac491d931b68bcc0 Mon Sep 17 00:00:00 2001 From: HideBa Date: Sun, 22 Dec 2024 16:55:24 +0100 Subject: [PATCH 08/19] fix: typo of semantics --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 034e697..f2529e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -635,7 +635,7 @@ pub struct SemanticsSurface { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Semantics { pub values: SemanticsValues, - pub surface: Vec, + pub surfaces: Vec, } #[derive(Serialize, Deserialize, Debug, Clone)] From 5eaf8f57cf42bc9dd512f847e14edac678852b20 Mon Sep 17 00:00:00 2001 From: HideBa Date: Sun, 22 Dec 2024 19:57:52 +0100 Subject: [PATCH 09/19] fix: change fileds of `SemanticsSurface` to public --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f2529e7..ace5f09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -623,13 +623,13 @@ pub type SemanticsValues = NestedArray; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SemanticsSurface { #[serde(rename = "type")] - thetype: String, + pub thetype: String, #[serde(skip_serializing_if = "Option::is_none")] - parent: Option, + pub parent: Option, #[serde(skip_serializing_if = "Option::is_none")] - children: Option>, + pub children: Option>, #[serde(flatten)] - other: serde_json::Value, + pub other: serde_json::Value, } #[derive(Serialize, Deserialize, Debug, Clone)] From 7f25bf6e3daaeb3cdc93edc90e21079f05048537 Mon Sep 17 00:00:00 2001 From: HideBa Date: Mon, 23 Dec 2024 14:23:38 +0100 Subject: [PATCH 10/19] feat: made Vertex public --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ace5f09..09ffbc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -888,10 +888,10 @@ impl Geometry { } #[derive(Serialize, Deserialize, Debug)] -struct Vertex { - x: i64, - y: i64, - z: i64, +pub struct Vertex { + pub x: i64, + pub y: i64, + pub z: i64, } #[derive(Serialize, Deserialize, Debug, Clone)] From fb4a84a87ff2670497ee13843f284149be5ba954 Mon Sep 17 00:00:00 2001 From: HideBa Date: Mon, 23 Dec 2024 14:25:41 +0100 Subject: [PATCH 11/19] chore: remove unused vertex struct --- src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 09ffbc3..61c3efd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -887,13 +887,6 @@ impl Geometry { } } -#[derive(Serialize, Deserialize, Debug)] -pub struct Vertex { - pub x: i64, - pub y: i64, - pub z: i64, -} - #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Transform { pub scale: Vec, From b507c5c8c7c7986ace11acbcd36343bdd0678e87 Mon Sep 17 00:00:00 2001 From: HideBa Date: Sat, 28 Dec 2024 21:25:53 +0100 Subject: [PATCH 12/19] feat: add new function on cityobject --- src/lib.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 61c3efd..d0ed6b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -462,6 +462,25 @@ pub struct CityObject { } impl CityObject { + pub fn new( + thetype: String, + geographical_extent: Option>, + attributes: Option, + geometry: Option>, + children: Option>, + parents: Option>, + other: Option, + ) -> Self { + CityObject { + thetype, + geographical_extent, + attributes, + geometry, + children, + parents, + other: other.unwrap_or(Value::Null), + } + } pub fn get_type(&self) -> String { self.thetype.clone() } From 7ed511650bda2360d49463c355ed4bf960aa6a38 Mon Sep 17 00:00:00 2001 From: HideBa Date: Wed, 1 Jan 2025 15:29:36 +0100 Subject: [PATCH 13/19] feat: add Eq and PartialEq trait on NestedArray --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d0ed6b3..b1268a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -522,7 +522,7 @@ pub enum GeometryType { GeometryInstance, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum NestedArray { Indices(Vec), Nested(Vec), From 3703cfcb910e4d7cb09e52252f81eb1e8ca7dbab Mon Sep 17 00:00:00 2001 From: HideBa Date: Wed, 1 Jan 2025 21:57:46 +0100 Subject: [PATCH 14/19] feat: add unit test for boundaries serde --- src/lib.rs | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index b1268a0..9c1c65d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1149,3 +1149,157 @@ impl Appearance { }; } } + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + /// Test cases derived from CityJSON specification v2.0.1 + /// See: https://www.cityjson.org/specs/2.0.1/#semantics-of-geometric-primitives + + /// MultiPoint: Single array of vertex indices + /// [v1, v2, v3, ...] + #[test] + fn test_multipoint_boundaries() { + let json_value = json!([2, 44, 0, 7]); + let boundaries = parse_boundaries_from_value(&json_value); + assert_eq!(boundaries, NestedArray::Indices(vec![2, 44, 0, 7])); + } + + /// MultiLineString: Array of arrays, each inner array represents a linestring + /// [[v1, v2, v3, ...], [v1, v2, v3, ...], ...] + #[test] + fn test_multilinestring_boundaries() { + let json_value = json!([[2, 3, 5], [77, 55, 212]]); + let boundaries = parse_boundaries_from_value(&json_value); + assert_eq!( + boundaries, + NestedArray::Nested(vec![ + NestedArray::Indices(vec![2, 3, 5]), + NestedArray::Indices(vec![77, 55, 212]), + ]) + ); + } + + /// MultiSurface: Array of surfaces, each surface is an array of rings, each ring is an array of vertex indices + /// [[[v1, v2, v3, ...]], [[v1, v2, v3, ...]], ...] + /// The innermost array represents a ring (exterior or interior) + #[test] + fn test_multisurface_boundaries() { + let json_value = json!([[[0, 3, 2, 1]], [[4, 5, 6, 7]], [[0, 1, 5, 4]]]); + let boundaries = parse_boundaries_from_value(&json_value); + assert_eq!( + boundaries, + NestedArray::Nested(vec![ + NestedArray::Nested(vec![NestedArray::Indices(vec![0, 3, 2, 1])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![4, 5, 6, 7])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![0, 1, 5, 4])]), + ]) + ); + } + + /// Solid: Array of shells (exterior + optional interior), each shell is an array of surfaces + /// Each surface is an array of rings, each ring is an array of vertex indices + /// [ + /// [[[v1, v2, ...]], [[v1, v2, ...]], ...], // exterior shell + /// [[[v1, v2, ...]], [[v1, v2, ...]], ...] // interior shell + /// ] + #[test] + fn test_solid_boundaries() { + let json_value = json!([ + [ + [[0, 3, 2, 1, 22]], + [[4, 5, 6, 7]], + [[0, 1, 5, 4]], + [[1, 2, 6, 5]] + ], + [ + [[240, 243, 124]], + [[244, 246, 724]], + [[34, 414, 45]], + [[111, 246, 5]] + ] + ]); + let boundaries = parse_boundaries_from_value(&json_value); + assert_eq!( + boundaries, + NestedArray::Nested(vec![ + NestedArray::Nested(vec![ + NestedArray::Nested(vec![NestedArray::Indices(vec![0, 3, 2, 1, 22])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![4, 5, 6, 7])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![0, 1, 5, 4])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![1, 2, 6, 5])]), + ]), + NestedArray::Nested(vec![ + NestedArray::Nested(vec![NestedArray::Indices(vec![240, 243, 124])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![244, 246, 724])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![34, 414, 45])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![111, 246, 5])]), + ]), + ]) + ); + } + + /// CompositeSolid: Array of solids, each solid follows the Solid structure above + /// [ + /// [ // First solid + /// [[[v1, v2, ...]], [[v1, v2, ...]], ...], // exterior shell + /// [[[v1, v2, ...]], [[v1, v2, ...]], ...] // interior shell + /// ], + /// [ // Second solid + /// [[[v1, v2, ...]], [[v1, v2, ...]], ...] // only exterior shell + /// ] + /// ] + #[test] + fn test_composite_solid_boundaries() { + let json_value = json!([ + [ + [ + [[0, 3, 2, 1, 22]], + [[4, 5, 6, 7]], + [[0, 1, 5, 4]], + [[1, 2, 6, 5]] + ], + [ + [[240, 243, 124]], + [[244, 246, 724]], + [[34, 414, 45]], + [[111, 246, 5]] + ] + ], + [[ + [[666, 667, 668]], + [[74, 75, 76]], + [[880, 881, 885]], + [[111, 122, 226]] + ]] + ]); + let boundaries = parse_boundaries_from_value(&json_value); + assert_eq!( + boundaries, + NestedArray::Nested(vec![ + NestedArray::Nested(vec![ + NestedArray::Nested(vec![ + NestedArray::Nested(vec![NestedArray::Indices(vec![0, 3, 2, 1, 22])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![4, 5, 6, 7])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![0, 1, 5, 4])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![1, 2, 6, 5])]), + ]), + NestedArray::Nested(vec![ + NestedArray::Nested(vec![NestedArray::Indices(vec![240, 243, 124])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![244, 246, 724])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![34, 414, 45])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![111, 246, 5])]), + ]), + ]), + NestedArray::Nested(vec![NestedArray::Nested(vec![ + NestedArray::Nested(vec![NestedArray::Indices(vec![666, 667, 668])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![74, 75, 76])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![880, 881, 885])]), + NestedArray::Nested(vec![NestedArray::Indices(vec![111, 122, 226])]), + ]),]), + ]) + ); + } +} From 6917631947c9cb808ddc629c047d6069a825262d Mon Sep 17 00:00:00 2001 From: HideBa Date: Thu, 2 Jan 2025 13:42:16 +0100 Subject: [PATCH 15/19] feat: add Eq and PartialEq to SemanticSurface --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9c1c65d..d05e00d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -639,7 +639,7 @@ impl Boundaries { pub type SemanticsValues = NestedArray; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct SemanticsSurface { #[serde(rename = "type")] pub thetype: String, @@ -651,7 +651,7 @@ pub struct SemanticsSurface { pub other: serde_json::Value, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct Semantics { pub values: SemanticsValues, pub surfaces: Vec, From e460778eebb26ee1a2dfa05f5d0387513abeb0b3 Mon Sep 17 00:00:00 2001 From: HideBa Date: Thu, 2 Jan 2025 14:40:56 +0100 Subject: [PATCH 16/19] feat: enhance JSON serialization/deserialization for NestedArray --- src/lib.rs | 170 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 119 insertions(+), 51 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d05e00d..33b40e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_json::{json, Error, Number, Value}; use std::collections::HashMap; @@ -522,85 +522,155 @@ pub enum GeometryType { GeometryInstance, } +pub trait JsonIndex: Clone + PartialEq + Eq + std::fmt::Debug { + /// Attempt to parse a `T` from the given `Value`. + /// Return `None` if parsing fails or if you want to skip certain cases. + fn from_value(v: &Value) -> Option; + + /// Convert a `T` into a JSON `Value`. + fn to_value(&self) -> Value; +} + +/// Implement `JsonIndex` for a plain `u32`. +/// - `null` is ignored (returns `None`). +/// - Numeric values are cast to `u32` (watch out for possible negative or large values). +impl JsonIndex for u32 { + fn from_value(v: &Value) -> Option { + if let Some(u) = v.as_u64() { + Some(u as u32) + } else if let Some(i) = v.as_i64() { + // You may want to check if `i` is negative, or out of u32 range. + Some(i as u32) + } else { + None + } + } + + fn to_value(&self) -> Value { + Value::Number(Number::from(*self as u64)) + } +} + +/// Implement `JsonIndex` for an `Option`. +/// - `null` becomes `None`. +/// - Numeric values become `Some(...)`. +impl JsonIndex for Option { + fn from_value(v: &Value) -> Option { + if v.is_null() { + // JSON null -> None + Some(None) + } else if let Some(u) = v.as_u64() { + Some(Some(u as u32)) + } else if let Some(i) = v.as_i64() { + Some(Some(i as u32)) + } else { + None + } + } + + fn to_value(&self) -> Value { + match self { + Some(x) => Value::Number(Number::from(*x as u64)), + None => Value::Null, + } + } +} + +/// Our nested structure, generic over `T`. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum NestedArray { - Indices(Vec), - Nested(Vec), +pub enum NestedArray { + Indices(Vec), + Nested(Vec>), } -impl Serialize for NestedArray { +/// For convenience, define `Boundaries` as `NestedArray` (no null allowed). +pub type Boundaries = NestedArray; +/// For Semantics, define `SemanticsValues` as `NestedArray>` (null allowed). +pub type SemanticsValues = NestedArray>; + +// --------------------------------------------------------------------------- +// Custom Serialize/Deserialize for `NestedArray` +// where `T: JsonIndex` defines how to go from/to JSON numbers or null. +// --------------------------------------------------------------------------- +impl Serialize for NestedArray +where + T: JsonIndex, +{ fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer, + S: Serializer, { - boundaries_to_value(self).serialize(serializer) + nested_array_to_value(self).serialize(serializer) } } -impl<'de> Deserialize<'de> for NestedArray { +impl<'de, T> Deserialize<'de> for NestedArray +where + T: JsonIndex, +{ fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: Deserializer<'de>, { let v = Value::deserialize(deserializer)?; - Ok(parse_boundaries_from_value(&v)) + Ok(parse_nested_array(&v)) } } -fn parse_boundaries_from_value(v: &Value) -> NestedArray { +// --------------------------------------------------------------------------- +// Parsing from `serde_json::Value` into a `NestedArray` +// --------------------------------------------------------------------------- +fn parse_nested_array(v: &Value) -> NestedArray { match v { Value::Array(elems) => { if elems.is_empty() { return NestedArray::Indices(Vec::new()); } - match &elems[0] { - Value::Array(_) => { - let mut nested = Vec::with_capacity(elems.len()); - for sub in elems { - nested.push(parse_boundaries_from_value(sub)); - } - NestedArray::Nested(nested) + // If the first element is itself an Array, assume it's "Nested" + if let Value::Array(_) = &elems[0] { + let mut nested = Vec::with_capacity(elems.len()); + for sub in elems { + nested.push(parse_nested_array(sub)); } - Value::Number(_) => { - let mut indices = Vec::with_capacity(elems.len()); - for num_val in elems { - if let Some(u) = num_val.as_u64() { - indices.push(u as u32); - } else if let Some(i) = num_val.as_i64() { - indices.push(i as u32); - } + NestedArray::Nested(nested) + } else { + // Indices: parse each element via `T::from_value()` + let mut indices = Vec::with_capacity(elems.len()); + for elem in elems { + if let Some(val) = T::from_value(elem) { + indices.push(val); + } else { + // If we can't parse, you could choose to skip or push a default. + // Here we skip. } - NestedArray::Indices(indices) - } - _ => { - return NestedArray::Indices(Vec::new()); } + NestedArray::Indices(indices) } } - _ => { - return NestedArray::Indices(Vec::new()); - } + // Not an array? Return an empty Indices array by default + _ => NestedArray::Indices(Vec::new()), } } -fn boundaries_to_value(b: &NestedArray) -> Value { - match b { - NestedArray::Indices(indices) => { - let arr = indices - .iter() - .map(|x| Value::Number(Number::from(*x as u64))) - .collect(); +// --------------------------------------------------------------------------- +// Converting a `NestedArray` to `serde_json::Value` +// --------------------------------------------------------------------------- +fn nested_array_to_value(na: &NestedArray) -> Value { + match na { + NestedArray::Indices(vec_of_t) => { + let arr = vec_of_t.iter().map(|t| t.to_value()).collect(); Value::Array(arr) } - NestedArray::Nested(nested) => { - let arr = nested.iter().map(boundaries_to_value).collect(); + NestedArray::Nested(vec_of_nested) => { + let arr = vec_of_nested + .iter() + .map(|sub_na| nested_array_to_value(sub_na)) + .collect(); Value::Array(arr) } } } -pub type Boundaries = NestedArray; - impl Boundaries { fn update_indices_recursively(&mut self, violdnew: &mut HashMap) { match self { @@ -637,8 +707,6 @@ impl Boundaries { } } -pub type SemanticsValues = NestedArray; - #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct SemanticsSurface { #[serde(rename = "type")] @@ -1163,7 +1231,7 @@ mod tests { #[test] fn test_multipoint_boundaries() { let json_value = json!([2, 44, 0, 7]); - let boundaries = parse_boundaries_from_value(&json_value); + let boundaries = parse_nested_array(&json_value); assert_eq!(boundaries, NestedArray::Indices(vec![2, 44, 0, 7])); } @@ -1172,7 +1240,7 @@ mod tests { #[test] fn test_multilinestring_boundaries() { let json_value = json!([[2, 3, 5], [77, 55, 212]]); - let boundaries = parse_boundaries_from_value(&json_value); + let boundaries = parse_nested_array(&json_value); assert_eq!( boundaries, NestedArray::Nested(vec![ @@ -1188,7 +1256,7 @@ mod tests { #[test] fn test_multisurface_boundaries() { let json_value = json!([[[0, 3, 2, 1]], [[4, 5, 6, 7]], [[0, 1, 5, 4]]]); - let boundaries = parse_boundaries_from_value(&json_value); + let boundaries = parse_nested_array(&json_value); assert_eq!( boundaries, NestedArray::Nested(vec![ @@ -1221,7 +1289,7 @@ mod tests { [[111, 246, 5]] ] ]); - let boundaries = parse_boundaries_from_value(&json_value); + let boundaries = parse_nested_array(&json_value); assert_eq!( boundaries, NestedArray::Nested(vec![ @@ -1275,7 +1343,7 @@ mod tests { [[111, 122, 226]] ]] ]); - let boundaries = parse_boundaries_from_value(&json_value); + let boundaries = parse_nested_array(&json_value); assert_eq!( boundaries, NestedArray::Nested(vec![ From 6a844e3a42796e9e328800d2c036fe10add5da2f Mon Sep 17 00:00:00 2001 From: HideBa Date: Fri, 3 Jan 2025 11:29:09 +0100 Subject: [PATCH 17/19] feat: add PartialEq to structs --- src/lib.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 33b40e6..de19e75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ pub enum SortingStrategy { Hilbert, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CityJSON { #[serde(rename = "type")] pub thetype: String, @@ -398,7 +398,7 @@ impl CityJSON { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CityJSONFeature { #[serde(rename = "type")] pub thetype: String, @@ -442,7 +442,7 @@ impl CityJSONFeature { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CityObject { #[serde(rename = "type")] pub thetype: String, @@ -725,7 +725,7 @@ pub struct Semantics { pub surfaces: Vec, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Geometry { #[serde(rename = "type")] pub thetype: GeometryType, @@ -974,7 +974,7 @@ impl Geometry { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Transform { pub scale: Vec, pub translate: Vec, @@ -990,7 +990,7 @@ impl Transform { pub type GeographicalExtent = [f64; 6]; -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Address { #[serde(rename = "thoroughfareNumber")] pub thoroughfare_number: i64, @@ -1002,7 +1002,7 @@ pub struct Address { pub country: String, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct PointOfContact { #[serde(rename = "contactName")] pub contact_name: String, @@ -1031,7 +1031,7 @@ pub struct PointOfContact { /// - `{version}` designates the specific version of the CRS /// (use "0" if there is no version) /// - `{code}` is the identifier for the specific coordinate reference system -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct ReferenceSystem { pub base_url: String, pub authority: String, @@ -1101,7 +1101,7 @@ impl<'de> Deserialize<'de> for ReferenceSystem { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Metadata { #[serde(rename = "geographicalExtent")] #[serde(skip_serializing_if = "Option::is_none")] @@ -1121,14 +1121,14 @@ pub struct Metadata { pub title: Option, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct GeometryTemplates { pub templates: Vec, #[serde(rename = "vertices-templates")] pub vertices_templates: Value, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Material { #[serde(skip_serializing_if = "Option::is_none")] pub values: Option, @@ -1136,13 +1136,13 @@ pub struct Material { pub value: Option, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Texture { #[serde(skip_serializing_if = "Option::is_none")] pub values: Option, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Appearance { #[serde(skip_serializing_if = "Option::is_none")] pub materials: Option>, From 828c7c77b0665c751413e4dbf8cd7391be69492c Mon Sep 17 00:00:00 2001 From: HideBa Date: Wed, 8 Jan 2025 18:50:59 +0100 Subject: [PATCH 18/19] feat: add children_roles as field --- src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index de19e75..92daf59 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -456,6 +456,8 @@ pub struct CityObject { #[serde(skip_serializing_if = "Option::is_none")] pub children: Option>, #[serde(skip_serializing_if = "Option::is_none")] + pub children_roles: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub parents: Option>, #[serde(flatten)] other: serde_json::Value, @@ -468,6 +470,7 @@ impl CityObject { attributes: Option, geometry: Option>, children: Option>, + children_roles: Option>, parents: Option>, other: Option, ) -> Self { @@ -477,6 +480,7 @@ impl CityObject { attributes, geometry, children, + children_roles, parents, other: other.unwrap_or(Value::Null), } From 8f7fbaf330b08c7bf6c54e10a700e026663723cc Mon Sep 17 00:00:00 2001 From: HideBa Date: Sun, 12 Jan 2025 15:17:08 +0100 Subject: [PATCH 19/19] refactor: change geographicalExtent to fixed length --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 92daf59..3cada2f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -448,7 +448,7 @@ pub struct CityObject { pub thetype: String, #[serde(rename = "geographicalExtent")] #[serde(skip_serializing_if = "Option::is_none")] - pub geographical_extent: Option>, + pub geographical_extent: Option, #[serde(skip_serializing_if = "Option::is_none")] pub attributes: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -466,7 +466,7 @@ pub struct CityObject { impl CityObject { pub fn new( thetype: String, - geographical_extent: Option>, + geographical_extent: Option, attributes: Option, geometry: Option>, children: Option>,