1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Well-Known Text (WKT) conversions.
//!
//! OpenGIS Simple Features Specification For SQL Revision 1.1, Chapter 3.2.5
pub(crate) mod wkt_reader;
pub(crate) mod wkt_writer;

pub use wkt_reader::*;
pub use wkt_writer::*;

pub(crate) mod conversion {
    use crate::error::Result;
    use crate::wkt::{WktDialect, WktWriter};
    use crate::{CoordDimensions, GeozeroGeometry};

    /// Convert to WKT.
    pub trait ToWkt {
        /// Convert to 2D WKT String.
        fn to_wkt(&self) -> Result<String>;
        /// Convert to EWKT String.
        fn to_ewkt(&self, srid: Option<i32>) -> Result<String>;
        /// Convert to WKT String with dimensions.
        fn to_wkt_ndim(&self, dims: CoordDimensions) -> Result<String>;
        /// Convert to WKT String with srid, dimensions and dialect.
        fn to_wkt_with_opts(
            &self,
            dialect: WktDialect,
            dims: CoordDimensions,
            srid: Option<i32>,
        ) -> Result<String>;
    }

    impl<T: GeozeroGeometry> ToWkt for T {
        fn to_wkt(&self) -> Result<String> {
            self.to_wkt_with_opts(WktDialect::Wkt, CoordDimensions::default(), None)
        }

        fn to_ewkt(&self, srid: Option<i32>) -> Result<String> {
            self.to_wkt_with_opts(WktDialect::Ewkt, CoordDimensions::xyzm(), srid)
        }

        fn to_wkt_ndim(&self, dims: CoordDimensions) -> Result<String> {
            self.to_wkt_with_opts(WktDialect::Wkt, dims, None)
        }

        fn to_wkt_with_opts(
            &self,
            dialect: WktDialect,
            dims: CoordDimensions,
            srid: Option<i32>,
        ) -> Result<String> {
            let mut out: Vec<u8> = Vec::new();
            let mut writer = WktWriter::with_opts(&mut out, dialect, dims, srid);
            self.process_geom(&mut writer)?;
            String::from_utf8(out).map_err(|_| {
                crate::error::GeozeroError::Geometry("Invalid UTF-8 encoding".to_string())
            })
        }
    }
}

#[cfg(feature = "with-wkb")]
mod wkb {
    use crate::error::Result;
    use crate::wkb::{FromWkb, WkbDialect};
    #[allow(deprecated)]
    use crate::wkt::{Ewkt, EwktString, Wkt, WktDialect, WktString, WktWriter};
    use crate::CoordDimensions;
    use std::io::Read;

    impl FromWkb for Wkt<String> {
        fn from_wkb<R: Read>(rdr: &mut R, dialect: WkbDialect) -> Result<Self> {
            let mut out: Vec<u8> = Vec::new();
            let mut writer = WktWriter::new(&mut out);
            crate::wkb::process_wkb_type_geom(rdr, &mut writer, dialect)?;
            let wkt = String::from_utf8(out).map_err(|_| {
                crate::error::GeozeroError::Geometry("Invalid UTF-8 encoding".to_string())
            })?;
            Ok(Wkt(wkt))
        }
    }

    impl FromWkb for Ewkt<String> {
        fn from_wkb<R: Read>(rdr: &mut R, dialect: WkbDialect) -> Result<Self> {
            let mut out: Vec<u8> = Vec::new();
            let mut writer =
                WktWriter::with_opts(&mut out, WktDialect::Ewkt, CoordDimensions::xyzm(), None);
            crate::wkb::process_wkb_type_geom(rdr, &mut writer, dialect)?;
            let wkt = String::from_utf8(out).map_err(|_| {
                crate::error::GeozeroError::Geometry("Invalid UTF-8 encoding".to_string())
            })?;
            Ok(Ewkt(wkt))
        }
    }

    #[allow(deprecated)]
    impl FromWkb for WktString {
        fn from_wkb<R: Read>(rdr: &mut R, dialect: WkbDialect) -> Result<Self> {
            let mut out: Vec<u8> = Vec::new();
            let mut writer = WktWriter::new(&mut out);
            crate::wkb::process_wkb_type_geom(rdr, &mut writer, dialect)?;
            let wkt = String::from_utf8(out).map_err(|_| {
                crate::error::GeozeroError::Geometry("Invalid UTF-8 encoding".to_string())
            })?;
            #[allow(deprecated)]
            Ok(WktString(wkt))
        }
    }

    #[allow(deprecated)]
    impl FromWkb for EwktString {
        fn from_wkb<R: Read>(rdr: &mut R, dialect: WkbDialect) -> Result<Self> {
            let mut out: Vec<u8> = Vec::new();
            let mut writer =
                WktWriter::with_opts(&mut out, WktDialect::Ewkt, CoordDimensions::xyzm(), None);
            crate::wkb::process_wkb_type_geom(rdr, &mut writer, dialect)?;
            let wkt = String::from_utf8(out).map_err(|_| {
                crate::error::GeozeroError::Geometry("Invalid UTF-8 encoding".to_string())
            })?;
            #[allow(deprecated)]
            Ok(EwktString(wkt))
        }
    }
}

/// WKB dialect.
#[derive(Default, PartialEq, Debug, Clone, Copy)]
pub enum WktDialect {
    #[default]
    Wkt,
    Ewkt,
}