Skip to main content

ogc_cql2/
srid.rs

1// SPDX-License-Identifier: Apache-2.0
2
3#![warn(missing_docs)]
4
5//! Spatial Reference System identifier. Assumes implicitely the code is
6//! under the "EPSG" Authority.
7//!
8
9use crate::{CRS, MyError};
10use core::fmt;
11use std::num::NonZero;
12
13/// The constant representing the ubiquitous `EPSG:4326` or `WGS'84` SRID.
14pub const EPSG_4326: SRID = SRID(4326);
15
16/// Representation of a Spatial Reference IDentifier. For now the Authority
17/// is implied to be EPSG.
18#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
19#[allow(clippy::upper_case_acronyms)]
20pub struct SRID(i32);
21
22// invoked when parsing WKB blobs...
23impl TryFrom<i32> for SRID {
24    type Error = MyError;
25
26    fn try_from(value: i32) -> Result<Self, Self::Error> {
27        // -1 and 0 are valid values for undefined cartesian and geographic SRS
28        // as per GeoPackage specs...
29        match value {
30            x if x == -1 || x == 0 => Ok(Self(x)),
31            x => {
32                // ensure Proj knows it...
33                let code = usize::try_from(value)?;
34                let _ = CRS::from_epsg(
35                    NonZero::new(code)
36                        .ok_or(MyError::Runtime("Expected a non-zero EPSG code".into()))?,
37                )?;
38                Ok(Self(x))
39            }
40        }
41    }
42}
43
44// invoked when parsing GEOS geometry instances...
45impl TryFrom<usize> for SRID {
46    type Error = MyError;
47
48    fn try_from(value: usize) -> Result<Self, Self::Error> {
49        match value {
50            0 => Ok(Self(0)),
51            x => {
52                // ensure Proj knows it...
53                let _ = CRS::from_epsg(
54                    NonZero::new(value)
55                        .ok_or(MyError::Runtime("Expected a non-zero EPSG code".into()))?,
56                )?;
57                Ok(Self(x.try_into()?))
58            }
59        }
60    }
61}
62
63impl fmt::Display for SRID {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        match self.0 {
66            -1 => write!(f, "Undefined (Cartesian)"),
67            0 => write!(f, "Undefined (geographic)"),
68            x => write!(f, "EPSG:{x}"),
69        }
70    }
71}
72
73impl SRID {
74    pub(crate) fn as_usize(&self) -> Result<usize, MyError> {
75        let it = usize::try_from(self.0)?;
76        Ok(it)
77    }
78}