use crate::Database;
use super::{BADNODE, NodeId};
#[inline]
fn index_or_end(raw: u64) -> Option<u64> {
(raw != BADNODE).then_some(raw)
}
pub struct Altvals<'db> {
db: &'db Database,
id: NodeId,
tag: u32,
next: Option<u64>,
}
impl<'db> Altvals<'db> {
pub(crate) fn new(db: &'db Database, id: NodeId, tag: u32) -> Self {
let next = index_or_end(db.netnode_altfirst(id.get(), tag));
Self { db, id, tag, next }
}
}
impl std::fmt::Debug for Altvals<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Altvals")
.field("id", &self.id)
.field("tag", &self.tag)
.finish_non_exhaustive()
}
}
impl Iterator for Altvals<'_> {
type Item = (u64, u64);
fn next(&mut self) -> Option<Self::Item> {
let index = self.next?;
let value = self.db.netnode_altval(self.id.get(), index, self.tag);
self.next = index_or_end(self.db.netnode_altnext(self.id.get(), index, self.tag));
Some((index, value))
}
}
pub struct Supvals<'db> {
db: &'db Database,
id: NodeId,
tag: u32,
next: Option<u64>,
}
impl<'db> Supvals<'db> {
pub(crate) fn new(db: &'db Database, id: NodeId, tag: u32) -> Self {
let next = index_or_end(db.netnode_supfirst(id.get(), tag));
Self { db, id, tag, next }
}
}
impl std::fmt::Debug for Supvals<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Supvals")
.field("id", &self.id)
.field("tag", &self.tag)
.finish_non_exhaustive()
}
}
impl Iterator for Supvals<'_> {
type Item = (u64, Vec<u8>);
fn next(&mut self) -> Option<Self::Item> {
let index = self.next?;
let value = self
.db
.netnode_supval(self.id.get(), index, self.tag)
.unwrap_or_default();
self.next = index_or_end(self.db.netnode_supnext(self.id.get(), index, self.tag));
Some((index, value))
}
}
pub struct HashEntries<'db> {
db: &'db Database,
id: NodeId,
tag: u32,
next: Option<String>,
}
impl<'db> HashEntries<'db> {
pub(crate) fn new(db: &'db Database, id: NodeId, tag: u32) -> Self {
let next = db.netnode_hashfirst(id.get(), tag);
Self { db, id, tag, next }
}
}
impl std::fmt::Debug for HashEntries<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("HashEntries")
.field("id", &self.id)
.field("tag", &self.tag)
.finish_non_exhaustive()
}
}
impl Iterator for HashEntries<'_> {
type Item = (String, Vec<u8>);
fn next(&mut self) -> Option<Self::Item> {
let key = self.next.take()?;
let value = self
.db
.netnode_hashval(self.id.get(), &key, self.tag)
.unwrap_or_default();
self.next = self.db.netnode_hashnext(self.id.get(), &key, self.tag);
Some((key, value))
}
}
#[cfg(test)]
mod tests {
use assert2::assert;
use super::*;
use crate::Database;
#[test]
fn altvals_debug_renders_id_and_tag() {
let db = Database::new();
let iter = Altvals {
db: &db,
id: NodeId::try_new(1).unwrap(),
tag: u32::from(b'A'),
next: None,
};
let rendered = format!("{iter:?}");
assert!(rendered.contains("NodeId(0x1)"));
assert!(rendered.contains("tag: 65"));
}
#[test]
fn supvals_debug_renders_id_and_tag() {
let db = Database::new();
let iter = Supvals {
db: &db,
id: NodeId::try_new(1).unwrap(),
tag: u32::from(b'S'),
next: None,
};
let rendered = format!("{iter:?}");
assert!(rendered.contains("NodeId(0x1)"));
assert!(rendered.contains("tag: 83"));
}
#[test]
fn hash_entries_debug_renders_id_and_tag() {
let db = Database::new();
let iter = HashEntries {
db: &db,
id: NodeId::try_new(1).unwrap(),
tag: u32::from(b'H'),
next: None,
};
let rendered = format!("{iter:?}");
assert!(rendered.contains("NodeId(0x1)"));
assert!(rendered.contains("tag: 72"));
}
}