Skip to main content

ecitygml_io/gml/
write.rs

1use crate::Error::InvalidFileExtension;
2use crate::gml::write_impl::serialize;
3use crate::{CitygmlFormat, Error};
4use ecitygml_core::model::core::CityModel;
5use egml::io::util::Formatting;
6use std::fs::{File, OpenOptions};
7use std::io::{BufWriter, Write};
8use std::path::Path;
9
10/// `GmlWriter` writes CityGML datasets.
11///
12#[derive(Debug, Clone)]
13pub struct GmlWriter<W: Write> {
14    writer: W,
15    format: CitygmlFormat,
16    formatting: Formatting,
17}
18
19impl<W: Write> GmlWriter<W> {
20    pub fn new(writer: W, format: CitygmlFormat) -> Self {
21        Self {
22            writer,
23            format,
24            formatting: Formatting::default(),
25        }
26    }
27
28    pub fn with_formatting(mut self, formatting: Formatting) -> Self {
29        self.formatting = formatting;
30        self
31    }
32
33    pub fn finish(self, city_model: CityModel) -> Result<(), Error> {
34        match self.format {
35            CitygmlFormat::Gml => {
36                let mut w = BufWriter::new(self.writer);
37                serialize(&mut w, city_model, self.formatting)?;
38            }
39            CitygmlFormat::GmlZst => {
40                let mut encoder = zstd::Encoder::new(BufWriter::new(self.writer), 9)?;
41                serialize(&mut encoder, city_model, self.formatting)?;
42                encoder.finish()?;
43            }
44            CitygmlFormat::GmlGz => {
45                let mut encoder = flate2::write::GzEncoder::new(
46                    BufWriter::new(self.writer),
47                    flate2::Compression::default(),
48                );
49                serialize(&mut encoder, city_model, self.formatting)?;
50                encoder.finish()?;
51            }
52        }
53
54        Ok(())
55    }
56}
57
58impl GmlWriter<File> {
59    pub fn from_path(path: impl AsRef<Path>) -> Result<Self, Error> {
60        let format = CitygmlFormat::from_path(path.as_ref()).ok_or_else(|| {
61            InvalidFileExtension(
62                path.as_ref()
63                    .extension()
64                    .and_then(|ext| ext.to_str())
65                    .unwrap_or_default()
66                    .to_string(),
67            )
68        })?;
69
70        let file = OpenOptions::new()
71            .create(true)
72            .write(true)
73            .truncate(true)
74            .open(path)?;
75        Ok(Self::new(file, format))
76    }
77
78    pub fn from_base_path_with_format(
79        base_path: impl AsRef<Path>,
80        format: CitygmlFormat,
81    ) -> Result<Self, Error> {
82        let mut path = base_path.as_ref().as_os_str().to_os_string();
83        path.push(".");
84        path.push(format.extension());
85
86        let file = OpenOptions::new()
87            .create(true)
88            .write(true)
89            .truncate(true)
90            .open(path)?;
91        Ok(Self::new(file, format))
92    }
93}