tsv 0.1.1

tsv (tab-seperated-values) data format for serde (serialization/deserialization)
Documentation
//! When serializing or deserializing tsv goes wrong.

use std::error;
use std::fmt::{self, Debug, Display};
use std::result;
use serde::ser;

/// This type represents all possible errors that can occur when serializing or deserializing tsv.
pub struct Error {
    pub(crate) err: Box<ErrorImpl>, // keep the size of `Error` small
}

/// For short.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub(crate) struct ErrorImpl {
    pub(crate) code: ErrorCode,
    pub(crate) line: usize,
    pub(crate) column: usize,
}

#[derive( Clone, Debug, PartialEq, Eq, PartialOrd, Ord )]
pub(crate) enum ErrorCode {
    Unknown,
    Serde( String ),
    UnsupportedEscape( char ),
    HeaderMistach,
    InvalidConfig,
    ExtraColumns,
    ExpectedChar,
    ExpectedBoolean,
    ExpectedUnsigned,
    ExpectedInteger,
    ExpectedFloat,
    ExpectedUnit,
    ExpectedVariant,
}

impl Error {
    pub(crate) fn new( code: ErrorCode, line: usize, column: usize ) -> Self {
        Error{ err: Box::new( ErrorImpl{ code, line, column })}
    }

    /// One-based line number at which the error was detected.
    ///
    /// Characters in the first line of the input (before the first newline character) are in line 1.
    pub fn line( &self ) -> usize { self.err.line }

    /// One-based column number at which the error was detected.
    ///
    /// The first string in each line are in column 1.
    ///
    /// Note that errors may occur in (line 0, column 0) when generated by serde.
    pub fn column( &self ) -> usize { self.err.column }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "TSV error"
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

impl Display for Error {
    fn fmt( &self, f: &mut fmt::Formatter ) -> fmt::Result {
        Display::fmt( &*self.err, f )
    }
}

impl Display for ErrorImpl {
    fn fmt( &self, f: &mut fmt::Formatter ) -> fmt::Result {
        if self.line == 0 {
            Debug::fmt( &self.code, f )
        } else {
            write!(
                f,
                "{:?} at line {} column {}",
                self.code,
                self.line,
                self.column
            )
        }
    }
}

impl Debug for Error {
    fn fmt( &self, f: &mut fmt::Formatter ) -> fmt::Result {
        Debug::fmt( &*self.err, f )
    }
}

impl ser::Error for Error {
    fn custom<T:Display>( _msg: T ) -> Error {
        Error {
            err: Box::new(
                ErrorImpl {
                    code: ErrorCode::Unknown,
                    line: 0,
                    column: 0,
                },
            ),
        }
    }
}

impl ::serde::de::Error for Error {
    fn custom<T:Display>( msg: T ) -> Error {
        Error {
            err: Box::new(
                ErrorImpl {
                    code: ErrorCode::Serde( msg.to_string() ),
                    line: 0,
                    column: 0,
                },
            ),
        }
    }

    fn invalid_type( unexp: ::serde::de::Unexpected, exp: &::serde::de::Expected ) -> Self {
        if let ::serde::de::Unexpected::Unit = unexp {
            Error::custom( format_args!( "invalid type: null, expected {}", exp ))
        } else {
            Error::custom( format_args!( "invalid type: {}, expected {}", unexp, exp ))
        }
    }
}