use std::io::{self, Write, Read};
use std::{error, fmt, result};
use std::str::Utf8Error;
use {CountSize, SizeLimit};
use byteorder::ByteOrder;
use std::error::Error as StdError;
pub use super::de::Deserializer;
pub use super::ser::Serializer;
use super::ser::SizeChecker;
use serde_crate as serde;
pub type Result<T> = result::Result<T, Error>;
pub type Error = Box<ErrorKind>;
#[derive(Debug)]
pub enum ErrorKind {
    
    
    Io(io::Error),
    
    InvalidUtf8Encoding(Utf8Error),
    
    
    InvalidBoolEncoding(u8),
    
    InvalidCharEncoding,
    
    
    InvalidTagEncoding(usize),
    
    
    DeserializeAnyNotSupported,
    
    
    SizeLimit,
    
    SequenceMustHaveLength,
    
    Custom(String),
}
impl StdError for ErrorKind {
    fn description(&self) -> &str {
        match *self {
            ErrorKind::Io(ref err) => error::Error::description(err),
            ErrorKind::InvalidUtf8Encoding(_) => "string is not valid utf8",
            ErrorKind::InvalidBoolEncoding(_) => "invalid u8 while decoding bool",
            ErrorKind::InvalidCharEncoding => "char is not valid",
            ErrorKind::InvalidTagEncoding(_) => "tag for enum is not valid",
            ErrorKind::SequenceMustHaveLength => "bincode can't encode infinite sequences",
            ErrorKind::DeserializeAnyNotSupported => {
                "bincode doesn't support serde::Deserializer::deserialize_any"
            }
            ErrorKind::SizeLimit => "the size limit for decoding has been reached",
            ErrorKind::Custom(ref msg) => msg,
        }
    }
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ErrorKind::Io(ref err) => Some(err),
            ErrorKind::InvalidUtf8Encoding(_) => None,
            ErrorKind::InvalidBoolEncoding(_) => None,
            ErrorKind::InvalidCharEncoding => None,
            ErrorKind::InvalidTagEncoding(_) => None,
            ErrorKind::SequenceMustHaveLength => None,
            ErrorKind::DeserializeAnyNotSupported => None,
            ErrorKind::SizeLimit => None,
            ErrorKind::Custom(_) => None,
        }
    }
}
impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        ErrorKind::Io(err).into()
    }
}
impl fmt::Display for ErrorKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ErrorKind::Io(ref ioerr) => write!(fmt, "io error: {}", ioerr),
            ErrorKind::InvalidUtf8Encoding(ref e) => write!(fmt, "{}: {}", self.description(), e),
            ErrorKind::InvalidBoolEncoding(b) => {
                write!(fmt, "{}, expected 0 or 1, found {}", self.description(), b)
            }
            ErrorKind::InvalidCharEncoding => write!(fmt, "{}", self.description()),
            ErrorKind::InvalidTagEncoding(tag) => {
                write!(fmt, "{}, found {}", self.description(), tag)
            }
            ErrorKind::SequenceMustHaveLength => {
                write!(
                    fmt,
                    "bincode can only encode sequences and maps that have a knowable size ahead of time."
                )
            }
            ErrorKind::SizeLimit => write!(fmt, "{}", self.description()),
            ErrorKind::DeserializeAnyNotSupported => {
                write!(
                    fmt,
                    "bincode does not support the serde::Deserializer::deserialize_any method"
                )
            }
            ErrorKind::Custom(ref s) => s.fmt(fmt),
        }
    }
}
impl serde::de::Error for Error {
    fn custom<T: fmt::Display>(desc: T) -> Error {
        ErrorKind::Custom(desc.to_string()).into()
    }
}
impl serde::ser::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ErrorKind::Custom(msg.to_string()).into()
    }
}
pub fn serialize_into<W, T: ?Sized, S, E>(writer: W, value: &T, size_limit: S) -> Result<()>
where
    W: Write,
    T: serde::Serialize,
    S: SizeLimit,
    E: ByteOrder,
{
    if let Some(limit) = size_limit.limit() {
        try!(serialized_size_bounded(value, limit).ok_or(
            ErrorKind::SizeLimit,
        ));
    }
    let mut serializer = Serializer::<_, E>::new(writer);
    serde::Serialize::serialize(value, &mut serializer)
}
pub fn serialize<T: ?Sized, S, E>(value: &T, size_limit: S) -> Result<Vec<u8>>
where
    T: serde::Serialize,
    S: SizeLimit,
    E: ByteOrder,
{
    let mut writer = match size_limit.limit() {
        Some(size_limit) => {
            let actual_size = try!(serialized_size_bounded(value, size_limit).ok_or(
                ErrorKind::SizeLimit,
            ));
            Vec::with_capacity(actual_size as usize)
        }
        None => {
            let size = serialized_size(value) as usize;
            Vec::with_capacity(size)
        }
    };
    try!(serialize_into::<_, _, _, E>(
        &mut writer,
        value,
        super::Infinite,
    ));
    Ok(writer)
}
impl SizeLimit for CountSize {
    fn add(&mut self, c: u64) -> Result<()> {
        self.total += c;
        if let Some(limit) = self.limit {
            if self.total > limit {
                return Err(Box::new(ErrorKind::SizeLimit));
            }
        }
        Ok(())
    }
    fn limit(&self) -> Option<u64> {
        unreachable!();
    }
}
pub fn serialized_size<T: ?Sized>(value: &T) -> u64
where
    T: serde::Serialize,
{
    let mut size_counter = SizeChecker {
        size_limit: CountSize {
            total: 0,
            limit: None,
        },
    };
    value.serialize(&mut size_counter).ok();
    size_counter.size_limit.total
}
pub fn serialized_size_bounded<T: ?Sized>(value: &T, max: u64) -> Option<u64>
where
    T: serde::Serialize,
{
    let mut size_counter = SizeChecker {
        size_limit: CountSize {
            total: 0,
            limit: Some(max),
        },
    };
    match value.serialize(&mut size_counter) {
        Ok(_) => Some(size_counter.size_limit.total),
        Err(_) => None,
    }
}
pub fn deserialize_from<R, T, S, E>(reader: R, size_limit: S) -> Result<T>
where
    R: Read,
    T: serde::de::DeserializeOwned,
    S: SizeLimit,
    E: ByteOrder,
{
    let reader = ::de::read::IoReader::new(reader);
    let mut deserializer = Deserializer::<_, S, E>::new(reader, size_limit);
    serde::Deserialize::deserialize(&mut deserializer)
}
pub fn deserialize<'a, T, E: ByteOrder>(bytes: &'a [u8]) -> Result<T>
where
    T: serde::de::Deserialize<'a>,
{
    let reader = ::de::read::SliceReader::new(bytes);
    let mut deserializer = Deserializer::<_, _, E>::new(reader, super::Infinite);
    serde::Deserialize::deserialize(&mut deserializer)
}