use crate::{TryFromWkt, Wkt, WktNum};
use serde::de::{Deserializer, Error, Visitor};
use std::{
default::Default,
fmt::{self, Debug},
marker::PhantomData,
str::FromStr,
};
#[cfg(feature = "geo-types")]
pub mod geo_types;
#[cfg_attr(feature = "geo-types", doc = "```")]
#[cfg_attr(not(feature = "geo-types"), doc = "```ignore")]
pub fn deserialize_wkt<'de, D, G, T>(deserializer: D) -> Result<G, D::Error>
where
D: Deserializer<'de>,
T: FromStr + Default + WktNum,
G: crate::TryFromWkt<T>,
<G as TryFromWkt<T>>::Error: std::fmt::Display,
{
deserializer.deserialize_str(TryFromWktVisitor::default())
}
struct TryFromWktVisitor<T, G: TryFromWkt<T>> {
_marker_t: PhantomData<T>,
_marker_g: PhantomData<G>,
}
impl<T, G: TryFromWkt<T>> Default for TryFromWktVisitor<T, G> {
fn default() -> Self {
Self {
_marker_t: PhantomData,
_marker_g: PhantomData,
}
}
}
impl<T, G> Visitor<'_> for TryFromWktVisitor<T, G>
where
T: FromStr + Default + WktNum,
G: TryFromWkt<T>,
<G as TryFromWkt<T>>::Error: std::fmt::Display,
{
type Value = G;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a valid WKT format")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
G::try_from_wkt_str(s).map_err(|e| serde::de::Error::custom(e))
}
}
struct WktVisitor<T> {
_marker: PhantomData<T>,
}
impl<T> Default for WktVisitor<T> {
fn default() -> Self {
WktVisitor {
_marker: PhantomData,
}
}
}
impl<T> Visitor<'_> for WktVisitor<T>
where
T: FromStr + Default + Debug + WktNum,
{
type Value = Wkt<T>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a valid WKT format")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))
}
}
impl<'de, T> serde::Deserialize<'de> for Wkt<T>
where
T: FromStr + Default + Debug + WktNum,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(WktVisitor::default())
}
}
struct GeometryVisitor<T> {
_marker: PhantomData<T>,
}
impl<T> Default for GeometryVisitor<T> {
fn default() -> Self {
GeometryVisitor {
_marker: PhantomData,
}
}
}
impl<T> Visitor<'_> for GeometryVisitor<T>
where
T: FromStr + Default + WktNum,
{
type Value = Wkt<T>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a valid WKT format")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
let wkt = Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))?;
Ok(wkt)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
types::{Coord, Point},
Wkt,
};
use serde::de::{
value::{Error, StrDeserializer},
Deserializer, Error as _, IntoDeserializer,
};
mod wkt {
use super::*;
#[test]
fn deserialize() {
let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1)".into_deserializer();
let wkt = deserializer
.deserialize_any(WktVisitor::<f64>::default())
.unwrap();
assert!(matches!(
wkt,
Wkt::Point(Point {
coord: Some(Coord {
x: _, y: _, z: None,
m: None,
}),
dim: _dim,
})
));
}
#[test]
fn deserialize_error() {
let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1A)".into_deserializer();
let wkt = deserializer.deserialize_any(WktVisitor::<f64>::default());
assert_eq!(
wkt.unwrap_err(),
Error::custom("Unable to parse input number as the desired output type")
);
}
}
mod geometry {
use super::*;
#[test]
fn deserialize() {
let deserializer: StrDeserializer<'_, Error> = "POINT (42 3.14)".into_deserializer();
let geometry = deserializer
.deserialize_any(GeometryVisitor::<f64>::default())
.unwrap();
assert!(matches!(
geometry,
Wkt::Point(Point {
coord: Some(Coord {
x: _, y: _, z: None,
m: None,
}),
dim: _dim,
})
));
}
#[test]
fn deserialize_error() {
let deserializer: StrDeserializer<'_, Error> = "POINT (42 PI3.14)".into_deserializer();
let geometry = deserializer.deserialize_any(GeometryVisitor::<f64>::default());
assert_eq!(
geometry.unwrap_err(),
Error::custom("Expected a number for the Y coordinate")
);
}
}
}