arrow_schema/extension/canonical/
opaque.rs1use serde::{Deserialize, Serialize};
23
24use crate::{extension::ExtensionType, ArrowError, DataType};
25
26#[derive(Debug, Clone, PartialEq)]
38pub struct Opaque(OpaqueMetadata);
39
40impl Opaque {
41 pub fn new(type_name: impl Into<String>, vendor_name: impl Into<String>) -> Self {
43 Self(OpaqueMetadata::new(type_name, vendor_name))
44 }
45
46 pub fn type_name(&self) -> &str {
48 self.0.type_name()
49 }
50
51 pub fn vendor_name(&self) -> &str {
53 self.0.vendor_name()
54 }
55}
56
57impl From<OpaqueMetadata> for Opaque {
58 fn from(value: OpaqueMetadata) -> Self {
59 Self(value)
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
65pub struct OpaqueMetadata {
66 type_name: String,
68
69 vendor_name: String,
71}
72
73impl OpaqueMetadata {
74 pub fn new(type_name: impl Into<String>, vendor_name: impl Into<String>) -> Self {
76 OpaqueMetadata {
77 type_name: type_name.into(),
78 vendor_name: vendor_name.into(),
79 }
80 }
81
82 pub fn type_name(&self) -> &str {
84 &self.type_name
85 }
86
87 pub fn vendor_name(&self) -> &str {
89 &self.vendor_name
90 }
91}
92
93impl ExtensionType for Opaque {
94 const NAME: &'static str = "arrow.opaque";
95
96 type Metadata = OpaqueMetadata;
97
98 fn metadata(&self) -> &Self::Metadata {
99 &self.0
100 }
101
102 fn serialize_metadata(&self) -> Option<String> {
103 Some(serde_json::to_string(self.metadata()).expect("metadata serialization"))
104 }
105
106 fn deserialize_metadata(metadata: Option<&str>) -> Result<Self::Metadata, ArrowError> {
107 metadata.map_or_else(
108 || {
109 Err(ArrowError::InvalidArgumentError(
110 "Opaque extension types requires metadata".to_owned(),
111 ))
112 },
113 |value| {
114 serde_json::from_str(value).map_err(|e| {
115 ArrowError::InvalidArgumentError(format!(
116 "Opaque metadata deserialization failed: {e}"
117 ))
118 })
119 },
120 )
121 }
122
123 fn supports_data_type(&self, _data_type: &DataType) -> Result<(), ArrowError> {
124 Ok(())
126 }
127
128 fn try_new(_data_type: &DataType, metadata: Self::Metadata) -> Result<Self, ArrowError> {
129 Ok(Self::from(metadata))
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 #[cfg(feature = "canonical_extension_types")]
136 use crate::extension::CanonicalExtensionType;
137 use crate::{
138 extension::{EXTENSION_TYPE_METADATA_KEY, EXTENSION_TYPE_NAME_KEY},
139 Field,
140 };
141
142 use super::*;
143
144 #[test]
145 fn valid() -> Result<(), ArrowError> {
146 let opaque = Opaque::new("name", "vendor");
147 let mut field = Field::new("", DataType::Null, false);
148 field.try_with_extension_type(opaque.clone())?;
149 assert_eq!(field.try_extension_type::<Opaque>()?, opaque);
150 #[cfg(feature = "canonical_extension_types")]
151 assert_eq!(
152 field.try_canonical_extension_type()?,
153 CanonicalExtensionType::Opaque(opaque)
154 );
155 Ok(())
156 }
157
158 #[test]
159 #[should_panic(expected = "Field extension type name missing")]
160 fn missing_name() {
161 let field = Field::new("", DataType::Null, false).with_metadata(
162 [(
163 EXTENSION_TYPE_METADATA_KEY.to_owned(),
164 r#"{ "type_name": "type", "vendor_name": "vendor" }"#.to_owned(),
165 )]
166 .into_iter()
167 .collect(),
168 );
169 field.extension_type::<Opaque>();
170 }
171
172 #[test]
173 #[should_panic(expected = "Opaque extension types requires metadata")]
174 fn missing_metadata() {
175 let field = Field::new("", DataType::Null, false).with_metadata(
176 [(EXTENSION_TYPE_NAME_KEY.to_owned(), Opaque::NAME.to_owned())]
177 .into_iter()
178 .collect(),
179 );
180 field.extension_type::<Opaque>();
181 }
182
183 #[test]
184 #[should_panic(
185 expected = "Opaque metadata deserialization failed: missing field `vendor_name`"
186 )]
187 fn invalid_metadata() {
188 let field = Field::new("", DataType::Null, false).with_metadata(
189 [
190 (EXTENSION_TYPE_NAME_KEY.to_owned(), Opaque::NAME.to_owned()),
191 (
192 EXTENSION_TYPE_METADATA_KEY.to_owned(),
193 r#"{ "type_name": "no-vendor" }"#.to_owned(),
194 ),
195 ]
196 .into_iter()
197 .collect(),
198 );
199 field.extension_type::<Opaque>();
200 }
201}