use super::{Dehydrate, Hydrate, SliceError};
use std::{
io::{Cursor, Error},
num::TryFromIntError,
str::Utf8Error,
};
#[derive(Debug)]
pub enum StringError {
TooLarge,
IoError(Error),
UnicodeError(Utf8Error),
}
impl From<Utf8Error> for StringError {
fn from(e: Utf8Error) -> Self {
Self::UnicodeError(e)
}
}
impl From<Error> for StringError {
fn from(e: Error) -> Self {
Self::IoError(e)
}
}
impl From<TryFromIntError> for StringError {
fn from(_e: TryFromIntError) -> Self {
Self::TooLarge
}
}
impl From<SliceError<std::io::Error>> for StringError {
fn from(se: SliceError<std::io::Error>) -> Self {
match se {
SliceError::Inner(e) => Self::IoError(e),
SliceError::IoError(e) => Self::IoError(e),
SliceError::TooLong => Self::TooLarge,
}
}
}
impl<T> Hydrate<T> for String
where
Self: Sized,
T: AsRef<[u8]>,
{
type Error = StringError;
fn hydrate(b: &mut Cursor<T>) -> Result<Self, Self::Error> {
let buf = Vec::<u8>::hydrate(b)?;
Ok(std::str::from_utf8(&buf)?.to_owned())
}
}
impl Dehydrate for &str
where
Self: Sized,
{
type Error = StringError;
fn dehydrate(&self, b: &mut Cursor<Vec<u8>>) -> Result<(), Self::Error> {
let buf = self.as_bytes();
Ok(buf.dehydrate(b)?)
}
}
impl Dehydrate for String
where
Self: Sized,
{
type Error = StringError;
fn dehydrate(&self, b: &mut Cursor<Vec<u8>>) -> Result<(), Self::Error> {
self.as_str().dehydrate(b)
}
}
#[cfg(test)]
mod tests {
use super::{super::test_round_trip, Dehydrate, Hydrate};
use std::io::Cursor;
test_round_trip!(round_trip_string, &str, String, ("foo bar", "fnord", ""));
}