Skip to content

Commit

Permalink
Merge pull request #126 from georust/kyle/update-geo-types-writer
Browse files Browse the repository at this point in the history
Update `ToWkt::write_wkt` to not buffer string
  • Loading branch information
michaelkirk authored Nov 27, 2024
2 parents 575bd3f + 79ae352 commit 94c32cd
Showing 1 changed file with 68 additions and 2 deletions.
70 changes: 68 additions & 2 deletions src/to_wkt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,35 @@ pub use geo_trait_impl::{
write_rect, write_triangle,
};

use crate::error::Error;
use std::io;

/// A wrapper around something that implements std::io::Write to be used with our writer traits,
/// which require std::fmt::Write
struct WriterWrapper<W: io::Write> {
writer: W,
most_recent_err: Option<io::Error>,
}

impl<W: io::Write> WriterWrapper<W> {
fn new(writer: W) -> Self {
Self {
writer,
most_recent_err: None,
}
}
}

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(())
}
}

/// A trait for converting values to WKT
pub trait ToWkt<T>
where
Expand Down Expand Up @@ -49,7 +78,44 @@ where
///
/// assert_eq!(wkt_string, "POINT(1.2 3.4)");
/// ```
fn write_wkt(&self, mut writer: impl std::io::Write) -> std::io::Result<()> {
writer.write_all(self.wkt_string().as_bytes())
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| {
match (err, writer_wrapper.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()),
}
})
}
}

#[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");
}
}

0 comments on commit 94c32cd

Please sign in to comment.