sof 0.17.1

Solana Observer Framework for low-latency shred ingestion and plugin-driven transaction observation
Documentation
use super::*;
use std::net::ToSocketAddrs;
use thiserror::Error;

#[derive(Debug, Error)]
pub(super) enum ResolveSocketAddrError {
    #[error("invalid socket address or hostname `{value}`: {source}")]
    InvalidAddress {
        value: String,
        source: std::io::Error,
    },
    #[error("failed to resolve socket address or hostname `{value}`")]
    UnresolvedAddress { value: String },
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub(super) struct ResolvedSocketAddr(SocketAddr);

impl ResolvedSocketAddr {
    #[must_use]
    pub const fn into_inner(self) -> SocketAddr {
        self.0
    }
}

impl TryFrom<&str> for ResolvedSocketAddr {
    type Error = ResolveSocketAddrError;

    fn try_from(raw: &str) -> Result<Self, Self::Error> {
        if let Ok(addr) = SocketAddr::from_str(raw) {
            return Ok(Self(addr));
        }
        let mut resolved =
            raw.to_socket_addrs()
                .map_err(|source| ResolveSocketAddrError::InvalidAddress {
                    value: raw.to_owned(),
                    source,
                })?;
        resolved
            .next()
            .map(Self)
            .ok_or_else(|| ResolveSocketAddrError::UnresolvedAddress {
                value: raw.to_owned(),
            })
    }
}

pub(super) fn resolve_socket_addr(raw: &str) -> Result<SocketAddr, ResolveSocketAddrError> {
    ResolvedSocketAddr::try_from(raw).map(ResolvedSocketAddr::into_inner)
}