Skip to main content

Module registry

Module registry 

Source
Expand description

Registry for custom Substrait advanced extension payloads.

This module lets users register handlers for advanced extensions that carry google.protobuf.Any detail payloads: custom relation types, relation enhancements, and optimization hints.

§Overview

The extension registry allows users to:

  • Register custom extension handlers in relation, enhancement, or optimization namespaces
  • Parse extension arguments/named arguments into google.protobuf.Any detail fields
  • Textify extension detail fields back into readable text format
  • Keep each registered payload’s protobuf type URL associated with its canonical text-format name

§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,
};

// 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::default();
        args.insert("path", 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.
ExtensionProtoConvert
Conversion between extension arguments and Substrait protobuf values.