Coverage Report

Created: 2025-08-26 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/andrewlamb/Software/arrow-rs/arrow-schema/src/field.rs
Line
Count
Source
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
use crate::error::ArrowError;
19
use std::cmp::Ordering;
20
use std::collections::HashMap;
21
use std::hash::{Hash, Hasher};
22
use std::sync::Arc;
23
24
use crate::datatype::DataType;
25
#[cfg(feature = "canonical_extension_types")]
26
use crate::extension::CanonicalExtensionType;
27
use crate::schema::SchemaBuilder;
28
use crate::{
29
    extension::{ExtensionType, EXTENSION_TYPE_METADATA_KEY, EXTENSION_TYPE_NAME_KEY},
30
    Fields, UnionFields, UnionMode,
31
};
32
33
/// A reference counted [`Field`]
34
pub type FieldRef = Arc<Field>;
35
36
/// Describes a single column in a [`Schema`](super::Schema).
37
///
38
/// A [`Schema`](super::Schema) is an ordered collection of
39
/// [`Field`] objects. Fields contain:
40
/// * `name`: the name of the field
41
/// * `data_type`: the type of the field
42
/// * `nullable`: if the field is nullable
43
/// * `metadata`: a map of key-value pairs containing additional custom metadata
44
///
45
/// Arrow Extension types, are encoded in `Field`s metadata. See
46
/// [`Self::try_extension_type`] to retrieve the [`ExtensionType`], if any.
47
#[derive(Debug, Clone)]
48
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49
pub struct Field {
50
    name: String,
51
    data_type: DataType,
52
    nullable: bool,
53
    #[deprecated(
54
        since = "54.0.0",
55
        note = "The ability to preserve dictionary IDs will be removed. With it, all fields related to it."
56
    )]
57
    dict_id: i64,
58
    dict_is_ordered: bool,
59
    /// A map of key-value pairs containing additional custom meta data.
60
    metadata: HashMap<String, String>,
61
}
62
63
// Auto-derive `PartialEq` traits will pull `dict_id` and `dict_is_ordered`
64
// into comparison. However, these properties are only used in IPC context
65
// for matching dictionary encoded data. They are not necessary to be same
66
// to consider schema equality. For example, in C++ `Field` implementation,
67
// it doesn't contain these dictionary properties too.
68
impl PartialEq for Field {
69
1.34k
    fn eq(&self, other: &Self) -> bool {
70
1.34k
        self.name == other.name
71
1.34k
            && self.data_type == other.data_type
72
1.34k
            && self.nullable == other.nullable
73
1.34k
            && self.metadata == other.metadata
74
1.34k
    }
75
}
76
77
impl Eq for Field {}
78
79
impl PartialOrd for Field {
80
0
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
81
0
        Some(self.cmp(other))
82
0
    }
83
}
84
85
impl Ord for Field {
86
0
    fn cmp(&self, other: &Self) -> Ordering {
87
0
        self.name
88
0
            .cmp(other.name())
89
0
            .then_with(|| self.data_type.cmp(other.data_type()))
90
0
            .then_with(|| self.nullable.cmp(&other.nullable))
91
0
            .then_with(|| {
92
                // ensure deterministic key order
93
0
                let mut keys: Vec<&String> =
94
0
                    self.metadata.keys().chain(other.metadata.keys()).collect();
95
0
                keys.sort();
96
0
                for k in keys {
97
0
                    match (self.metadata.get(k), other.metadata.get(k)) {
98
0
                        (None, None) => {}
99
                        (Some(_), None) => {
100
0
                            return Ordering::Less;
101
                        }
102
                        (None, Some(_)) => {
103
0
                            return Ordering::Greater;
104
                        }
105
0
                        (Some(v1), Some(v2)) => match v1.cmp(v2) {
106
0
                            Ordering::Equal => {}
107
0
                            other => {
108
0
                                return other;
109
                            }
110
                        },
111
                    }
112
                }
113
114
0
                Ordering::Equal
115
0
            })
116
0
    }
117
}
118
119
impl Hash for Field {
120
0
    fn hash<H: Hasher>(&self, state: &mut H) {
121
0
        self.name.hash(state);
122
0
        self.data_type.hash(state);
123
0
        self.nullable.hash(state);
124
125
        // ensure deterministic key order
126
0
        let mut keys: Vec<&String> = self.metadata.keys().collect();
127
0
        keys.sort();
128
0
        for k in keys {
129
0
            k.hash(state);
130
0
            self.metadata.get(k).expect("key valid").hash(state);
131
0
        }
132
0
    }
133
}
134
135
impl Field {
136
    /// Default list member field name
137
    pub const LIST_FIELD_DEFAULT_NAME: &'static str = "item";
138
139
    /// Creates a new field with the given name, data type, and nullability
140
    ///
141
    /// # Example
142
    /// ```
143
    /// # use arrow_schema::{Field, DataType};
144
    /// Field::new("field_name", DataType::Int32, true);
145
    /// ```
146
1.42k
    pub fn new(name: impl Into<String>, data_type: DataType, nullable: bool) -> Self {
147
        #[allow(deprecated)]
148
1.42k
        Field {
149
1.42k
            name: name.into(),
150
1.42k
            data_type,
151
1.42k
            nullable,
152
1.42k
            dict_id: 0,
153
1.42k
            dict_is_ordered: false,
154
1.42k
            metadata: HashMap::default(),
155
1.42k
        }
156
1.42k
    }
157
158
    /// Creates a new `Field` suitable for [`DataType::List`] and
159
    /// [`DataType::LargeList`]
160
    ///
161
    /// While not required, this method follows the convention of naming the
162
    /// `Field` `"item"`.
163
    ///
164
    /// # Example
165
    /// ```
166
    /// # use arrow_schema::{Field, DataType};
167
    /// assert_eq!(
168
    ///   Field::new("item", DataType::Int32, true),
169
    ///   Field::new_list_field(DataType::Int32, true)
170
    /// );
171
    /// ```
172
12
    pub fn new_list_field(data_type: DataType, nullable: bool) -> Self {
173
12
        Self::new(Self::LIST_FIELD_DEFAULT_NAME, data_type, nullable)
174
12
    }
175
176
    /// Creates a new field that has additional dictionary information
177
    #[deprecated(
178
        since = "54.0.0",
179
        note = "The ability to preserve dictionary IDs will be removed. With the dict_id field disappearing this function signature will change by removing the dict_id parameter."
180
    )]
181
0
    pub fn new_dict(
182
0
        name: impl Into<String>,
183
0
        data_type: DataType,
184
0
        nullable: bool,
185
0
        dict_id: i64,
186
0
        dict_is_ordered: bool,
187
0
    ) -> Self {
188
        #[allow(deprecated)]
189
0
        Field {
190
0
            name: name.into(),
191
0
            data_type,
192
0
            nullable,
193
0
            dict_id,
194
0
            dict_is_ordered,
195
0
            metadata: HashMap::default(),
196
0
        }
197
0
    }
198
199
    /// Create a new [`Field`] with [`DataType::Dictionary`]
200
    ///
201
    /// Use [`Self::new_dict`] for more advanced dictionary options
202
    ///
203
    /// # Panics
204
    ///
205
    /// Panics if [`!key.is_dictionary_key_type`][DataType::is_dictionary_key_type]
206
0
    pub fn new_dictionary(
207
0
        name: impl Into<String>,
208
0
        key: DataType,
209
0
        value: DataType,
210
0
        nullable: bool,
211
0
    ) -> Self {
212
0
        assert!(
213
0
            key.is_dictionary_key_type(),
214
0
            "{key} is not a valid dictionary key"
215
        );
216
0
        let data_type = DataType::Dictionary(Box::new(key), Box::new(value));
217
0
        Self::new(name, data_type, nullable)
218
0
    }
219
220
    /// Create a new [`Field`] with [`DataType::Struct`]
221
    ///
222
    /// - `name`: the name of the [`DataType::Struct`] field
223
    /// - `fields`: the description of each struct element
224
    /// - `nullable`: if the [`DataType::Struct`] array is nullable
225
0
    pub fn new_struct(name: impl Into<String>, fields: impl Into<Fields>, nullable: bool) -> Self {
226
0
        Self::new(name, DataType::Struct(fields.into()), nullable)
227
0
    }
228
229
    /// Create a new [`Field`] with [`DataType::List`]
230
    ///
231
    /// - `name`: the name of the [`DataType::List`] field
232
    /// - `value`: the description of each list element
233
    /// - `nullable`: if the [`DataType::List`] array is nullable
234
0
    pub fn new_list(name: impl Into<String>, value: impl Into<FieldRef>, nullable: bool) -> Self {
235
0
        Self::new(name, DataType::List(value.into()), nullable)
236
0
    }
237
238
    /// Create a new [`Field`] with [`DataType::LargeList`]
239
    ///
240
    /// - `name`: the name of the [`DataType::LargeList`] field
241
    /// - `value`: the description of each list element
242
    /// - `nullable`: if the [`DataType::LargeList`] array is nullable
243
0
    pub fn new_large_list(
244
0
        name: impl Into<String>,
245
0
        value: impl Into<FieldRef>,
246
0
        nullable: bool,
247
0
    ) -> Self {
248
0
        Self::new(name, DataType::LargeList(value.into()), nullable)
249
0
    }
250
251
    /// Create a new [`Field`] with [`DataType::FixedSizeList`]
252
    ///
253
    /// - `name`: the name of the [`DataType::FixedSizeList`] field
254
    /// - `value`: the description of each list element
255
    /// - `size`: the size of the fixed size list
256
    /// - `nullable`: if the [`DataType::FixedSizeList`] array is nullable
257
0
    pub fn new_fixed_size_list(
258
0
        name: impl Into<String>,
259
0
        value: impl Into<FieldRef>,
260
0
        size: i32,
261
0
        nullable: bool,
262
0
    ) -> Self {
263
0
        Self::new(name, DataType::FixedSizeList(value.into(), size), nullable)
264
0
    }
265
266
    /// Create a new [`Field`] with [`DataType::Map`]
267
    ///
268
    /// - `name`: the name of the [`DataType::Map`] field
269
    /// - `entries`: the name of the inner [`DataType::Struct`] field
270
    /// - `keys`: the map keys
271
    /// - `values`: the map values
272
    /// - `sorted`: if the [`DataType::Map`] array is sorted
273
    /// - `nullable`: if the [`DataType::Map`] array is nullable
274
0
    pub fn new_map(
275
0
        name: impl Into<String>,
276
0
        entries: impl Into<String>,
277
0
        keys: impl Into<FieldRef>,
278
0
        values: impl Into<FieldRef>,
279
0
        sorted: bool,
280
0
        nullable: bool,
281
0
    ) -> Self {
282
0
        let data_type = DataType::Map(
283
0
            Arc::new(Field::new(
284
0
                entries.into(),
285
0
                DataType::Struct(Fields::from([keys.into(), values.into()])),
286
0
                false, // The inner map field is always non-nullable (#1697),
287
0
            )),
288
0
            sorted,
289
0
        );
290
0
        Self::new(name, data_type, nullable)
291
0
    }
292
293
    /// Create a new [`Field`] with [`DataType::Union`]
294
    ///
295
    /// - `name`: the name of the [`DataType::Union`] field
296
    /// - `type_ids`: the union type ids
297
    /// - `fields`: the union fields
298
    /// - `mode`: the union mode
299
0
    pub fn new_union<S, F, T>(name: S, type_ids: T, fields: F, mode: UnionMode) -> Self
300
0
    where
301
0
        S: Into<String>,
302
0
        F: IntoIterator,
303
0
        F::Item: Into<FieldRef>,
304
0
        T: IntoIterator<Item = i8>,
305
    {
306
0
        Self::new(
307
0
            name,
308
0
            DataType::Union(UnionFields::new(type_ids, fields), mode),
309
            false, // Unions cannot be nullable
310
        )
311
0
    }
312
313
    /// Sets the `Field`'s optional custom metadata.
314
    #[inline]
315
937
    pub fn set_metadata(&mut self, metadata: HashMap<String, String>) {
316
937
        self.metadata = metadata;
317
937
    }
318
319
    /// Sets the metadata of this `Field` to be `metadata` and returns self
320
937
    pub fn with_metadata(mut self, metadata: HashMap<String, String>) -> Self {
321
937
        self.set_metadata(metadata);
322
937
        self
323
937
    }
324
325
    /// Returns the immutable reference to the `Field`'s optional custom metadata.
326
    #[inline]
327
326
    pub const fn metadata(&self) -> &HashMap<String, String> {
328
326
        &self.metadata
329
326
    }
330
331
    /// Returns a mutable reference to the `Field`'s optional custom metadata.
332
    #[inline]
333
0
    pub fn metadata_mut(&mut self) -> &mut HashMap<String, String> {
334
0
        &mut self.metadata
335
0
    }
336
337
    /// Returns an immutable reference to the `Field`'s name.
338
    #[inline]
339
139
    pub const fn name(&self) -> &String {
340
139
        &self.name
341
139
    }
342
343
    /// Set the name of this [`Field`]
344
    #[inline]
345
0
    pub fn set_name(&mut self, name: impl Into<String>) {
346
0
        self.name = name.into();
347
0
    }
348
349
    /// Set the name of the [`Field`] and returns self.
350
    ///
351
    /// ```
352
    /// # use arrow_schema::*;
353
    /// let field = Field::new("c1", DataType::Int64, false)
354
    ///    .with_name("c2");
355
    ///
356
    /// assert_eq!(field.name(), "c2");
357
    /// ```
358
0
    pub fn with_name(mut self, name: impl Into<String>) -> Self {
359
0
        self.set_name(name);
360
0
        self
361
0
    }
362
363
    /// Returns an immutable reference to the [`Field`]'s  [`DataType`].
364
    #[inline]
365
1.88k
    pub const fn data_type(&self) -> &DataType {
366
1.88k
        &self.data_type
367
1.88k
    }
368
369
    /// Set [`DataType`] of the [`Field`]
370
    ///
371
    /// ```
372
    /// # use arrow_schema::*;
373
    /// let mut field = Field::new("c1", DataType::Int64, false);
374
    /// field.set_data_type(DataType::Utf8);
375
    ///
376
    /// assert_eq!(field.data_type(), &DataType::Utf8);
377
    /// ```
378
    #[inline]
379
0
    pub fn set_data_type(&mut self, data_type: DataType) {
380
0
        self.data_type = data_type;
381
0
    }
382
383
    /// Set [`DataType`] of the [`Field`] and returns self.
384
    ///
385
    /// ```
386
    /// # use arrow_schema::*;
387
    /// let field = Field::new("c1", DataType::Int64, false)
388
    ///    .with_data_type(DataType::Utf8);
389
    ///
390
    /// assert_eq!(field.data_type(), &DataType::Utf8);
391
    /// ```
392
0
    pub fn with_data_type(mut self, data_type: DataType) -> Self {
393
0
        self.set_data_type(data_type);
394
0
        self
395
0
    }
396
397
    /// Returns the extension type name of this [`Field`], if set.
398
    ///
399
    /// This returns the value of [`EXTENSION_TYPE_NAME_KEY`], if set in
400
    /// [`Field::metadata`]. If the key is missing, there is no extension type
401
    /// name and this returns `None`.
402
    ///
403
    /// # Example
404
    ///
405
    /// ```
406
    /// # use arrow_schema::{DataType, extension::EXTENSION_TYPE_NAME_KEY, Field};
407
    ///
408
    /// let field = Field::new("", DataType::Null, false);
409
    /// assert_eq!(field.extension_type_name(), None);
410
    ///
411
    /// let field = Field::new("", DataType::Null, false).with_metadata(
412
    ///    [(EXTENSION_TYPE_NAME_KEY.to_owned(), "example".to_owned())]
413
    ///        .into_iter()
414
    ///        .collect(),
415
    /// );
416
    /// assert_eq!(field.extension_type_name(), Some("example"));
417
    /// ```
418
0
    pub fn extension_type_name(&self) -> Option<&str> {
419
0
        self.metadata()
420
0
            .get(EXTENSION_TYPE_NAME_KEY)
421
0
            .map(String::as_ref)
422
0
    }
423
424
    /// Returns the extension type metadata of this [`Field`], if set.
425
    ///
426
    /// This returns the value of [`EXTENSION_TYPE_METADATA_KEY`], if set in
427
    /// [`Field::metadata`]. If the key is missing, there is no extension type
428
    /// metadata and this returns `None`.
429
    ///
430
    /// # Example
431
    ///
432
    /// ```
433
    /// # use arrow_schema::{DataType, extension::EXTENSION_TYPE_METADATA_KEY, Field};
434
    ///
435
    /// let field = Field::new("", DataType::Null, false);
436
    /// assert_eq!(field.extension_type_metadata(), None);
437
    ///
438
    /// let field = Field::new("", DataType::Null, false).with_metadata(
439
    ///    [(EXTENSION_TYPE_METADATA_KEY.to_owned(), "example".to_owned())]
440
    ///        .into_iter()
441
    ///        .collect(),
442
    /// );
443
    /// assert_eq!(field.extension_type_metadata(), Some("example"));
444
    /// ```
445
0
    pub fn extension_type_metadata(&self) -> Option<&str> {
446
0
        self.metadata()
447
0
            .get(EXTENSION_TYPE_METADATA_KEY)
448
0
            .map(String::as_ref)
449
0
    }
450
451
    /// Returns an instance of the given [`ExtensionType`] of this [`Field`],
452
    /// if set in the [`Field::metadata`].
453
    ///
454
    /// # Error
455
    ///
456
    /// Returns an error if
457
    /// - this field does not have the name of this extension type
458
    ///   ([`ExtensionType::NAME`]) in the [`Field::metadata`] (mismatch or
459
    ///   missing)
460
    /// - the deserialization of the metadata
461
    ///   ([`ExtensionType::deserialize_metadata`]) fails
462
    /// - the construction of the extension type ([`ExtensionType::try_new`])
463
    ///   fail (for example when the [`Field::data_type`] is not supported by
464
    ///   the extension type ([`ExtensionType::supports_data_type`]))
465
0
    pub fn try_extension_type<E: ExtensionType>(&self) -> Result<E, ArrowError> {
466
        // Check the extension name in the metadata
467
0
        match self.extension_type_name() {
468
            // It should match the name of the given extension type
469
0
            Some(name) if name == E::NAME => {
470
                // Deserialize the metadata and try to construct the extension
471
                // type
472
0
                E::deserialize_metadata(self.extension_type_metadata())
473
0
                    .and_then(|metadata| E::try_new(self.data_type(), metadata))
474
            }
475
            // Name mismatch
476
0
            Some(name) => Err(ArrowError::InvalidArgumentError(format!(
477
0
                "Field extension type name mismatch, expected {}, found {name}",
478
0
                E::NAME
479
0
            ))),
480
            // Name missing
481
0
            None => Err(ArrowError::InvalidArgumentError(
482
0
                "Field extension type name missing".to_owned(),
483
0
            )),
484
        }
485
0
    }
486
487
    /// Returns an instance of the given [`ExtensionType`] of this [`Field`],
488
    /// panics if this [`Field`] does not have this extension type.
489
    ///
490
    /// # Panic
491
    ///
492
    /// This calls [`Field::try_extension_type`] and panics when it returns an
493
    /// error.
494
0
    pub fn extension_type<E: ExtensionType>(&self) -> E {
495
0
        self.try_extension_type::<E>()
496
0
            .unwrap_or_else(|e| panic!("{e}"))
497
0
    }
498
499
    /// Updates the metadata of this [`Field`] with the [`ExtensionType::NAME`]
500
    /// and [`ExtensionType::metadata`] of the given [`ExtensionType`], if the
501
    /// given extension type supports the [`Field::data_type`] of this field
502
    /// ([`ExtensionType::supports_data_type`]).
503
    ///
504
    /// If the given extension type defines no metadata, a previously set
505
    /// value of [`EXTENSION_TYPE_METADATA_KEY`] is cleared.
506
    ///
507
    /// # Error
508
    ///
509
    /// This functions returns an error if the data type of this field does not
510
    /// match any of the supported storage types of the given extension type.
511
0
    pub fn try_with_extension_type<E: ExtensionType>(
512
0
        &mut self,
513
0
        extension_type: E,
514
0
    ) -> Result<(), ArrowError> {
515
        // Make sure the data type of this field is supported
516
0
        extension_type.supports_data_type(&self.data_type)?;
517
518
0
        self.metadata
519
0
            .insert(EXTENSION_TYPE_NAME_KEY.to_owned(), E::NAME.to_owned());
520
0
        match extension_type.serialize_metadata() {
521
0
            Some(metadata) => self
522
0
                .metadata
523
0
                .insert(EXTENSION_TYPE_METADATA_KEY.to_owned(), metadata),
524
            // If this extension type has no metadata, we make sure to
525
            // clear previously set metadata.
526
0
            None => self.metadata.remove(EXTENSION_TYPE_METADATA_KEY),
527
        };
528
529
0
        Ok(())
530
0
    }
531
532
    /// Updates the metadata of this [`Field`] with the [`ExtensionType::NAME`]
533
    /// and [`ExtensionType::metadata`] of the given [`ExtensionType`].
534
    ///
535
    /// # Panics
536
    ///
537
    /// This calls [`Field::try_with_extension_type`] and panics when it
538
    /// returns an error.
539
0
    pub fn with_extension_type<E: ExtensionType>(mut self, extension_type: E) -> Self {
540
0
        self.try_with_extension_type(extension_type)
541
0
            .unwrap_or_else(|e| panic!("{e}"));
542
0
        self
543
0
    }
544
545
    /// Returns the [`CanonicalExtensionType`] of this [`Field`], if set.
546
    ///
547
    /// # Error
548
    ///
549
    /// Returns an error if
550
    /// - this field does have a canonical extension type (mismatch or missing)
551
    /// - the canonical extension is not supported
552
    /// - the construction of the extension type fails
553
    #[cfg(feature = "canonical_extension_types")]
554
    pub fn try_canonical_extension_type(&self) -> Result<CanonicalExtensionType, ArrowError> {
555
        CanonicalExtensionType::try_from(self)
556
    }
557
558
    /// Indicates whether this [`Field`] supports null values.
559
    ///
560
    /// If true, the field *may* contain null values.
561
    #[inline]
562
1.88k
    pub const fn is_nullable(&self) -> bool {
563
1.88k
        self.nullable
564
1.88k
    }
565
566
    /// Set the `nullable` of this [`Field`].
567
    ///
568
    /// ```
569
    /// # use arrow_schema::*;
570
    /// let mut field = Field::new("c1", DataType::Int64, false);
571
    /// field.set_nullable(true);
572
    ///
573
    /// assert_eq!(field.is_nullable(), true);
574
    /// ```
575
    #[inline]
576
14
    pub fn set_nullable(&mut self, nullable: bool) {
577
14
        self.nullable = nullable;
578
14
    }
579
580
    /// Set `nullable` of the [`Field`] and returns self.
581
    ///
582
    /// ```
583
    /// # use arrow_schema::*;
584
    /// let field = Field::new("c1", DataType::Int64, false)
585
    ///    .with_nullable(true);
586
    ///
587
    /// assert_eq!(field.is_nullable(), true);
588
    /// ```
589
14
    pub fn with_nullable(mut self, nullable: bool) -> Self {
590
14
        self.set_nullable(nullable);
591
14
        self
592
14
    }
593
594
    /// Returns a (flattened) [`Vec`] containing all child [`Field`]s
595
    /// within `self` contained within this field (including `self`)
596
0
    pub(crate) fn fields(&self) -> Vec<&Field> {
597
0
        let mut collected_fields = vec![self];
598
0
        collected_fields.append(&mut Field::_fields(&self.data_type));
599
600
0
        collected_fields
601
0
    }
602
603
0
    fn _fields(dt: &DataType) -> Vec<&Field> {
604
0
        match dt {
605
0
            DataType::Struct(fields) => fields.iter().flat_map(|f| f.fields()).collect(),
606
0
            DataType::Union(fields, _) => fields.iter().flat_map(|(_, f)| f.fields()).collect(),
607
0
            DataType::List(field)
608
0
            | DataType::LargeList(field)
609
0
            | DataType::FixedSizeList(field, _)
610
0
            | DataType::Map(field, _) => field.fields(),
611
0
            DataType::Dictionary(_, value_field) => Field::_fields(value_field.as_ref()),
612
0
            DataType::RunEndEncoded(_, field) => field.fields(),
613
0
            _ => vec![],
614
        }
615
0
    }
616
617
    /// Returns a vector containing all (potentially nested) `Field` instances selected by the
618
    /// dictionary ID they use
619
    #[inline]
620
    #[deprecated(
621
        since = "54.0.0",
622
        note = "The ability to preserve dictionary IDs will be removed. With it, all fields related to it."
623
    )]
624
0
    pub(crate) fn fields_with_dict_id(&self, id: i64) -> Vec<&Field> {
625
0
        self.fields()
626
0
            .into_iter()
627
0
            .filter(|&field| {
628
                #[allow(deprecated)]
629
0
                let matching_dict_id = field.dict_id == id;
630
0
                matches!(field.data_type(), DataType::Dictionary(_, _)) && matching_dict_id
631
0
            })
632
0
            .collect()
633
0
    }
634
635
    /// Returns the dictionary ID, if this is a dictionary type.
636
    #[inline]
637
    #[deprecated(
638
        since = "54.0.0",
639
        note = "The ability to preserve dictionary IDs will be removed. With it, all fields related to it."
640
    )]
641
0
    pub const fn dict_id(&self) -> Option<i64> {
642
0
        match self.data_type {
643
            #[allow(deprecated)]
644
0
            DataType::Dictionary(_, _) => Some(self.dict_id),
645
0
            _ => None,
646
        }
647
0
    }
648
649
    /// Returns whether this `Field`'s dictionary is ordered, if this is a dictionary type.
650
    ///
651
    /// # Example
652
    /// ```
653
    /// # use arrow_schema::{DataType, Field};
654
    /// // non dictionaries do not have a dict is ordered flat
655
    /// let field = Field::new("c1", DataType::Int64, false);
656
    /// assert_eq!(field.dict_is_ordered(), None);
657
    /// // by default dictionary is not ordered
658
    /// let field = Field::new("c1", DataType::Dictionary(Box::new(DataType::Int64), Box::new(DataType::Utf8)), false);
659
    /// assert_eq!(field.dict_is_ordered(), Some(false));
660
    /// let field = field.with_dict_is_ordered(true);
661
    /// assert_eq!(field.dict_is_ordered(), Some(true));
662
    /// ```
663
    #[inline]
664
0
    pub const fn dict_is_ordered(&self) -> Option<bool> {
665
0
        match self.data_type {
666
0
            DataType::Dictionary(_, _) => Some(self.dict_is_ordered),
667
0
            _ => None,
668
        }
669
0
    }
670
671
    /// Set the is ordered field for this `Field`, if it is a dictionary.
672
    ///
673
    /// Does nothing if this is not a dictionary type.
674
    ///
675
    /// See [`Field::dict_is_ordered`] for more information.
676
0
    pub fn with_dict_is_ordered(mut self, dict_is_ordered: bool) -> Self {
677
0
        if matches!(self.data_type, DataType::Dictionary(_, _)) {
678
0
            self.dict_is_ordered = dict_is_ordered;
679
0
        };
680
0
        self
681
0
    }
682
683
    /// Merge this field into self if it is compatible.
684
    ///
685
    /// Struct fields are merged recursively.
686
    ///
687
    /// NOTE: `self` may be updated to a partial / unexpected state in case of merge failure.
688
    ///
689
    /// Example:
690
    ///
691
    /// ```
692
    /// # use arrow_schema::*;
693
    /// let mut field = Field::new("c1", DataType::Int64, false);
694
    /// assert!(field.try_merge(&Field::new("c1", DataType::Int64, true)).is_ok());
695
    /// assert!(field.is_nullable());
696
    /// ```
697
0
    pub fn try_merge(&mut self, from: &Field) -> Result<(), ArrowError> {
698
0
        if from.dict_is_ordered != self.dict_is_ordered {
699
0
            return Err(ArrowError::SchemaError(format!(
700
0
                "Fail to merge schema field '{}' because from dict_is_ordered = {} does not match {}",
701
0
                self.name, from.dict_is_ordered, self.dict_is_ordered
702
0
            )));
703
0
        }
704
        // merge metadata
705
0
        match (self.metadata().is_empty(), from.metadata().is_empty()) {
706
            (false, false) => {
707
0
                let mut merged = self.metadata().clone();
708
0
                for (key, from_value) in from.metadata() {
709
0
                    if let Some(self_value) = self.metadata.get(key) {
710
0
                        if self_value != from_value {
711
0
                            return Err(ArrowError::SchemaError(format!(
712
0
                                "Fail to merge field '{}' due to conflicting metadata data value for key {}.
713
0
                                    From value = {} does not match {}", self.name, key, from_value, self_value),
714
0
                            ));
715
0
                        }
716
0
                    } else {
717
0
                        merged.insert(key.clone(), from_value.clone());
718
0
                    }
719
                }
720
0
                self.set_metadata(merged);
721
            }
722
0
            (true, false) => {
723
0
                self.set_metadata(from.metadata().clone());
724
0
            }
725
0
            _ => {}
726
        }
727
0
        match &mut self.data_type {
728
0
            DataType::Struct(nested_fields) => match &from.data_type {
729
0
                DataType::Struct(from_nested_fields) => {
730
0
                    let mut builder = SchemaBuilder::new();
731
0
                    nested_fields.iter().chain(from_nested_fields).try_for_each(|f| builder.try_merge(f))?;
732
0
                    *nested_fields = builder.finish().fields;
733
                }
734
                _ => {
735
0
                    return Err(ArrowError::SchemaError(
736
0
                        format!("Fail to merge schema field '{}' because the from data_type = {} is not DataType::Struct",
737
0
                            self.name, from.data_type)
738
0
                ))}
739
            },
740
0
            DataType::Union(nested_fields, _) => match &from.data_type {
741
0
                DataType::Union(from_nested_fields, _) => {
742
0
                    nested_fields.try_merge(from_nested_fields)?
743
                }
744
                _ => {
745
0
                    return Err(ArrowError::SchemaError(
746
0
                        format!("Fail to merge schema field '{}' because the from data_type = {} is not DataType::Union",
747
0
                            self.name, from.data_type)
748
0
                    ));
749
                }
750
            },
751
0
            DataType::List(field) => match &from.data_type {
752
0
                DataType::List(from_field) => {
753
0
                    let mut f = (**field).clone();
754
0
                    f.try_merge(from_field)?;
755
0
                    (*field) = Arc::new(f);
756
                },
757
                _ => {
758
0
                    return Err(ArrowError::SchemaError(
759
0
                        format!("Fail to merge schema field '{}' because the from data_type = {} is not DataType::List",
760
0
                            self.name, from.data_type)
761
0
                ))}
762
            },
763
0
            DataType::LargeList(field) => match &from.data_type {
764
0
                DataType::LargeList(from_field) => {
765
0
                    let mut f = (**field).clone();
766
0
                    f.try_merge(from_field)?;
767
0
                    (*field) = Arc::new(f);
768
                },
769
                _ => {
770
0
                    return Err(ArrowError::SchemaError(
771
0
                        format!("Fail to merge schema field '{}' because the from data_type = {} is not DataType::LargeList",
772
0
                            self.name, from.data_type)
773
0
                ))}
774
            },
775
0
            DataType::Null => {
776
0
                self.nullable = true;
777
0
                self.data_type = from.data_type.clone();
778
0
            }
779
            | DataType::Boolean
780
            | DataType::Int8
781
            | DataType::Int16
782
            | DataType::Int32
783
            | DataType::Int64
784
            | DataType::UInt8
785
            | DataType::UInt16
786
            | DataType::UInt32
787
            | DataType::UInt64
788
            | DataType::Float16
789
            | DataType::Float32
790
            | DataType::Float64
791
            | DataType::Timestamp(_, _)
792
            | DataType::Date32
793
            | DataType::Date64
794
            | DataType::Time32(_)
795
            | DataType::Time64(_)
796
            | DataType::Duration(_)
797
            | DataType::Binary
798
            | DataType::LargeBinary
799
            | DataType::BinaryView
800
            | DataType::Interval(_)
801
            | DataType::LargeListView(_)
802
            | DataType::ListView(_)
803
            | DataType::Map(_, _)
804
            | DataType::Dictionary(_, _)
805
            | DataType::RunEndEncoded(_, _)
806
            | DataType::FixedSizeList(_, _)
807
            | DataType::FixedSizeBinary(_)
808
            | DataType::Utf8
809
            | DataType::LargeUtf8
810
            | DataType::Utf8View
811
            | DataType::Decimal32(_, _)
812
            | DataType::Decimal64(_, _)
813
            | DataType::Decimal128(_, _)
814
            | DataType::Decimal256(_, _) => {
815
0
                if from.data_type == DataType::Null {
816
0
                    self.nullable = true;
817
0
                } else if self.data_type != from.data_type {
818
0
                    return Err(ArrowError::SchemaError(
819
0
                        format!("Fail to merge schema field '{}' because the from data_type = {} does not equal {}",
820
0
                            self.name, from.data_type, self.data_type)
821
0
                    ));
822
0
                }
823
            }
824
        }
825
0
        self.nullable |= from.nullable;
826
827
0
        Ok(())
828
0
    }
829
830
    /// Check to see if `self` is a superset of `other` field. Superset is defined as:
831
    ///
832
    /// * if nullability doesn't match, self needs to be nullable
833
    /// * self.metadata is a superset of other.metadata
834
    /// * all other fields are equal
835
0
    pub fn contains(&self, other: &Field) -> bool {
836
0
        self.name == other.name
837
0
        && self.data_type.contains(&other.data_type)
838
0
        && self.dict_is_ordered == other.dict_is_ordered
839
        // self need to be nullable or both of them are not nullable
840
0
        && (self.nullable || !other.nullable)
841
        // make sure self.metadata is a superset of other.metadata
842
0
        && other.metadata.iter().all(|(k, v1)| {
843
0
            self.metadata.get(k).map(|v2| v1 == v2).unwrap_or_default()
844
0
        })
845
0
    }
846
847
    /// Return size of this instance in bytes.
848
    ///
849
    /// Includes the size of `Self`.
850
0
    pub fn size(&self) -> usize {
851
0
        std::mem::size_of_val(self) - std::mem::size_of_val(&self.data_type)
852
0
            + self.data_type.size()
853
0
            + self.name.capacity()
854
0
            + (std::mem::size_of::<(String, String)>() * self.metadata.capacity())
855
0
            + self
856
0
                .metadata
857
0
                .iter()
858
0
                .map(|(k, v)| k.capacity() + v.capacity())
859
0
                .sum::<usize>()
860
0
    }
861
}
862
863
// TODO: improve display with crate https://crates.io/crates/derive_more ?
864
impl std::fmt::Display for Field {
865
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
866
0
        write!(f, "{self:?}")
867
0
    }
868
}
869
870
#[cfg(test)]
871
mod test {
872
    use super::*;
873
    use std::collections::hash_map::DefaultHasher;
874
875
    #[test]
876
    fn test_new_with_string() {
877
        // Fields should allow owned Strings to support reuse
878
        let s = "c1";
879
        Field::new(s, DataType::Int64, false);
880
    }
881
882
    #[test]
883
    fn test_new_dict_with_string() {
884
        // Fields should allow owned Strings to support reuse
885
        let s = "c1";
886
        #[allow(deprecated)]
887
        Field::new_dict(s, DataType::Int64, false, 4, false);
888
    }
889
890
    #[test]
891
    fn test_merge_incompatible_types() {
892
        let mut field = Field::new("c1", DataType::Int64, false);
893
        let result = field
894
            .try_merge(&Field::new("c1", DataType::Float32, true))
895
            .expect_err("should fail")
896
            .to_string();
897
        assert_eq!("Schema error: Fail to merge schema field 'c1' because the from data_type = Float32 does not equal Int64", result);
898
    }
899
900
    #[test]
901
    fn test_merge_with_null() {
902
        let mut field1 = Field::new("c1", DataType::Null, true);
903
        field1
904
            .try_merge(&Field::new("c1", DataType::Float32, false))
905
            .expect("should widen type to nullable float");
906
        assert_eq!(Field::new("c1", DataType::Float32, true), field1);
907
908
        let mut field2 = Field::new("c2", DataType::Utf8, false);
909
        field2
910
            .try_merge(&Field::new("c2", DataType::Null, true))
911
            .expect("should widen type to nullable utf8");
912
        assert_eq!(Field::new("c2", DataType::Utf8, true), field2);
913
    }
914
915
    #[test]
916
    fn test_merge_with_nested_null() {
917
        let mut struct1 = Field::new(
918
            "s1",
919
            DataType::Struct(Fields::from(vec![Field::new(
920
                "inner",
921
                DataType::Float32,
922
                false,
923
            )])),
924
            false,
925
        );
926
927
        let struct2 = Field::new(
928
            "s2",
929
            DataType::Struct(Fields::from(vec![Field::new(
930
                "inner",
931
                DataType::Null,
932
                false,
933
            )])),
934
            true,
935
        );
936
937
        struct1
938
            .try_merge(&struct2)
939
            .expect("should widen inner field's type to nullable float");
940
        assert_eq!(
941
            Field::new(
942
                "s1",
943
                DataType::Struct(Fields::from(vec![Field::new(
944
                    "inner",
945
                    DataType::Float32,
946
                    true,
947
                )])),
948
                true,
949
            ),
950
            struct1
951
        );
952
953
        let mut list1 = Field::new(
954
            "l1",
955
            DataType::List(Field::new("inner", DataType::Float32, false).into()),
956
            false,
957
        );
958
959
        let list2 = Field::new(
960
            "l2",
961
            DataType::List(Field::new("inner", DataType::Null, false).into()),
962
            true,
963
        );
964
965
        list1
966
            .try_merge(&list2)
967
            .expect("should widen inner field's type to nullable float");
968
        assert_eq!(
969
            Field::new(
970
                "l1",
971
                DataType::List(Field::new("inner", DataType::Float32, true).into()),
972
                true,
973
            ),
974
            list1
975
        );
976
977
        let mut large_list1 = Field::new(
978
            "ll1",
979
            DataType::LargeList(Field::new("inner", DataType::Float32, false).into()),
980
            false,
981
        );
982
983
        let large_list2 = Field::new(
984
            "ll2",
985
            DataType::LargeList(Field::new("inner", DataType::Null, false).into()),
986
            true,
987
        );
988
989
        large_list1
990
            .try_merge(&large_list2)
991
            .expect("should widen inner field's type to nullable float");
992
        assert_eq!(
993
            Field::new(
994
                "ll1",
995
                DataType::LargeList(Field::new("inner", DataType::Float32, true).into()),
996
                true,
997
            ),
998
            large_list1
999
        );
1000
    }
1001
1002
    #[test]
1003
    fn test_fields_with_dict_id() {
1004
        #[allow(deprecated)]
1005
        let dict1 = Field::new_dict(
1006
            "dict1",
1007
            DataType::Dictionary(DataType::Utf8.into(), DataType::Int32.into()),
1008
            false,
1009
            10,
1010
            false,
1011
        );
1012
        #[allow(deprecated)]
1013
        let dict2 = Field::new_dict(
1014
            "dict2",
1015
            DataType::Dictionary(DataType::Int32.into(), DataType::Int8.into()),
1016
            false,
1017
            20,
1018
            false,
1019
        );
1020
1021
        let field = Field::new(
1022
            "struct<dict1, list[struct<dict2, list[struct<dict1]>]>",
1023
            DataType::Struct(Fields::from(vec![
1024
                dict1.clone(),
1025
                Field::new(
1026
                    "list[struct<dict1, list[struct<dict2>]>]",
1027
                    DataType::List(Arc::new(Field::new(
1028
                        "struct<dict1, list[struct<dict2>]>",
1029
                        DataType::Struct(Fields::from(vec![
1030
                            dict1.clone(),
1031
                            Field::new(
1032
                                "list[struct<dict2>]",
1033
                                DataType::List(Arc::new(Field::new(
1034
                                    "struct<dict2>",
1035
                                    DataType::Struct(vec![dict2.clone()].into()),
1036
                                    false,
1037
                                ))),
1038
                                false,
1039
                            ),
1040
                        ])),
1041
                        false,
1042
                    ))),
1043
                    false,
1044
                ),
1045
            ])),
1046
            false,
1047
        );
1048
1049
        #[allow(deprecated)]
1050
        for field in field.fields_with_dict_id(10) {
1051
            assert_eq!(dict1, *field);
1052
        }
1053
        #[allow(deprecated)]
1054
        for field in field.fields_with_dict_id(20) {
1055
            assert_eq!(dict2, *field);
1056
        }
1057
    }
1058
1059
    fn get_field_hash(field: &Field) -> u64 {
1060
        let mut s = DefaultHasher::new();
1061
        field.hash(&mut s);
1062
        s.finish()
1063
    }
1064
1065
    #[test]
1066
    fn test_field_comparison_case() {
1067
        // dictionary-encoding properties not used for field comparison
1068
        #[allow(deprecated)]
1069
        let dict1 = Field::new_dict(
1070
            "dict1",
1071
            DataType::Dictionary(DataType::Utf8.into(), DataType::Int32.into()),
1072
            false,
1073
            10,
1074
            false,
1075
        );
1076
        #[allow(deprecated)]
1077
        let dict2 = Field::new_dict(
1078
            "dict1",
1079
            DataType::Dictionary(DataType::Utf8.into(), DataType::Int32.into()),
1080
            false,
1081
            20,
1082
            false,
1083
        );
1084
1085
        assert_eq!(dict1, dict2);
1086
        assert_eq!(get_field_hash(&dict1), get_field_hash(&dict2));
1087
1088
        #[allow(deprecated)]
1089
        let dict1 = Field::new_dict(
1090
            "dict0",
1091
            DataType::Dictionary(DataType::Utf8.into(), DataType::Int32.into()),
1092
            false,
1093
            10,
1094
            false,
1095
        );
1096
1097
        assert_ne!(dict1, dict2);
1098
        assert_ne!(get_field_hash(&dict1), get_field_hash(&dict2));
1099
    }
1100
1101
    #[test]
1102
    fn test_field_comparison_metadata() {
1103
        let f1 = Field::new("x", DataType::Binary, false).with_metadata(HashMap::from([
1104
            (String::from("k1"), String::from("v1")),
1105
            (String::from("k2"), String::from("v2")),
1106
        ]));
1107
        let f2 = Field::new("x", DataType::Binary, false).with_metadata(HashMap::from([
1108
            (String::from("k1"), String::from("v1")),
1109
            (String::from("k3"), String::from("v3")),
1110
        ]));
1111
        let f3 = Field::new("x", DataType::Binary, false).with_metadata(HashMap::from([
1112
            (String::from("k1"), String::from("v1")),
1113
            (String::from("k3"), String::from("v4")),
1114
        ]));
1115
1116
        assert!(f1.cmp(&f2).is_lt());
1117
        assert!(f2.cmp(&f3).is_lt());
1118
        assert!(f1.cmp(&f3).is_lt());
1119
    }
1120
1121
    #[test]
1122
    fn test_contains_reflexivity() {
1123
        let mut field = Field::new("field1", DataType::Float16, false);
1124
        field.set_metadata(HashMap::from([
1125
            (String::from("k0"), String::from("v0")),
1126
            (String::from("k1"), String::from("v1")),
1127
        ]));
1128
        assert!(field.contains(&field))
1129
    }
1130
1131
    #[test]
1132
    fn test_contains_transitivity() {
1133
        let child_field = Field::new("child1", DataType::Float16, false);
1134
1135
        let mut field1 = Field::new(
1136
            "field1",
1137
            DataType::Struct(Fields::from(vec![child_field])),
1138
            false,
1139
        );
1140
        field1.set_metadata(HashMap::from([(String::from("k1"), String::from("v1"))]));
1141
1142
        let mut field2 = Field::new("field1", DataType::Struct(Fields::default()), true);
1143
        field2.set_metadata(HashMap::from([(String::from("k2"), String::from("v2"))]));
1144
        field2.try_merge(&field1).unwrap();
1145
1146
        let mut field3 = Field::new("field1", DataType::Struct(Fields::default()), false);
1147
        field3.set_metadata(HashMap::from([(String::from("k3"), String::from("v3"))]));
1148
        field3.try_merge(&field2).unwrap();
1149
1150
        assert!(field2.contains(&field1));
1151
        assert!(field3.contains(&field2));
1152
        assert!(field3.contains(&field1));
1153
1154
        assert!(!field1.contains(&field2));
1155
        assert!(!field1.contains(&field3));
1156
        assert!(!field2.contains(&field3));
1157
    }
1158
1159
    #[test]
1160
    fn test_contains_nullable() {
1161
        let field1 = Field::new("field1", DataType::Boolean, true);
1162
        let field2 = Field::new("field1", DataType::Boolean, false);
1163
        assert!(field1.contains(&field2));
1164
        assert!(!field2.contains(&field1));
1165
    }
1166
1167
    #[test]
1168
    fn test_contains_must_have_same_fields() {
1169
        let child_field1 = Field::new("child1", DataType::Float16, false);
1170
        let child_field2 = Field::new("child2", DataType::Float16, false);
1171
1172
        let field1 = Field::new(
1173
            "field1",
1174
            DataType::Struct(vec![child_field1.clone()].into()),
1175
            true,
1176
        );
1177
        let field2 = Field::new(
1178
            "field1",
1179
            DataType::Struct(vec![child_field1, child_field2].into()),
1180
            true,
1181
        );
1182
1183
        assert!(!field1.contains(&field2));
1184
        assert!(!field2.contains(&field1));
1185
1186
        // UnionFields with different type ID
1187
        let field1 = Field::new(
1188
            "field1",
1189
            DataType::Union(
1190
                UnionFields::new(
1191
                    vec![1, 2],
1192
                    vec![
1193
                        Field::new("field1", DataType::UInt8, true),
1194
                        Field::new("field3", DataType::Utf8, false),
1195
                    ],
1196
                ),
1197
                UnionMode::Dense,
1198
            ),
1199
            true,
1200
        );
1201
        let field2 = Field::new(
1202
            "field1",
1203
            DataType::Union(
1204
                UnionFields::new(
1205
                    vec![1, 3],
1206
                    vec![
1207
                        Field::new("field1", DataType::UInt8, false),
1208
                        Field::new("field3", DataType::Utf8, false),
1209
                    ],
1210
                ),
1211
                UnionMode::Dense,
1212
            ),
1213
            true,
1214
        );
1215
        assert!(!field1.contains(&field2));
1216
1217
        // UnionFields with same type ID
1218
        let field1 = Field::new(
1219
            "field1",
1220
            DataType::Union(
1221
                UnionFields::new(
1222
                    vec![1, 2],
1223
                    vec![
1224
                        Field::new("field1", DataType::UInt8, true),
1225
                        Field::new("field3", DataType::Utf8, false),
1226
                    ],
1227
                ),
1228
                UnionMode::Dense,
1229
            ),
1230
            true,
1231
        );
1232
        let field2 = Field::new(
1233
            "field1",
1234
            DataType::Union(
1235
                UnionFields::new(
1236
                    vec![1, 2],
1237
                    vec![
1238
                        Field::new("field1", DataType::UInt8, false),
1239
                        Field::new("field3", DataType::Utf8, false),
1240
                    ],
1241
                ),
1242
                UnionMode::Dense,
1243
            ),
1244
            true,
1245
        );
1246
        assert!(field1.contains(&field2));
1247
    }
1248
1249
    #[cfg(feature = "serde")]
1250
    fn assert_binary_serde_round_trip(field: Field) {
1251
        let serialized = bincode::serialize(&field).unwrap();
1252
        let deserialized: Field = bincode::deserialize(&serialized).unwrap();
1253
        assert_eq!(field, deserialized)
1254
    }
1255
1256
    #[cfg(feature = "serde")]
1257
    #[test]
1258
    fn test_field_without_metadata_serde() {
1259
        let field = Field::new("name", DataType::Boolean, true);
1260
        assert_binary_serde_round_trip(field)
1261
    }
1262
1263
    #[cfg(feature = "serde")]
1264
    #[test]
1265
    fn test_field_with_empty_metadata_serde() {
1266
        let field = Field::new("name", DataType::Boolean, false).with_metadata(HashMap::new());
1267
1268
        assert_binary_serde_round_trip(field)
1269
    }
1270
1271
    #[cfg(feature = "serde")]
1272
    #[test]
1273
    fn test_field_with_nonempty_metadata_serde() {
1274
        let mut metadata = HashMap::new();
1275
        metadata.insert("hi".to_owned(), "".to_owned());
1276
        let field = Field::new("name", DataType::Boolean, false).with_metadata(metadata);
1277
1278
        assert_binary_serde_round_trip(field)
1279
    }
1280
}