dns-update-lite 0.5.7

Dynamic DNS update (RFC 2136 and cloud) library for Rust. Lightweight fork of dns-update
Documentation
use crate::{DnsRecord, DnsRecordType, Error, IntoFqdn, NamedDnsRecord, utils::check_record_types};
use std::sync::{Arc, Mutex};

#[derive(Clone)]
pub struct InMemoryProvider {
    records: Arc<Mutex<Vec<NamedDnsRecord>>>,
}

impl InMemoryProvider {
    pub(crate) fn new(records: Arc<Mutex<Vec<NamedDnsRecord>>>) -> Self {
        Self { records }
    }

    pub(crate) async fn set_rrset(
        &self,
        name: impl IntoFqdn<'_>,
        record_type: DnsRecordType,
        _ttl: u32,
        records: Vec<DnsRecord>,
        _origin: impl IntoFqdn<'_>,
    ) -> crate::Result<()> {
        check_record_types(record_type, &records)?;
        let name = name.into_fqdn().into_owned();
        let mut store = self
            .records
            .lock()
            .map_err(|_| Error::Client("in-memory record store poisoned".to_string()))?;
        store.retain(|r| !(r.name == name && r.record.as_type() == record_type));
        for record in records {
            store.push(NamedDnsRecord {
                name: name.clone(),
                record,
            });
        }
        Ok(())
    }

    pub(crate) async fn add_to_rrset(
        &self,
        name: impl IntoFqdn<'_>,
        record_type: DnsRecordType,
        _ttl: u32,
        records: Vec<DnsRecord>,
        _origin: impl IntoFqdn<'_>,
    ) -> crate::Result<()> {
        check_record_types(record_type, &records)?;
        if records.is_empty() {
            return Ok(());
        }
        let name = name.into_fqdn().into_owned();
        let mut store = self
            .records
            .lock()
            .map_err(|_| Error::Client("in-memory record store poisoned".to_string()))?;
        for record in records {
            let already_present = store.iter().any(|r| r.name == name && r.record == record);
            if !already_present {
                store.push(NamedDnsRecord {
                    name: name.clone(),
                    record,
                });
            }
        }
        Ok(())
    }

    pub(crate) async fn remove_from_rrset(
        &self,
        name: impl IntoFqdn<'_>,
        record_type: DnsRecordType,
        records: Vec<DnsRecord>,
        _origin: impl IntoFqdn<'_>,
    ) -> crate::Result<()> {
        check_record_types(record_type, &records)?;
        if records.is_empty() {
            return Ok(());
        }
        let name = name.into_fqdn().into_owned();
        let mut store = self
            .records
            .lock()
            .map_err(|_| Error::Client("in-memory record store poisoned".to_string()))?;
        store.retain(|r| !(r.name == name && records.contains(&r.record)));
        Ok(())
    }

    pub(crate) async fn list_rrset(
        &self,
        _name: impl IntoFqdn<'_>,
        _record_type: DnsRecordType,
        _origin: impl IntoFqdn<'_>,
    ) -> crate::Result<Vec<DnsRecord>> {
        Err(Error::Unsupported(
            "InMemory does not support listing records".to_string(),
        ))
    }
}