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
//! The module defines most error type used by this crate.

use crate::metas::{FieldDef, ValueKind};

/// The error returned from the crate.
#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("parsing error at line {line}: {desc}")]
    ParseError { line: usize, desc: String },
    #[error("schema mismatch error, expect {expect:?}, but found {found:?}")]
    SchemaMismatchError {
        expect: Vec<(Option<String>, ValueKind, Option<usize>)>,
        found: Vec<(String, ValueKind, usize)>,
    },
    #[error(
        r#"field size mismatch, expect {expect} elements in "{field_name}" field, but found {found} elements in record"#,
    )]
    FieldSizeMismatchError {
        field_name: String,
        expect: usize,
        found: usize,
    },
    #[error("record has {expect} fields, but the line has {found} tokens")]
    TextTokenMismatchError { expect: usize, found: usize },
    #[error("Invalid argument: {desc}")]
    InvalidArgumentError { desc: String },
}

impl Error {
    pub fn new_parse_error(line: usize, desc: &str) -> Error {
        Error::ParseError {
            line,
            desc: desc.to_owned(),
        }
    }

    pub fn new_schema_mismatch_error(
        record_fields: &[(Option<String>, ValueKind, Option<usize>)],
        file_fields: &[FieldDef],
    ) -> Error {
        let expect = record_fields.to_vec();
        let found = file_fields
            .iter()
            .map(|field_def| {
                (
                    field_def.name.to_owned(),
                    field_def.kind,
                    field_def.count as usize,
                )
            })
            .collect::<Vec<_>>();
        Error::SchemaMismatchError { expect, found }
    }

    pub fn new_field_size_mismatch_error(field_name: &str, expect: usize, found: usize) -> Error {
        Error::FieldSizeMismatchError {
            field_name: field_name.to_owned(),
            expect,
            found,
        }
    }

    pub fn new_text_token_mismatch_error(expect: usize, found: usize) -> Error {
        Error::TextTokenMismatchError { expect, found }
    }

    pub fn new_invalid_argument_error(desc: &str) -> Error {
        Error::InvalidArgumentError {
            desc: desc.to_owned(),
        }
    }
}