use std::path::PathBuf;
use crate::journal::journal_reader::{JournalReader, JournalReaderError};
use crate::messages::inter::rr_classes::RRClasses;
use crate::messages::inter::rr_types::RRTypes;
use crate::zone::rr_set::RRSet;
use crate::rr_data::inter::rr_data::RRData;
use crate::utils::fqdn_utils::{decode_fqdn, encode_fqdn};
use crate::utils::trie::trie::Trie;
use crate::zone::inter::zone_types::ZoneTypes;
#[derive(Debug, Clone)]
pub struct Zone {
_type: ZoneTypes,
class: RRClasses,
sets: Trie<Vec<RRSet>>,
journal_path: Option<PathBuf>
}
impl Default for Zone {
fn default() -> Self {
Self {
_type: Default::default(),
class: Default::default(),
sets: Trie::new(),
journal_path: None
}
}
}
impl Zone {
pub fn new(_type: ZoneTypes, class: RRClasses) -> Self {
Self {
_type,
class,
..Default::default()
}
}
pub fn new_with_jnl<P: Into<PathBuf>>(_type: ZoneTypes, class: RRClasses, journal_path: P) -> Self {
Self {
_type,
class,
journal_path: Some(journal_path.into()),
..Default::default()
}
}
pub fn set_type(&mut self, _type: ZoneTypes) {
self._type = _type;
}
pub fn get_type(&self) -> ZoneTypes {
self._type
}
pub fn get_class(&self) -> RRClasses {
self.class
}
pub fn is_authority(&self) -> bool {
self._type.eq(&ZoneTypes::Master) || self._type.eq(&ZoneTypes::Slave)
}
pub fn add_record(&mut self, query: &str, ttl: u32, data: Box<dyn RRData>) {
let key = encode_fqdn(query);
let _type = data.get_type();
match self.sets.get_mut(&key) {
Some(sets) => {
match sets
.iter_mut()
.find(|s| s.get_type().eq(&_type)) {
Some(set) => {
set.add_data(ttl, data);
}
None => {
let mut set = RRSet::new(_type, ttl);
set.add_data(ttl, data);
sets.push(set);
}
}
}
None => {
let mut set = RRSet::new(_type, ttl);
set.add_data(ttl, data);
self.sets.insert(key, vec![set]);
}
}
}
pub fn remove_record(&mut self, query: &str, data: Box<dyn RRData>) {
println!("REMOVE RECORD");
}
pub fn remove_set(&mut self, query: &str, _type: &RRTypes) -> Option<RRSet> {
let key = encode_fqdn(query);
let (removed, became_empty) = {
let sets = self.sets.get_mut(&key)?;
let idx = sets.iter().position(|s| s.get_type().eq(_type))?;
let removed = sets.swap_remove(idx);
(Some(removed), sets.is_empty())
};
if became_empty {
self.sets.remove(&key);
}
removed
}
pub fn remove_all_records(&mut self, query: &str, protected_types: &[RRTypes]) {
let key = encode_fqdn(query);
if match self.sets.get_mut(&key) {
Some(sets) => {
sets.retain(|set| protected_types.contains(&set.get_type()));
sets.is_empty()
}
None => false
} {
self.sets.remove(&key);
}
}
pub fn get_set(&self, query: &str, _type: &RRTypes) -> Option<&RRSet> {
self.sets.get(&encode_fqdn(query))?.iter().find(|s| s.get_type().eq(_type))
}
pub fn get_all_sets(&self, query: &str) -> Option<&Vec<RRSet>> {
self.sets.get(&encode_fqdn(query))
}
pub fn get_all_sets_recursive(&self) -> impl Iterator<Item = (String, &Vec<RRSet>)> {
self.sets.iter().map(|(key, records)| (decode_fqdn(key), records))
}
pub fn get_delegation_point(&self, query: &str) -> Option<(String, &RRSet)> {
match self.sets.get_shallowest(&encode_fqdn(query)) {
Some((name, sets)) => {
sets
.iter()
.find(|s| s.get_type().eq(&RRTypes::Ns))
.map(|set| (decode_fqdn(name), set))
}
None => None
}
}
pub fn get_journal_reader(&self) -> Result<JournalReader, JournalReaderError> {
JournalReader::open(self.journal_path.as_ref().unwrap())
}
pub fn set_journal_path<P: Into<PathBuf>>(&mut self, journal_path: P) {
self.journal_path = Some(journal_path.into());
}
pub fn get_journal_path(&self) -> Option<&PathBuf> {
self.journal_path.as_ref()
}
pub fn as_ref(&self) -> &Self {
self
}
pub fn as_mut(&mut self) -> &mut Self {
self
}
}