use crate::{Wkt, WktNum};
mod geo_trait_impl;
pub use geo_trait_impl::{
write_geometry, write_geometry_collection, write_line, write_linestring,
write_multi_linestring, write_multi_point, write_multi_polygon, write_point, write_polygon,
write_rect, write_triangle,
};
use crate::error::Error;
use std::io;
pub(crate) struct WriterWrapper<W: io::Write> {
writer: W,
most_recent_err: Option<io::Error>,
}
impl<W: io::Write> WriterWrapper<W> {
pub(crate) fn new(writer: W) -> Self {
Self {
writer,
most_recent_err: None,
}
}
pub(crate) fn into_io_err(self, err: Error) -> std::io::Error {
match (err, self.most_recent_err) {
(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())
}
(other, _) => io::Error::new(io::ErrorKind::Other, other.to_string()),
}
}
}
impl<W: io::Write> std::fmt::Write for WriterWrapper<W> {
fn write_str(&mut self, s: &str) -> std::fmt::Result {
self.writer.write(s.as_bytes()).map_err(|err| {
self.most_recent_err = Some(err);
std::fmt::Error
})?;
Ok(())
}
}
pub trait ToWkt<T>
where
T: WktNum + std::fmt::Display,
{
fn to_wkt(&self) -> Wkt<T>;
#[cfg_attr(feature = "geo-types", doc = "```")]
#[cfg_attr(not(feature = "geo-types"), doc = "```ignore")]
fn wkt_string(&self) -> String {
self.to_wkt().to_string()
}
#[cfg_attr(feature = "geo-types", doc = "```")]
#[cfg_attr(not(feature = "geo-types"), doc = "```ignore")]
fn write_wkt(&self, writer: impl io::Write) -> io::Result<()> {
let mut writer_wrapper = WriterWrapper::new(writer);
write_geometry(&mut writer_wrapper, &self.to_wkt())
.map_err(|err| writer_wrapper.into_io_err(err))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "geo-types")]
#[test]
fn write_wkt_error_handling() {
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",
))
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
let point = geo_types::Point::new(1.2, 3.4);
let err = point.write_wkt(FailingWriter).unwrap_err();
assert_eq!(err.to_string(), "FailingWriter always fails");
}
}