Expand description
Extension Registry for Custom Substrait Extension Relations
This module provides a registry system for custom Substrait extension relations, allowing users to register their own extension types with custom parsing and textification logic.
§Overview
The extension registry allows users to:
- Register custom extension handlers for specific extension names
- Parse extension arguments/named arguments into
google.protobuf.Anydetail fields - Textify extension detail fields back into readable text format
- Support both compile-time and runtime extension registration
§Architecture
The system is built around several key traits:
AnyConvertible: For converting types to/from protobuf Any messagesExplainable: For converting types to/from ExtensionArgsExtensionRegistry: Registry for managing extension types
§Example Usage
use substrait_explain::extensions::{
Any, AnyConvertible, AnyRef, Explainable, ExtensionArgs, ExtensionError, ExtensionRegistry,
ExtensionRelationType, ExtensionValue,
};
// Define a custom extension type
struct CustomScanConfig {
path: String,
}
// Implement AnyConvertible for protobuf serialization
impl AnyConvertible for CustomScanConfig {
fn to_any(&self) -> Result<Any, ExtensionError> {
// For this example, we'll create a simple Any (protobuf details field) with the path
Ok(Any::new(Self::type_url(), self.path.as_bytes().to_vec()))
}
fn from_any<'a>(any: AnyRef<'a>) -> Result<Self, ExtensionError> {
// Deserialize from Any
let path = String::from_utf8(any.value.to_vec())
.map_err(|e| ExtensionError::Custom(format!("Invalid UTF-8: {}", e)))?;
Ok(CustomScanConfig { path })
}
fn type_url() -> String {
"type.googleapis.com/example.CustomScanConfig".to_string()
}
}
// Implement Explainable for text format conversion
impl Explainable for CustomScanConfig {
fn name() -> &'static str {
"ParquetScan"
}
fn from_args(args: &ExtensionArgs) -> Result<Self, ExtensionError> {
let mut extractor = args.extractor();
let path: &str = extractor.expect_named_arg("path")?;
extractor.check_exhausted()?;
Ok(CustomScanConfig {
path: path.to_string(),
})
}
fn to_args(&self) -> Result<ExtensionArgs, ExtensionError> {
let mut args = ExtensionArgs::new(ExtensionRelationType::Leaf);
args.named.insert(
"path".to_string(),
ExtensionValue::String(self.path.clone()),
);
Ok(args)
}
}
// Register the extension type
let mut registry = ExtensionRegistry::new();
registry.register_relation::<CustomScanConfig>().unwrap();Structs§
- Extension
Adapter 🔒 - Type adapter that implements ExtensionConverter for any type T that implements both AnyConvertible and Explainable.
- Extension
Registry - Registry for extension handlers
Enums§
- Extension
Error - Errors during extension parsing, formatting, and argument extraction (runtime)
- Extension
Type - Type of extension in the registry, used for namespace separation.
- Registration
Error - Errors during extension registration (setup phase)
Traits§
- AnyConvertible
- Trait for types that can be converted to/from protobuf Any messages. Note that this is already implemented for all prost::Message types. For custom types, implement this trait.
- Explainable
- Trait for types that participate in text explanations.
- Extension
- Extension
Converter 🔒 - Internal trait that converts between ExtensionArgs and protobuf Any messages.