#![doc = include_str!("../readme.md")]
#![warn(
missing_docs,
missing_copy_implementations,
missing_debug_implementations,
clippy::missing_safety_doc,
clippy::missing_errors_doc
)]
use std::net::IpAddr;
use builder::Builder;
use serde::{Deserialize, Serialize};
#[cfg(feature = "tokio")]
pub mod async_tokio;
pub mod builder;
pub mod error;
mod net;
pub mod sync;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct Udis {
name: String,
addr: IpAddr,
services: Vec<Service>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ServiceInfo {
pub name: String,
pub kind: String,
pub addr: IpAddr,
pub port: u16,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
enum Service {
Host { kind: String, port: u16 },
Search { kind: String },
}
impl Udis {
#[expect(clippy::new_ret_no_self)]
pub fn new<S: Into<String>>(name: S) -> Builder {
Builder::new(name.into())
}
pub(crate) fn build(name: String, addr: IpAddr, services: Vec<Service>) -> Self {
Self {
name,
addr,
services,
}
}
pub(crate) fn get_wanted_services<'a>(
&'a self,
peer: &'a Udis,
) -> impl Iterator<Item = &'a Service> {
self.services
.iter()
.filter(|s| peer.services.iter().any(|p| s.wanted_by(p)))
}
}
impl Service {
fn wanted_by(&self, peer_service: &Service) -> bool {
if let (
Service::Host { kind, .. },
Service::Search {
kind: peer_wanted_kind,
},
) = (self, peer_service)
{
kind == peer_wanted_kind
} else {
false
}
}
}