1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! 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 ))
        }
    }
}