Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

name: Run tests
jobs:
wkt:
test:
name: wkt
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
Expand All @@ -28,3 +28,13 @@ jobs:
- run: cargo clippy --all-features --all-targets -- -Dwarnings
- run: cargo test --all-features
- run: cargo test --no-default-features
doc:
name: Documentation
runs-on: ubuntu-latest
env:
RUSTDOCFLAGS: -Dwarnings
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/install@cargo-docs-rs
- run: cargo docs-rs
124 changes: 28 additions & 96 deletions src/deserialize/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! This module deserialises to WKT using [`serde`].
//!
//! You can deserialise to [`geo_types`] or any other implementor of [`TryFromWkt`], using
//! [`deserialize_wkt`]. Or you can store this crates internal primitives [`wkt`]
//! or [`Wkt`] in your struct fields.
//! [`deserialize_wkt`]. Alternatively, you can store this crate's [`Wkt`] in your struct fields.

use crate::{TryFromWkt, Wkt, WktNum};
use serde::de::{Deserializer, Error, Visitor};
Expand All @@ -19,7 +18,7 @@ pub mod geo_types;
/// Deserializes a WKT String into any type which implements `TryFromWkt`.
///
/// This is useful when you have a struct which has a structured geometry field, (like a [`geo`](https://docs.rs/geo) or
/// [`geo-types`] geometry) stored as WKT.
/// [`geo-types`](https://docs.rs/geo-types) geometry) stored as WKT.
///
#[cfg_attr(feature = "geo-types", doc = "```")]
#[cfg_attr(not(feature = "geo-types"), doc = "```ignore")]
Expand Down Expand Up @@ -144,35 +143,6 @@ where
}
}

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::*;
Expand All @@ -185,71 +155,33 @@ mod tests {
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: _, // floating-point types cannot be used in patterns
y: _, // floating-point types cannot be used in patterns
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")
);
}
#[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: _, // floating-point types cannot be used in patterns
y: _, // floating-point types cannot be used in patterns
z: None,
m: None,
}),
dim: _dim,
})
));
}

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: _, // floating-point types cannot be used in patterns
y: _, // floating-point types cannot be used in patterns
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")
);
}
#[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")
);
}
}
2 changes: 1 addition & 1 deletion src/infer_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub fn infer_type(input: &str) -> Result<(GeometryType, Dimension), String> {
} else if input.starts_with(GEOMETRYCOLLECTION) {
Ok((GeometryType::GeometryCollection, dim))
} else {
return Err(format!("Unsupported WKT prefix {}", input));
Err(format!("Unsupported WKT prefix {}", input))
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
// The unstable `doc_auto_cfg` feature annotates documentation with any required cfg/features
// needed for optional items. We set the `docsrs` config when building for docs.rs. To use it
// in a local docs build, run: `cargo +nightly rustdoc --all-features -- --cfg docsrs`
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(docsrs, feature(doc_cfg))]

//! The `wkt` crate provides conversions to and from the [WKT (Well Known Text)](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry)
//! geometry format.
//!
//! Conversions are available via the [`TryFromWkt`] and [`ToWkt`] traits, with implementations for
//! [`geo_types`] and [`geo_traits`] primitives enabled by default.
//!
//! For advanced usage, see the [`types`](crate::types) module for a list of internally used types.
//! For advanced usage, see the [`types`] module for a list of internally used types.
//!
//! This crate has optional `serde` integration for deserializing fields containing WKT. See
//! [`deserialize`] for an example.
Expand Down
9 changes: 3 additions & 6 deletions src/to_wkt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ impl<W: io::Write> WriterWrapper<W> {
(Error::FmtError(_), Some(io_err)) => io_err,
(Error::FmtError(fmt_err), None) => {
debug_assert!(false, "FmtError without setting an error on WriterWrapper");
io::Error::new(io::ErrorKind::Other, fmt_err.to_string())
io::Error::other(fmt_err.to_string())
}
(other, _) => io::Error::new(io::ErrorKind::Other, other.to_string()),
(other, _) => io::Error::other(other.to_string()),
}
}
}
Expand Down Expand Up @@ -108,10 +108,7 @@ mod tests {
struct FailingWriter;
impl io::Write for FailingWriter {
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
Err(io::Error::new(
io::ErrorKind::Other,
"FailingWriter always fails",
))
Err(io::Error::other("FailingWriter always fails"))
}

fn flush(&mut self) -> io::Result<()> {
Expand Down
Loading