recoco-core 0.2.1

Recoco-core is the core library of Recoco; it's nearly identical to the main ReCoco crate, which is a simple wrapper around recoco-core and other sub-crates.
Documentation
// ReCoco is a Rust-only fork of CocoIndex, by [CocoIndex](https://CocoIndex)
// Original code from CocoIndex is copyrighted by CocoIndex
// SPDX-FileCopyrightText: 2025-2026 CocoIndex (upstream)
// SPDX-FileContributor: CocoIndex Contributors
//
// All modifications from the upstream for ReCoco are copyrighted by Knitli Inc.
// SPDX-FileCopyrightText: 2026 Knitli Inc. (ReCoco)
// SPDX-FileContributor: Adam Poulemanos <adam@knit.li>
//
// Both the upstream CocoIndex code and the ReCoco modifications are licensed under the Apache-2.0 License.
// SPDX-License-Identifier: Apache-2.0

use super::interface::ExecutorFactory;
use crate::prelude::*;
use recoco_utils::internal_error;
use std::collections::HashMap;
use std::sync::Arc;

pub struct ExecutorFactoryRegistry {
    source_factories: HashMap<String, Arc<dyn super::interface::SourceFactory + Send + Sync>>,
    function_factories:
        HashMap<String, Arc<dyn super::interface::SimpleFunctionFactory + Send + Sync>>,
    target_factories: HashMap<String, Arc<dyn super::interface::TargetFactory + Send + Sync>>,
    target_attachment_factories:
        HashMap<String, Arc<dyn super::interface::TargetAttachmentFactory + Send + Sync>>,
}

impl Default for ExecutorFactoryRegistry {
    fn default() -> Self {
        Self::new()
    }
}

impl ExecutorFactoryRegistry {
    pub fn new() -> Self {
        Self {
            source_factories: HashMap::new(),
            function_factories: HashMap::new(),
            target_factories: HashMap::new(),
            target_attachment_factories: HashMap::new(),
        }
    }

    pub fn register(&mut self, name: String, factory: ExecutorFactory) -> Result<()> {
        match factory {
            ExecutorFactory::Source(source_factory) => match self.source_factories.entry(name) {
                std::collections::hash_map::Entry::Occupied(entry) => Err(internal_error!(
                    "Source factory with name already exists: {}",
                    entry.key()
                )),
                std::collections::hash_map::Entry::Vacant(entry) => {
                    entry.insert(source_factory);
                    Ok(())
                }
            },
            ExecutorFactory::SimpleFunction(function_factory) => {
                match self.function_factories.entry(name) {
                    std::collections::hash_map::Entry::Occupied(entry) => Err(internal_error!(
                        "Function factory with name already exists: {}",
                        entry.key()
                    )),
                    std::collections::hash_map::Entry::Vacant(entry) => {
                        entry.insert(function_factory);
                        Ok(())
                    }
                }
            }
            ExecutorFactory::ExportTarget(target_factory) => {
                match self.target_factories.entry(name) {
                    std::collections::hash_map::Entry::Occupied(entry) => Err(internal_error!(
                        "Target factory with name already exists: {}",
                        entry.key()
                    )),
                    std::collections::hash_map::Entry::Vacant(entry) => {
                        entry.insert(target_factory);
                        Ok(())
                    }
                }
            }
            ExecutorFactory::TargetAttachment(target_attachment_factory) => {
                match self.target_attachment_factories.entry(name) {
                    std::collections::hash_map::Entry::Occupied(entry) => Err(internal_error!(
                        "Target attachment factory with name already exists: {}",
                        entry.key()
                    )),
                    std::collections::hash_map::Entry::Vacant(entry) => {
                        entry.insert(target_attachment_factory);
                        Ok(())
                    }
                }
            }
        }
    }

    pub fn get_source(
        &self,
        name: &str,
    ) -> Option<&Arc<dyn super::interface::SourceFactory + Send + Sync>> {
        self.source_factories.get(name)
    }

    pub fn get_function(
        &self,
        name: &str,
    ) -> Option<&Arc<dyn super::interface::SimpleFunctionFactory + Send + Sync>> {
        self.function_factories.get(name)
    }

    pub fn get_target(
        &self,
        name: &str,
    ) -> Option<&Arc<dyn super::interface::TargetFactory + Send + Sync>> {
        self.target_factories.get(name)
    }

    pub fn get_target_attachment(
        &self,
        name: &str,
    ) -> Option<&Arc<dyn super::interface::TargetAttachmentFactory + Send + Sync>> {
        self.target_attachment_factories.get(name)
    }
}