Skip to main content

arrow_schema/extension/canonical/
bool8.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5//! 8-bit Boolean
6//!
7//! <https://arrow.apache.org/docs/format/CanonicalExtensions.html#bit-boolean>
8
9use crate::{ArrowError, DataType, extension::ExtensionType};
10
11/// The extension type for `8-bit Boolean`.
12///
13/// Extension name: `arrow.bool8`.
14///
15/// The storage type of the extension is `Int8` where:
16/// - false is denoted by the value 0.
17/// - true can be specified using any non-zero value. Preferably 1.
18///
19/// <https://arrow.apache.org/docs/format/CanonicalExtensions.html#bit-boolean>
20#[derive(Debug, Default, Clone, Copy, PartialEq)]
21pub struct Bool8;
22
23impl ExtensionType for Bool8 {
24    const NAME: &'static str = "arrow.bool8";
25
26    type Metadata = &'static str;
27
28    fn metadata(&self) -> &Self::Metadata {
29        &""
30    }
31
32    fn serialize_metadata(&self) -> Option<String> {
33        Some(String::default())
34    }
35
36    fn deserialize_metadata(metadata: Option<&str>) -> Result<Self::Metadata, ArrowError> {
37        if metadata.is_some_and(str::is_empty) {
38            Ok("")
39        } else {
40            Err(ArrowError::InvalidArgumentError(
41                "Bool8 extension type expects an empty string as metadata".to_owned(),
42            ))
43        }
44    }
45
46    fn supports_data_type(&self, data_type: &DataType) -> Result<(), ArrowError> {
47        match data_type {
48            DataType::Int8 => Ok(()),
49            data_type => Err(ArrowError::InvalidArgumentError(format!(
50                "Bool8 data type mismatch, expected Int8, found {data_type}"
51            ))),
52        }
53    }
54
55    fn try_new(data_type: &DataType, _metadata: Self::Metadata) -> Result<Self, ArrowError> {
56        Self.supports_data_type(data_type).map(|()| Self)
57    }
58
59    fn validate(data_type: &DataType, _metadata: Self::Metadata) -> Result<(), ArrowError> {
60        Self.supports_data_type(data_type)
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    #[cfg(feature = "canonical_extension_types")]
67    use crate::extension::CanonicalExtensionType;
68    use crate::{
69        Field,
70        extension::{EXTENSION_TYPE_METADATA_KEY, EXTENSION_TYPE_NAME_KEY},
71    };
72
73    use super::*;
74
75    #[test]
76    fn valid() -> Result<(), ArrowError> {
77        let mut field = Field::new("", DataType::Int8, false);
78        field.try_with_extension_type(Bool8)?;
79        field.try_extension_type::<Bool8>()?;
80        #[cfg(feature = "canonical_extension_types")]
81        assert_eq!(
82            field.try_canonical_extension_type()?,
83            CanonicalExtensionType::Bool8(Bool8)
84        );
85
86        Ok(())
87    }
88
89    #[test]
90    #[should_panic(expected = "Extension type name missing")]
91    fn missing_name() {
92        let field = Field::new("", DataType::Int8, false)
93            .with_metadata([(EXTENSION_TYPE_METADATA_KEY, "")]);
94        field.extension_type::<Bool8>();
95    }
96
97    #[test]
98    #[should_panic(expected = "expected Int8, found Boolean")]
99    fn invalid_type() {
100        Field::new("", DataType::Boolean, false).with_extension_type(Bool8);
101    }
102
103    #[test]
104    #[should_panic(expected = "Bool8 extension type expects an empty string as metadata")]
105    fn missing_metadata() {
106        let field = Field::new("", DataType::Int8, false)
107            .with_metadata([(EXTENSION_TYPE_NAME_KEY, Bool8::NAME)]);
108        field.extension_type::<Bool8>();
109    }
110
111    #[test]
112    #[should_panic(expected = "Bool8 extension type expects an empty string as metadata")]
113    fn invalid_metadata() {
114        let field = Field::new("", DataType::Int8, false).with_metadata([
115            (EXTENSION_TYPE_NAME_KEY, Bool8::NAME),
116            (EXTENSION_TYPE_METADATA_KEY, "non-empty"),
117        ]);
118        field.extension_type::<Bool8>();
119    }
120}