Skip to main content

arrow_schema/
lib.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//! Arrow logical types
19//!
20//! # Platform Support
21//!
22//! Only little-endian platforms are officially supported and tested in CI.
23//! Big-endian platforms are not tested in CI and may not work correctly.
24//! Fixes for big-endian platforms are welcome and handled on a best-effort basis,
25//! but compatibility is not guaranteed.
26
27#![doc(
28    html_logo_url = "https://arrow.apache.org/img/arrow-logo_chevrons_black-txt_white-bg.svg",
29    html_favicon_url = "https://arrow.apache.org/img/arrow-logo_chevrons_black-txt_transparent-bg.svg"
30)]
31#![cfg_attr(docsrs, feature(doc_cfg))]
32#![warn(missing_docs)]
33
34mod datatype;
35
36pub use datatype::*;
37use std::fmt::Display;
38mod datatype_display;
39mod datatype_parse;
40mod error;
41pub use error::*;
42pub mod extension;
43mod field;
44pub use field::*;
45mod fields;
46pub use fields::*;
47mod metadata;
48pub use metadata::*;
49mod schema;
50pub use schema::*;
51use std::ops;
52
53#[cfg(feature = "ffi")]
54pub mod ffi;
55
56/// Options that define the sort order of a given column
57///
58/// The default sorts equivalently to of `ASC NULLS FIRST` in SQL (i.e.
59/// ascending order with nulls sorting before any other values).
60///
61/// # Example creation
62/// ```
63/// # use arrow_schema::SortOptions;
64/// // configure using explicit initialization
65/// let options = SortOptions {
66///   descending: false,
67///   nulls_first: true,
68/// };
69/// // Default is ASC NULLs First
70/// assert_eq!(options, SortOptions::default());
71/// assert_eq!(options.to_string(), "ASC NULLS FIRST");
72///
73/// // Configure using builder APIs
74/// let options = SortOptions::default()
75///  .desc()
76///  .nulls_first();
77/// assert_eq!(options.to_string(), "DESC NULLS FIRST");
78///
79/// // configure using explicit field values
80/// let options = SortOptions::default()
81///  .with_descending(false)
82///  .with_nulls_first(false);
83/// assert_eq!(options.to_string(), "ASC NULLS LAST");
84/// ```
85///
86/// # Example operations
87/// It is also possible to negate the sort options using the `!` operator.
88/// ```
89/// use arrow_schema::SortOptions;
90/// let options = !SortOptions::default();
91/// assert_eq!(options.to_string(), "DESC NULLS LAST");
92/// ```
93#[derive(Clone, Hash, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
94pub struct SortOptions {
95    /// Whether to sort in descending order
96    pub descending: bool,
97    /// Whether to sort nulls first
98    pub nulls_first: bool,
99}
100
101impl Display for SortOptions {
102    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
103        if self.descending {
104            write!(f, "DESC")?;
105        } else {
106            write!(f, "ASC")?;
107        }
108        if self.nulls_first {
109            write!(f, " NULLS FIRST")?;
110        } else {
111            write!(f, " NULLS LAST")?;
112        }
113        Ok(())
114    }
115}
116
117impl SortOptions {
118    /// Create a new `SortOptions` struct
119    pub fn new(descending: bool, nulls_first: bool) -> Self {
120        Self {
121            descending,
122            nulls_first,
123        }
124    }
125
126    /// Set this sort options to sort in descending order
127    ///
128    /// See [Self::with_descending] to explicitly set the underlying field
129    pub fn desc(mut self) -> Self {
130        self.descending = true;
131        self
132    }
133
134    /// Set this sort options to sort in ascending order
135    ///
136    /// See [Self::with_descending] to explicitly set the underlying field
137    pub fn asc(mut self) -> Self {
138        self.descending = false;
139        self
140    }
141
142    /// Set this sort options to sort nulls first
143    ///
144    /// See [Self::with_nulls_first] to explicitly set the underlying field
145    pub fn nulls_first(mut self) -> Self {
146        self.nulls_first = true;
147        self
148    }
149
150    /// Set this sort options to sort nulls last
151    ///
152    /// See [Self::with_nulls_first] to explicitly set the underlying field
153    pub fn nulls_last(mut self) -> Self {
154        self.nulls_first = false;
155        self
156    }
157
158    /// Set this sort options to sort descending if argument is true
159    pub fn with_descending(mut self, descending: bool) -> Self {
160        self.descending = descending;
161        self
162    }
163
164    /// Set this sort options to sort nulls first if argument is true
165    pub fn with_nulls_first(mut self, nulls_first: bool) -> Self {
166        self.nulls_first = nulls_first;
167        self
168    }
169}
170
171impl Default for SortOptions {
172    fn default() -> Self {
173        Self {
174            descending: false,
175            // default to nulls first to match spark's behavior
176            nulls_first: true,
177        }
178    }
179}
180
181/// `!` operator is overloaded for `SortOptions` to invert boolean
182/// fields of the struct.
183impl ops::Not for SortOptions {
184    type Output = SortOptions;
185
186    fn not(self) -> SortOptions {
187        SortOptions {
188            descending: !self.descending,
189            nulls_first: !self.nulls_first,
190        }
191    }
192}
193
194#[test]
195fn test_overloaded_not_sort_options() {
196    let sort_options_array = [
197        SortOptions {
198            descending: false,
199            nulls_first: false,
200        },
201        SortOptions {
202            descending: false,
203            nulls_first: true,
204        },
205        SortOptions {
206            descending: true,
207            nulls_first: false,
208        },
209        SortOptions {
210            descending: true,
211            nulls_first: true,
212        },
213    ];
214
215    assert!((!sort_options_array[0]).descending);
216    assert!((!sort_options_array[0]).nulls_first);
217
218    assert!((!sort_options_array[1]).descending);
219    assert!(!(!sort_options_array[1]).nulls_first);
220
221    assert!(!(!sort_options_array[2]).descending);
222    assert!((!sort_options_array[2]).nulls_first);
223
224    assert!(!(!sort_options_array[3]).descending);
225    assert!(!(!sort_options_array[3]).nulls_first);
226}