Module registry

Module registry 

Source
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.Any detail 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 messages
  • Explainable: For converting types to/from ExtensionArgs
  • ExtensionRegistry: 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§

ExtensionAdapter 🔒
Type adapter that implements ExtensionConverter for any type T that implements both AnyConvertible and Explainable.
ExtensionRegistry
Registry for extension handlers

Enums§

ExtensionError
Errors during extension parsing, formatting, and argument extraction (runtime)
ExtensionType
Type of extension in the registry, used for namespace separation.
RegistrationError
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
ExtensionConverter 🔒
Internal trait that converts between ExtensionArgs and protobuf Any messages.