datasources 0.1.5

Async datasource interfaces, middleware, registry, and test doubles
Documentation
use crate::datasource_error::DatasourceError;
use crate::datasource_url_parser::DatasourceUrlParser;
use crate::driver_loader::DriverLoader;
use crate::provider_catalog::ProviderCatalog;
use crate::register;
use crate::result::Result;
use std::collections::HashMap;

pub fn defaults(options: HashMap<String, String>) -> Result<()> {
    register_listed(&options)
}

pub fn register_listed(options: &HashMap<String, String>) -> Result<()> {
    for name in installed(options)? {
        if crate::registered().iter().any(|existing| existing == &name) {
            continue;
        }
        let catalog = ProviderCatalog::default()
            .get(&name)
            .cloned()
            .ok_or_else(|| DatasourceError::not_installed(name.clone()))?;
        register(&name, DriverLoader::load(&catalog)?);
    }
    Ok(())
}

fn installed(options: &HashMap<String, String>) -> Result<Vec<String>> {
    let mut names = Vec::new();
    if let Some(value) = get(options, "INSTALLED_PROVIDERS") {
        for name in value.split(',') {
            let name = name.trim();
            if !name.is_empty() && !names.iter().any(|existing| existing == name) {
                names.push(name.to_string());
            }
        }
    }
    let Some(url) = get(options, "DATASOURCE_URL") else {
        return Ok(names);
    };
    let provider = DatasourceUrlParser::parse(url)
        .map(|parsed| parsed.provider)
        .ok_or_else(|| DatasourceError::message("DATASOURCE_URL has no provider"))?;
    if !names.iter().any(|existing| existing == &provider) {
        names.push(provider);
    }
    Ok(names)
}

fn get<'a>(options: &'a HashMap<String, String>, key: &str) -> Option<&'a str> {
    options
        .get(key)
        .map(|value| value.trim())
        .filter(|value| !value.is_empty())
}