Skip to main content

datafusion_common/
parsers.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Interval parsing logic
19
20use std::fmt::Display;
21use std::str::FromStr;
22
23use crate::DataFusionError;
24
25/// Readable file compression type
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27pub enum CompressionTypeVariant {
28    /// Gzip-ed file
29    GZIP,
30    /// Bzip2-ed file
31    BZIP2,
32    /// Xz-ed file (liblzma)
33    XZ,
34    /// Zstd-ed file,
35    ZSTD,
36    /// Uncompressed file
37    UNCOMPRESSED,
38}
39
40impl FromStr for CompressionTypeVariant {
41    type Err = DataFusionError;
42
43    fn from_str(s: &str) -> Result<Self, Self::Err> {
44        let s = s.to_uppercase();
45        match s.as_str() {
46            "GZIP" | "GZ" => Ok(Self::GZIP),
47            "BZIP2" | "BZ2" => Ok(Self::BZIP2),
48            "XZ" => Ok(Self::XZ),
49            "ZST" | "ZSTD" => Ok(Self::ZSTD),
50            "" | "UNCOMPRESSED" => Ok(Self::UNCOMPRESSED),
51            _ => Err(DataFusionError::NotImplemented(format!(
52                "Unsupported file compression type {s}"
53            ))),
54        }
55    }
56}
57
58impl Display for CompressionTypeVariant {
59    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60        let str = match self {
61            Self::GZIP => "GZIP",
62            Self::BZIP2 => "BZIP2",
63            Self::XZ => "XZ",
64            Self::ZSTD => "ZSTD",
65            Self::UNCOMPRESSED => "",
66        };
67        write!(f, "{str}")
68    }
69}
70
71impl CompressionTypeVariant {
72    pub const fn is_compressed(&self) -> bool {
73        !matches!(self, &Self::UNCOMPRESSED)
74    }
75}
76
77/// CSV quote style
78///
79/// Controls when fields are quoted when writing CSV files.
80/// Corresponds to [`arrow::csv::QuoteStyle`].
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
82pub enum CsvQuoteStyle {
83    /// Quote all fields
84    Always,
85    /// Only quote fields when necessary (default)
86    #[default]
87    Necessary,
88    /// Quote all non-numeric fields
89    NonNumeric,
90    /// Never quote fields
91    Never,
92}
93
94impl FromStr for CsvQuoteStyle {
95    type Err = DataFusionError;
96
97    fn from_str(s: &str) -> Result<Self, Self::Err> {
98        match s.to_lowercase().as_str() {
99            "always" => Ok(Self::Always),
100            "necessary" => Ok(Self::Necessary),
101            "non_numeric" | "nonnumeric" => Ok(Self::NonNumeric),
102            "never" => Ok(Self::Never),
103            _ => Err(DataFusionError::NotImplemented(format!(
104                "Unsupported CSV quote style {s}"
105            ))),
106        }
107    }
108}
109
110impl From<CsvQuoteStyle> for arrow::csv::QuoteStyle {
111    fn from(style: CsvQuoteStyle) -> Self {
112        match style {
113            CsvQuoteStyle::Always => Self::Always,
114            CsvQuoteStyle::NonNumeric => Self::NonNumeric,
115            CsvQuoteStyle::Never => Self::Never,
116            CsvQuoteStyle::Necessary => Self::Necessary,
117        }
118    }
119}
120
121impl Display for CsvQuoteStyle {
122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123        let str = match self {
124            Self::Always => "Always",
125            Self::Necessary => "Necessary",
126            Self::NonNumeric => "NonNumeric",
127            Self::Never => "Never",
128        };
129        write!(f, "{str}")
130    }
131}