feat(ser): Add ser::Error trait; avoid panic when serializing Paths

The only way to safely serialize a `Path` is to use
`.to_string_lossy()`, which replaces invalid UTF-8 characters with
the U+FFFD replacement character. Unfortunately this would lose
information, so for our default implementations, it'd be better
to punt and report an error, and leave it up to the user to
decide if they want to use the lossy encoding.

Unfortunately, we had no way for `Serializer`s to require some methods
on `Serializer::Error`, so there was no way before this patch for
the `Path` implementation to generically report that it cannot encode
this value. This adds that implementation.

breaking-change

Closes #57.
This commit is contained in:
Erick Tryzelaar
2016-01-28 10:41:21 -08:00
parent 9ae47a261e
commit f1b20577d3
5 changed files with 102 additions and 38 deletions
+6 -2
View File
@@ -27,6 +27,7 @@ use std::sync::Arc;
use core::nonzero::{NonZero, Zeroable};
use super::{
Error,
Serialize,
Serializer,
SeqVisitor,
@@ -682,7 +683,10 @@ impl Serialize for path::Path {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_str().unwrap().serialize(serializer)
match self.to_str() {
Some(s) => s.serialize(serializer),
None => Err(Error::invalid_value("Path contains invalid UTF-8 characters")),
}
}
}
@@ -690,7 +694,7 @@ impl Serialize for path::PathBuf {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
self.to_str().unwrap().serialize(serializer)
self.as_path().serialize(serializer)
}
}
+17 -1
View File
@@ -1,9 +1,25 @@
//! Generic serialization framework.
use std::error;
pub mod impls;
///////////////////////////////////////////////////////////////////////////////
/// `Error` is a trait that allows a `Serialize` to generically create a
/// `Serializer` error.
pub trait Error: Sized + error::Error {
/// Raised when there is general error when deserializing a type.
fn syntax(msg: &str) -> Self;
/// Raised when a `Serialize` was passed an incorrect value.
fn invalid_value(msg: &str) -> Self {
Error::syntax(msg)
}
}
///////////////////////////////////////////////////////////////////////////////
/// A trait that describes a type that can be serialized by a `Serializer`.
pub trait Serialize {
/// Serializes this value into this serializer.
@@ -16,7 +32,7 @@ pub trait Serialize {
/// A trait that describes a type that can serialize a stream of values into the underlying format.
pub trait Serializer {
/// The error type that can be returned if some error occurs during serialization.
type Error;
type Error: Error;
/// Serializes a `bool` value.
fn serialize_bool(&mut self, v: bool) -> Result<(), Self::Error>;