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 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 fn new(delimiter: u8, header: Header, quote: Quote, flexible: bool, is_utf8: bool) -> Self {
68        Self {
69            delimiter,
70            header,
71            quote,
72            flexible,
73            is_utf8,
74        }
75    }
76}
77
78/// Header configuration for a CSV file.
79#[derive(Debug, Clone, PartialEq, Default)]
80pub struct Header {
81    /// Whether the CSV has a header row.
82    pub has_header_row: bool,
83    /// Number of rows to skip before the data (preamble/comment rows).
84    pub num_preamble_rows: usize,
85}
86
87impl Header {
88    /// Create a new Header configuration.
89    pub fn new(has_header_row: bool, num_preamble_rows: usize) -> Self {
90        Self {
91            has_header_row,
92            num_preamble_rows,
93        }
94    }
95}
96
97/// Quote character configuration.
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
99pub enum Quote {
100    /// No quoting.
101    None,
102    /// Quote with the specified character.
103    Some(u8),
104}
105
106impl Default for Quote {
107    fn default() -> Self {
108        Quote::Some(b'"')
109    }
110}
111
112impl Quote {
113    /// Returns the quote character if set.
114    pub fn char(&self) -> Option<u8> {
115        match self {
116            Quote::None => None,
117            Quote::Some(c) => Some(*c),
118        }
119    }
120}
121
122impl fmt::Display for Quote {
123    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124        match self {
125            Quote::None => write!(f, "none"),
126            Quote::Some(c) => write!(f, "{}", *c as char),
127        }
128    }
129}