Skip to main content

fcb_core/writer/
feature_writer.rs

1use cjseq::CityJSONFeature;
2
3use crate::serializer::*;
4
5use super::attribute::{cityfeature_to_index_entries, AttributeIndexEntry, AttributeSchema};
6
7use crate::packed_rtree::NodeItem;
8
9/// A writer that converts CityJSON features to FlatBuffers format
10///
11/// This struct handles the serialization of CityJSON features into a binary
12/// FlatBuffers representation, which is more efficient for storage and transmission.
13pub struct FeatureWriter<'a> {
14    /// The CityJSON feature to be serialized
15    city_feature: &'a CityJSONFeature,
16    /// The FlatBuffers builder instance used for serialization
17    fbb: flatbuffers::FlatBufferBuilder<'a>,
18    /// The attribute schema to be used for serialization
19    attr_schema: AttributeSchema,
20
21    semantic_attr_schema: Option<AttributeSchema>,
22    pub(super) bbox: NodeItem,
23
24    attr_indices: Option<Vec<String>>,
25
26    pub(super) attribute_feature_offsets: AttributeFeatureOffset,
27}
28
29#[derive(Clone, PartialEq, Debug)]
30pub(super) struct AttributeFeatureOffset {
31    pub(super) offset: usize,
32    pub(super) size: usize,
33    pub(super) index_entries: Vec<AttributeIndexEntry>,
34}
35
36impl<'a> FeatureWriter<'a> {
37    /// Creates a new `FeatureWriter` instance
38    ///
39    /// # Arguments
40    ///
41    /// * `city_feature` - A reference to the CityJSON feature to be serialized
42    pub fn new(
43        city_feature: &'a CityJSONFeature,
44        attr_schema: AttributeSchema,
45        semantic_attr_schema: Option<AttributeSchema>,
46        attr_indices: Option<Vec<String>>,
47    ) -> FeatureWriter<'a> {
48        FeatureWriter {
49            city_feature,
50            fbb: flatbuffers::FlatBufferBuilder::new(),
51            attr_schema,
52            semantic_attr_schema,
53            bbox: NodeItem::create(0),
54            attr_indices,
55            attribute_feature_offsets: AttributeFeatureOffset {
56                offset: 0,
57                size: 0,
58                index_entries: Vec::new(),
59            },
60        }
61    }
62
63    /// Serializes the current feature to a FlatBuffers binary format
64    ///
65    /// This method converts the CityJSON feature into a FlatBuffers representation,
66    /// including all city objects and vertices. The resulting buffer is size-prefixed.
67    ///
68    /// # Returns
69    ///
70    /// A vector of bytes containing the serialized feature
71    pub fn finish_to_feature(&mut self) -> Vec<u8> {
72        self.reset_bbox();
73        self.reset_attribute_feature_offsets();
74        self.extract_indexable_attributes();
75        let (cf_buf, bbox) = to_fcb_city_feature(
76            &mut self.fbb,
77            self.city_feature.id.as_str(),
78            self.city_feature,
79            &self.attr_schema,
80            self.semantic_attr_schema.as_ref(),
81        );
82        self.bbox = bbox;
83        self.fbb.finish_size_prefixed(cf_buf, None);
84        let buf = self.fbb.finished_data().to_vec();
85        self.fbb.reset();
86        buf
87    }
88
89    /// Updates the writer with a new feature to be serialized
90    ///
91    /// # Arguments
92    ///
93    /// * `feature` - A reference to the new CityJSON feature
94    pub fn add_feature(&mut self, feature: &'a CityJSONFeature) {
95        self.city_feature = feature;
96    }
97
98    fn extract_indexable_attributes(&mut self) {
99        if let Some(attr_indices) = &self.attr_indices {
100            let index_entries =
101                cityfeature_to_index_entries(self.city_feature, &self.attr_schema, attr_indices);
102            self.attribute_feature_offsets.index_entries = index_entries;
103        }
104    }
105
106    fn reset_bbox(&mut self) {
107        self.bbox = NodeItem::create(0);
108    }
109
110    fn reset_attribute_feature_offsets(&mut self) {
111        self.attribute_feature_offsets.index_entries.clear();
112        self.attribute_feature_offsets.offset = 0;
113        self.attribute_feature_offsets.size = 0;
114    }
115}