apollo-configuration 0.4.0

A typed, friendly configuration system for Apollo products.
Documentation
//! Support for socket address types in configuration.

use std::borrow::Cow;

use derive_more::{Deref, Display, From, FromStr};
use schemars::JsonSchema;
use serde::de::Deserializer;
use serde::{Deserialize, Serialize};

use crate::Validate;

// =============================================================================
// SocketAddr
// =============================================================================

/// A socket address (v4 or v6) parsed from configuration.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deref, From, FromStr, Display)]
pub struct SocketAddr(std::net::SocketAddr);

impl<'de> Deserialize<'de> for SocketAddr {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        s.parse::<std::net::SocketAddr>()
            .map(Self)
            .map_err(serde::de::Error::custom)
    }
}

impl Serialize for SocketAddr {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.0.to_string().serialize(serializer)
    }
}

impl JsonSchema for SocketAddr {
    fn schema_name() -> Cow<'static, str> {
        Cow::Borrowed("SocketAddr")
    }

    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
        std::net::SocketAddr::json_schema(generator)
    }
}

impl Validate for SocketAddr {}

// =============================================================================
// SocketAddrV4
// =============================================================================

/// An IPv4 socket address parsed from configuration.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deref, From, FromStr, Display)]
pub struct SocketAddrV4(std::net::SocketAddrV4);

impl<'de> Deserialize<'de> for SocketAddrV4 {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        s.parse::<std::net::SocketAddrV4>()
            .map(Self)
            .map_err(serde::de::Error::custom)
    }
}

impl Serialize for SocketAddrV4 {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.0.to_string().serialize(serializer)
    }
}

impl JsonSchema for SocketAddrV4 {
    fn schema_name() -> Cow<'static, str> {
        Cow::Borrowed("SocketAddrV4")
    }

    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
        std::net::SocketAddrV4::json_schema(generator)
    }
}

impl Validate for SocketAddrV4 {}

// =============================================================================
// SocketAddrV6
// =============================================================================

/// An IPv6 socket address parsed from configuration.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deref, From, FromStr, Display)]
pub struct SocketAddrV6(std::net::SocketAddrV6);

impl<'de> Deserialize<'de> for SocketAddrV6 {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        s.parse::<std::net::SocketAddrV6>()
            .map(Self)
            .map_err(serde::de::Error::custom)
    }
}

impl Serialize for SocketAddrV6 {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.0.to_string().serialize(serializer)
    }
}

impl JsonSchema for SocketAddrV6 {
    fn schema_name() -> Cow<'static, str> {
        Cow::Borrowed("SocketAddrV6")
    }

    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
        std::net::SocketAddrV6::json_schema(generator)
    }
}

impl Validate for SocketAddrV6 {}