Skip to main content

csv_nose/
metadata.rs

1use crate::field_type::Type;
2use std::fmt;
3
4/// Metadata about a CSV file.
5#[derive(Debug, Clone)]
6pub struct Metadata {
7    /// The detected CSV dialect.
8    pub dialect: Dialect,
9    /// Average record length in bytes.
10    pub avg_record_len: usize,
11    /// Number of fields per record.
12    pub num_fields: usize,
13    /// Field names from the header row (or generated names if no header).
14    pub fields: Vec<String>,
15    /// Detected type for each field.
16    pub types: Vec<Type>,
17}
18
19impl Metadata {
20    /// Create a new Metadata instance.
21    pub const fn new(
22        dialect: Dialect,
23        avg_record_len: usize,
24        num_fields: usize,
25        fields: Vec<String>,
26        types: Vec<Type>,
27    ) -> Self {
28        Self {
29            dialect,
30            avg_record_len,
31            num_fields,
32            fields,
33            types,
34        }
35    }
36}
37
38/// CSV dialect specification.
39#[derive(Debug, Clone, PartialEq)]
40pub struct Dialect {
41    /// Field delimiter character.
42    pub delimiter: u8,
43    /// Header configuration.
44    pub header: Header,
45    /// Quote character configuration.
46    pub quote: Quote,
47    /// Whether the CSV has variable field counts across records.
48    pub flexible: bool,
49    /// Whether the file is valid UTF-8.
50    pub is_utf8: bool,
51}
52
53impl Default for Dialect {
54    fn default() -> Self {
55        Self {
56            delimiter: b',',
57            header: Header::default(),
58            quote: Quote::Some(b'"'),
59            flexible: false,
60            is_utf8: true,
61        }
62    }
63}
64
65impl Dialect {
66    /// Create a new Dialect with the given parameters.
67    pub const fn new(
68        delimiter: u8,
69        header: Header,
70        quote: Quote,
71        flexible: bool,
72        is_utf8: bool,
73    ) -> Self {
74        Self {
75            delimiter,
76            header,
77            quote,
78            flexible,
79            is_utf8,
80        }
81    }
82}
83
84/// Header configuration for a CSV file.
85#[derive(Debug, Clone, PartialEq, Default)]
86pub struct Header {
87    /// Whether the CSV has a header row.
88    pub has_header_row: bool,
89    /// Number of rows to skip before the data (preamble/comment rows).
90    pub num_preamble_rows: usize,
91}
92
93impl Header {
94    /// Create a new Header configuration.
95    pub const fn new(has_header_row: bool, num_preamble_rows: usize) -> Self {
96        Self {
97            has_header_row,
98            num_preamble_rows,
99        }
100    }
101}
102
103/// Quote character configuration.
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
105pub enum Quote {
106    /// No quoting.
107    None,
108    /// Quote with the specified character.
109    Some(u8),
110}
111
112impl Default for Quote {
113    fn default() -> Self {
114        Quote::Some(b'"')
115    }
116}
117
118impl Quote {
119    /// Returns the quote character if set.
120    #[inline]
121    pub fn char(&self) -> Option<u8> {
122        match self {
123            Quote::None => None,
124            Quote::Some(c) => Some(*c),
125        }
126    }
127}
128
129impl fmt::Display for Quote {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        match self {
132            Quote::None => write!(f, "none"),
133            Quote::Some(c) => write!(f, "{}", *c as char),
134        }
135    }
136}