arrow_schema/extension/canonical/mod.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//! Canonical extension types.
19//!
20//! The Arrow columnar format allows defining extension types so as to extend
21//! standard Arrow data types with custom semantics. Often these semantics will
22//! be specific to a system or application. However, it is beneficial to share
23//! the definitions of well-known extension types so as to improve
24//! interoperability between different systems integrating Arrow columnar data.
25//!
26//! <https://arrow.apache.org/docs/format/CanonicalExtensions.html#format-canonical-extensions>
27
28mod bool8;
29pub use bool8::Bool8;
30mod fixed_shape_tensor;
31pub use fixed_shape_tensor::{FixedShapeTensor, FixedShapeTensorMetadata};
32mod json;
33pub use json::{Json, JsonMetadata};
34mod opaque;
35pub use opaque::{Opaque, OpaqueMetadata};
36mod uuid;
37pub use uuid::Uuid;
38mod variable_shape_tensor;
39pub use variable_shape_tensor::{VariableShapeTensor, VariableShapeTensorMetadata};
40
41use crate::{ArrowError, Field};
42
43use super::ExtensionType;
44
45/// Canonical extension types.
46///
47/// <https://arrow.apache.org/docs/format/CanonicalExtensions.html#format-canonical-extensions>
48#[non_exhaustive]
49#[derive(Debug, Clone, PartialEq)]
50pub enum CanonicalExtensionType {
51 /// The extension type for `FixedShapeTensor`.
52 ///
53 /// <https://arrow.apache.org/docs/format/CanonicalExtensions.html#fixed-shape-tensor>
54 FixedShapeTensor(FixedShapeTensor),
55
56 /// The extension type for `VariableShapeTensor`.
57 ///
58 /// <https://arrow.apache.org/docs/format/CanonicalExtensions.html#variable-shape-tensor>
59 VariableShapeTensor(VariableShapeTensor),
60
61 /// The extension type for 'JSON'.
62 ///
63 /// <https://arrow.apache.org/docs/format/CanonicalExtensions.html#json>
64 Json(Json),
65
66 /// The extension type for `UUID`.
67 ///
68 /// <https://arrow.apache.org/docs/format/CanonicalExtensions.html#uuid>
69 Uuid(Uuid),
70
71 /// The extension type for `Opaque`.
72 ///
73 /// <https://arrow.apache.org/docs/format/CanonicalExtensions.html#opaque>
74 Opaque(Opaque),
75
76 /// The extension type for `Bool8`.
77 ///
78 /// <https://arrow.apache.org/docs/format/CanonicalExtensions.html#bit-boolean>
79 Bool8(Bool8),
80}
81
82impl TryFrom<&Field> for CanonicalExtensionType {
83 type Error = ArrowError;
84
85 fn try_from(value: &Field) -> Result<Self, Self::Error> {
86 // Canonical extension type names start with `arrow.`
87 match value.extension_type_name() {
88 // An extension type name with an `arrow.` prefix
89 Some(name) if name.starts_with("arrow.") => match name {
90 FixedShapeTensor::NAME => value
91 .try_extension_type::<FixedShapeTensor>()
92 .map(Into::into),
93 VariableShapeTensor::NAME => value
94 .try_extension_type::<VariableShapeTensor>()
95 .map(Into::into),
96 Json::NAME => value.try_extension_type::<Json>().map(Into::into),
97 Uuid::NAME => value.try_extension_type::<Uuid>().map(Into::into),
98 Opaque::NAME => value.try_extension_type::<Opaque>().map(Into::into),
99 Bool8::NAME => value.try_extension_type::<Bool8>().map(Into::into),
100 _ => Err(ArrowError::InvalidArgumentError(format!(
101 "Unsupported canonical extension type: {name}"
102 ))),
103 },
104 // Name missing the expected prefix
105 Some(name) => Err(ArrowError::InvalidArgumentError(format!(
106 "Field extension type name mismatch, expected a name with an `arrow.` prefix, found {name}"
107 ))),
108 // Name missing
109 None => Err(ArrowError::InvalidArgumentError(
110 "Field extension type name missing".to_owned(),
111 )),
112 }
113 }
114}
115
116impl From<FixedShapeTensor> for CanonicalExtensionType {
117 fn from(value: FixedShapeTensor) -> Self {
118 CanonicalExtensionType::FixedShapeTensor(value)
119 }
120}
121
122impl From<VariableShapeTensor> for CanonicalExtensionType {
123 fn from(value: VariableShapeTensor) -> Self {
124 CanonicalExtensionType::VariableShapeTensor(value)
125 }
126}
127
128impl From<Json> for CanonicalExtensionType {
129 fn from(value: Json) -> Self {
130 CanonicalExtensionType::Json(value)
131 }
132}
133
134impl From<Uuid> for CanonicalExtensionType {
135 fn from(value: Uuid) -> Self {
136 CanonicalExtensionType::Uuid(value)
137 }
138}
139
140impl From<Opaque> for CanonicalExtensionType {
141 fn from(value: Opaque) -> Self {
142 CanonicalExtensionType::Opaque(value)
143 }
144}
145
146impl From<Bool8> for CanonicalExtensionType {
147 fn from(value: Bool8) -> Self {
148 CanonicalExtensionType::Bool8(value)
149 }
150}