use std::fmt;
use std::str::FromStr;
use bstring::bstr;
pub trait FromBStr: Sized {
type Err;
fn from_bstr(b: &bstr) -> Result<Self, Self::Err>;
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FromStrError<T> {
InvalidUtf8,
ParseError(T)
}
impl<T> FromStrError<T> {
#[inline]
pub fn as_inner(&self) -> Option<&T> {
match *self {
FromStrError::ParseError(ref t) => Some(t),
_ => None
}
}
#[inline]
pub fn into_inner(self) -> Option<T> {
match self {
FromStrError::ParseError(t) => Some(t),
_ => None
}
}
}
impl<T: fmt::Display> fmt::Display for FromStrError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
FromStrError::InvalidUtf8 => f.write_str("invalid utf-8"),
FromStrError::ParseError(ref e) => e.fmt(f)
}
}
}
impl<T: FromStr> FromBStr for T {
type Err = FromStrError<<T as FromStr>::Err>;
fn from_bstr(b: &bstr) -> Result<T, FromStrError<<Self as FromStr>::Err>> {
b.to_str().map_err(|_| FromStrError::InvalidUtf8)
.and_then(|s| s.parse().map_err(FromStrError::ParseError))
}
}