ferripfs-config 0.1.0

IPFS node configuration types, compatible with Kubo config format
Documentation
// Ported from: kubo/config/routing.go
// Kubo version: v0.39.0
// Original: https://github.com/ipfs/kubo/blob/v0.39.0/config/routing.go
//
// Original work: Copyright (c) Protocol Labs, Inc.
// Port: Copyright (c) 2026 ferripfs contributors
// SPDX-License-Identifier: MIT OR Apache-2.0

//! Routing configuration for DHT and delegated routing.

use crate::{Flag, OptionalString};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Default routing type
pub const DEFAULT_ROUTING_TYPE: &str = "auto";

/// Routing configuration section
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Routing {
    /// Routing type: "auto", "autoclient", "dht", "dhtclient", "dhtserver", "none", "custom"
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub r#type: Option<OptionalString>,

    /// Enable accelerated DHT client
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "AcceleratedDHTClient"
    )]
    pub accelerated_dht_client: Option<Flag>,

    /// Allow loopback addresses on LAN DHT
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "LoopbackAddressesOnLanDHT"
    )]
    pub loopback_addresses_on_lan_dht: Option<Flag>,

    /// Provider peer IDs to ignore
    #[serde(default)]
    pub ignore_providers: Vec<String>,

    /// Delegated router URLs
    #[serde(default)]
    pub delegated_routers: Vec<String>,

    /// Custom routers configuration
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub routers: Option<HashMap<String, RouterConfig>>,

    /// Method routing configuration
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub methods: Option<HashMap<String, MethodConfig>>,
}

/// Router configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct RouterConfig {
    /// Router type: "http", "dht", "sequential", "parallel"
    pub r#type: RouterType,

    /// Router-specific parameters
    pub parameters: serde_json::Value,
}

/// Router types
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum RouterType {
    Http,
    Dht,
    Sequential,
    Parallel,
}

/// DHT mode
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DhtMode {
    Server,
    Client,
    #[default]
    Auto,
}

/// Method routing configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct MethodConfig {
    /// Router name to use for this method
    pub router_name: String,
}

/// HTTP router parameters
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct HttpRouterParams {
    /// Endpoint URL
    pub endpoint: String,

    /// Maximum batch size for provide operations
    #[serde(default)]
    pub max_provide_batch_size: i32,

    /// Maximum concurrency for provide operations
    #[serde(default)]
    pub max_provide_concurrency: i32,
}

/// DHT router parameters
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct DhtRouterParams {
    /// DHT mode
    pub mode: DhtMode,

    /// Enable accelerated DHT client
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "AcceleratedDHTClient"
    )]
    pub accelerated_dht_client: Option<bool>,

    /// Use public IP network
    #[serde(default, rename = "PublicIPNetwork")]
    pub public_ip_network: bool,
}

impl Routing {
    /// Get the routing type with default
    pub fn routing_type(&self) -> &str {
        self.r#type
            .as_ref()
            .and_then(|t| t.as_str())
            .unwrap_or(DEFAULT_ROUTING_TYPE)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_routing_default() {
        let routing = Routing::default();
        assert_eq!(routing.routing_type(), "auto");
    }

    #[test]
    fn test_router_type_serialization() {
        let json = serde_json::to_string(&RouterType::Http).unwrap();
        assert_eq!(json, "\"http\"");
    }

    #[test]
    fn test_dht_mode_serialization() {
        let json = serde_json::to_string(&DhtMode::Server).unwrap();
        assert_eq!(json, "\"server\"");
    }
}