use crate::{
Cursor, MdbxError, ReadResult, TableObject, TableObjectOwned, TransactionKind,
error::mdbx_result,
tx::{
TxPtrAccess,
aliases::{IterDupKeys, IterDupVals},
iter::Iter,
},
};
use std::{borrow::Cow, ptr};
pub struct IterDup<'tx, 'cur, K: TransactionKind, Key = Cow<'tx, [u8]>, Value = Cow<'tx, [u8]>> {
inner: IterDupKeys<'tx, 'cur, K, Key, Value>,
}
impl<'tx, 'cur, K, Key, Value> core::fmt::Debug for IterDup<'tx, 'cur, K, Key, Value>
where
K: TransactionKind,
Key: core::fmt::Debug,
Value: core::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("IterDup").finish()
}
}
impl<'tx: 'cur, 'cur, K, Key, Value> IterDup<'tx, 'cur, K, Key, Value>
where
K: TransactionKind,
{
pub(crate) fn new(cursor: Cow<'cur, Cursor<'tx, K>>) -> Self {
IterDup { inner: IterDupKeys::new(cursor) }
}
pub(crate) fn from_ref(cursor: &'cur mut Cursor<'tx, K>) -> Self {
Self::new(Cow::Borrowed(cursor))
}
pub fn from_owned(cursor: Cursor<'tx, K>) -> Self {
Self::new(Cow::Owned(cursor))
}
pub(crate) fn new_with(cursor: Cow<'cur, Cursor<'tx, K>>, first: (Key, Value)) -> Self {
IterDup { inner: Iter::new_with(cursor, first) }
}
pub fn from_ref_with(cursor: &'cur mut Cursor<'tx, K>, first: (Key, Value)) -> Self {
Self::new_with(Cow::Borrowed(cursor), first)
}
pub fn new_end(cursor: Cow<'cur, Cursor<'tx, K>>) -> Self {
IterDup { inner: Iter::new_end(cursor) }
}
pub fn end_from_ref(cursor: &'cur mut Cursor<'tx, K>) -> Self {
Self::new_end(Cow::Borrowed(cursor))
}
pub fn end_from_owned(cursor: Cursor<'tx, K>) -> Self {
Self::new_end(Cow::Owned(cursor))
}
}
impl<'tx, 'cur, K, Key, Value> IterDup<'tx, 'cur, K, Key, Value>
where
K: TransactionKind,
Key: TableObject<'tx>,
Value: TableObject<'tx>,
{
pub fn borrow_next(&mut self) -> ReadResult<Option<IterDupVals<'tx, 'cur, K, Key, Value>>> {
let cursor_ptr = self.inner.cursor.as_ref().cursor();
let access = self.inner.cursor.access();
match self.inner.borrow_next()? {
Some((key, value)) => {
let db = self.inner.cursor.as_ref().db();
let dup_cursor = access.with_txn_ptr(move |_| unsafe {
let new_cursor = ffi::mdbx_cursor_create(ptr::null_mut());
let res = ffi::mdbx_cursor_copy(cursor_ptr, new_cursor);
mdbx_result(res)?;
Ok::<_, MdbxError>(Cursor::new_raw(access, new_cursor, db))
})?;
Ok(Some(IterDupVals::from_owned_with(dup_cursor, (key, value))))
}
None => Ok(None),
}
}
}
impl<'tx: 'cur, 'cur, K, Key, Value> IterDup<'tx, 'cur, K, Key, Value>
where
K: TransactionKind,
Key: TableObjectOwned,
Value: TableObjectOwned,
{
pub fn owned_next(&mut self) -> ReadResult<Option<IterDupVals<'tx, 'cur, K, Key, Value>>> {
self.borrow_next()
}
}
impl<'tx: 'cur, 'cur, K, Key, Value> Iterator for IterDup<'tx, 'cur, K, Key, Value>
where
K: TransactionKind,
Key: TableObjectOwned,
Value: TableObjectOwned,
{
type Item = ReadResult<IterDupVals<'tx, 'cur, K, Key, Value>>;
fn next(&mut self) -> Option<Self::Item> {
self.owned_next().transpose()
}
}