use serde::{Deserialize, Serialize};
use crate::{extension::ExtensionType, ArrowError, DataType};
#[derive(Debug, Clone, PartialEq)]
pub struct Opaque(OpaqueMetadata);
impl Opaque {
pub fn new(type_name: impl Into<String>, vendor_name: impl Into<String>) -> Self {
Self(OpaqueMetadata::new(type_name, vendor_name))
}
pub fn type_name(&self) -> &str {
self.0.type_name()
}
pub fn vendor_name(&self) -> &str {
self.0.vendor_name()
}
}
impl From<OpaqueMetadata> for Opaque {
fn from(value: OpaqueMetadata) -> Self {
Self(value)
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct OpaqueMetadata {
type_name: String,
vendor_name: String,
}
impl OpaqueMetadata {
pub fn new(type_name: impl Into<String>, vendor_name: impl Into<String>) -> Self {
OpaqueMetadata {
type_name: type_name.into(),
vendor_name: vendor_name.into(),
}
}
pub fn type_name(&self) -> &str {
&self.type_name
}
pub fn vendor_name(&self) -> &str {
&self.vendor_name
}
}
impl ExtensionType for Opaque {
const NAME: &'static str = "arrow.opaque";
type Metadata = OpaqueMetadata;
fn metadata(&self) -> &Self::Metadata {
&self.0
}
fn serialize_metadata(&self) -> Option<String> {
Some(serde_json::to_string(self.metadata()).expect("metadata serialization"))
}
fn deserialize_metadata(metadata: Option<&str>) -> Result<Self::Metadata, ArrowError> {
metadata.map_or_else(
|| {
Err(ArrowError::InvalidArgumentError(
"Opaque extension types requires metadata".to_owned(),
))
},
|value| {
serde_json::from_str(value).map_err(|e| {
ArrowError::InvalidArgumentError(format!(
"Opaque metadata deserialization failed: {e}"
))
})
},
)
}
fn supports_data_type(&self, _data_type: &DataType) -> Result<(), ArrowError> {
Ok(())
}
fn try_new(_data_type: &DataType, metadata: Self::Metadata) -> Result<Self, ArrowError> {
Ok(Self::from(metadata))
}
}
#[cfg(test)]
mod tests {
#[cfg(feature = "canonical_extension_types")]
use crate::extension::CanonicalExtensionType;
use crate::{
extension::{EXTENSION_TYPE_METADATA_KEY, EXTENSION_TYPE_NAME_KEY},
Field,
};
use super::*;
#[test]
fn valid() -> Result<(), ArrowError> {
let opaque = Opaque::new("name", "vendor");
let mut field = Field::new("", DataType::Null, false);
field.try_with_extension_type(opaque.clone())?;
assert_eq!(field.try_extension_type::<Opaque>()?, opaque);
#[cfg(feature = "canonical_extension_types")]
assert_eq!(
field.try_canonical_extension_type()?,
CanonicalExtensionType::Opaque(opaque)
);
Ok(())
}
#[test]
#[should_panic(expected = "Field extension type name missing")]
fn missing_name() {
let field = Field::new("", DataType::Null, false).with_metadata(
[(
EXTENSION_TYPE_METADATA_KEY.to_owned(),
r#"{ "type_name": "type", "vendor_name": "vendor" }"#.to_owned(),
)]
.into_iter()
.collect(),
);
field.extension_type::<Opaque>();
}
#[test]
#[should_panic(expected = "Opaque extension types requires metadata")]
fn missing_metadata() {
let field = Field::new("", DataType::Null, false).with_metadata(
[(EXTENSION_TYPE_NAME_KEY.to_owned(), Opaque::NAME.to_owned())]
.into_iter()
.collect(),
);
field.extension_type::<Opaque>();
}
#[test]
#[should_panic(
expected = "Opaque metadata deserialization failed: missing field `vendor_name`"
)]
fn invalid_metadata() {
let field = Field::new("", DataType::Null, false).with_metadata(
[
(EXTENSION_TYPE_NAME_KEY.to_owned(), Opaque::NAME.to_owned()),
(
EXTENSION_TYPE_METADATA_KEY.to_owned(),
r#"{ "type_name": "no-vendor" }"#.to_owned(),
),
]
.into_iter()
.collect(),
);
field.extension_type::<Opaque>();
}
}