use crate::keri::db::dbing::LMDBer;
use crate::keri::db::errors::DBError;
use crate::keri::db::subing::iodup::IoDupSuber;
use crate::keri::db::subing::on::OnSuberBase;
use crate::keri::db::subing::{SuberError, Utf8Codec, ValueCodec};
use std::sync::Arc;
use std::ops::Bound;
pub struct OnIoDupSuber<'db, C: ValueCodec = Utf8Codec> {
pub on_base: OnSuberBase<'db, C>,
pub io_dup_suber: IoDupSuber<'db, C>,
}
impl<'db, C: ValueCodec> OnIoDupSuber<'db, C> {
pub fn new(
db: Arc<&'db LMDBer>,
subkey: &str,
sep: Option<u8>,
verify: bool,
) -> Result<Self, SuberError> {
let on_base = OnSuberBase::new(db.clone(), subkey, sep, verify, Some(true))?;
let io_dup_suber = IoDupSuber::new(db, subkey, sep, verify)?;
Ok(Self {
on_base,
io_dup_suber,
})
}
pub fn add_on<K: AsRef<[u8]>, V: ?Sized + Clone + Into<Vec<u8>>>(
&self,
keys: &[K],
on: u32,
val: &V,
) -> Result<bool, SuberError> {
let key = self.on_base._tokey(keys);
let sval = self.on_base._ser(val)?;
self.on_base
.base
.db
.add_on_io_dup_val(
&self.on_base.base.sdb,
&key,
Some(on as u64),
&sval,
Some([self.on_base.base.sep]),
)
.map_err(SuberError::DBError)
}
pub fn append_on<K: AsRef<[u8]>, V: ?Sized + Clone + Into<Vec<u8>>>(
&self,
keys: &[K],
val: &V,
) -> Result<u64, SuberError> {
let key = self.on_base._tokey(keys);
let sval = self.on_base._ser(val)?;
self.on_base
.base
.db
.append_on_io_dup_val(
&self.on_base.base.sdb,
&key,
&sval,
Some([self.on_base.base.sep]),
)
.map_err(SuberError::DBError)
}
pub fn get_on<K: AsRef<[u8]>, R: TryFrom<Vec<u8>>>(
&self,
keys: &[K],
on: u32,
) -> Result<Vec<R>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
{
let key = self.on_base._tokey(keys);
let mut results = Vec::new();
self.on_base
.base
.db
.get_on_io_dup_val_iter(
&self.on_base.base.sdb,
Some(&key),
Some(on as u64),
Some([self.on_base.base.sep]),
|val| {
match self.on_base._des(&val) {
Ok(deserialized) => {
results.push(deserialized);
Ok(true) }
Err(e) => {
Err(DBError::ValueError(format!(
"Deserialization error: {:?}",
e
)))
}
}
},
)
.map_err(SuberError::DBError)?;
Ok(results)
}
pub fn rem_on<K: AsRef<[u8]>, V: ?Sized + Clone + Into<Vec<u8>>>(
&self,
keys: &[K],
on: u32,
val: Option<&V>,
) -> Result<bool, SuberError> {
let key = self.on_base._tokey(keys);
match val {
Some(v) => {
let sval = self.on_base._ser(v)?;
self.on_base
.base
.db
.del_on_io_dup_val(
&self.on_base.base.sdb,
&key,
Some(on as u64),
&sval,
Some([self.on_base.base.sep]),
)
.map_err(SuberError::DBError)
}
None => self
.on_base
.base
.db
.del_on_io_dup_vals(
&self.on_base.base.sdb,
&key,
Some(on as u64),
Some([self.on_base.base.sep]),
)
.map_err(SuberError::DBError),
}
}
pub fn get_on_iter<K: AsRef<[u8]>, R: TryFrom<Vec<u8>> + 'static>(
&self,
keys: &[K],
on: u32,
) -> Result<Box<dyn Iterator<Item = Result<R, SuberError>> + '_>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
SuberError: From<<R as TryFrom<Vec<u8>>>::Error>,
{
let key = self.on_base._tokey(keys);
let sep = self.on_base.base.sep;
let mut collector = Vec::new();
self.on_base
.base
.db
.get_on_io_dup_val_iter(
&self.on_base.base.sdb,
Some(&key),
Some(on as u64),
Some([sep]),
|val| {
collector.push(val);
Ok(true)
},
)
.map_err(SuberError::DBError)?;
let iter = collector.into_iter().map(move |val| {
let deserialized: R = self.on_base._des(&val)?;
Ok(deserialized)
});
Ok(Box::new(iter))
}
pub fn get_on_item_iter<K: AsRef<[u8]>, R: TryFrom<Vec<u8>> + 'static>(
&self,
keys: &[K],
on: u32,
) -> Result<Box<dyn Iterator<Item = Result<(Vec<Vec<u8>>, u64, R), SuberError>> + '_>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
SuberError: From<<R as TryFrom<Vec<u8>>>::Error>,
{
let key = self.on_base._tokey(keys);
let sep = self.on_base.base.sep;
let mut collector = Vec::new();
self.on_base
.base
.db
.get_on_io_dup_item_iter(
&self.on_base.base.sdb,
Some(&key),
Some(on as u64),
Some([sep]),
|k, o, v| {
collector.push((k.to_vec(), o, v.to_vec()));
Ok(true)
},
)
.map_err(SuberError::DBError)?;
let iter = collector.into_iter().map(move |(k, o, v)| {
let keys = self.on_base._tokeys(&k);
let deserialized: R = self.on_base._des(&v)?;
Ok((keys, o, deserialized))
});
Ok(Box::new(iter))
}
pub fn get_on_last_iter<K: AsRef<[u8]>, R: TryFrom<Vec<u8>> + 'static>(
&self,
keys: &[K],
on: u32,
) -> Result<Box<dyn Iterator<Item = Result<R, SuberError>> + '_>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
SuberError: From<<R as TryFrom<Vec<u8>>>::Error>,
{
let key = self.on_base._tokey(keys);
let sep = self.on_base.base.sep;
let mut collector = Vec::new();
self.on_base
.base
.db
.get_on_io_dup_last_val_iter(
&self.on_base.base.sdb,
Some(&key),
Some(on as u64),
Some([sep]),
|val| {
collector.push(val.to_vec());
Ok(true)
},
)
.map_err(SuberError::DBError)?;
let iter = collector
.into_iter()
.map(move |val| self.on_base._des(&val));
Ok(Box::new(iter))
}
pub fn get_on_last_item_iter<K: AsRef<[u8]>, R: TryFrom<Vec<u8>> + 'static>(
&self,
keys: &[K],
on: u32,
) -> Result<Box<dyn Iterator<Item = Result<(Vec<Vec<u8>>, u64, R), SuberError>> + '_>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
SuberError: From<<R as TryFrom<Vec<u8>>>::Error>,
{
let key = self.on_base._tokey(keys);
let sep = self.on_base.base.sep;
let mut collector = Vec::new();
self.on_base
.base
.db
.get_on_io_dup_last_item_iter(
&self.on_base.base.sdb,
Some(&key),
Some(on as u64),
Some([sep]),
|k, o, v| {
collector.push((k.to_vec(), o, v.to_vec()));
Ok(true)
},
)
.map_err(SuberError::DBError)?;
let iter = collector.into_iter().map(move |(k, o, v)| {
let keys = self.on_base._tokeys(&k);
let deserialized: R = self.on_base._des(&v)?;
Ok((keys, o, deserialized))
});
Ok(Box::new(iter))
}
pub fn get_on_back_iter<K: AsRef<[u8]>, R: TryFrom<Vec<u8>> + 'static>(
&self,
keys: &[K],
on: u32,
) -> Result<Box<dyn Iterator<Item = Result<R, SuberError>> + '_>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
SuberError: From<<R as TryFrom<Vec<u8>>>::Error>,
{
let key = self.on_base._tokey(keys);
let sep = self.on_base.base.sep;
let mut collector = Vec::new();
self.on_base
.base
.db
.get_on_io_dup_val_back_iter(
&self.on_base.base.sdb,
Some(&key),
Some(on as u64),
Some([sep]),
|val| {
collector.push(val.to_vec());
Ok(true)
},
)
.map_err(SuberError::DBError)?;
let iter = collector
.into_iter()
.map(move |val| self.on_base._des(&val));
Ok(Box::new(iter))
}
pub fn get_on_item_back_iter<K: AsRef<[u8]>, R: TryFrom<Vec<u8>> + 'static>(
&self,
keys: &[K],
on: u32,
) -> Result<Box<dyn Iterator<Item = Result<(Vec<Vec<u8>>, u64, R), SuberError>> + '_>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
SuberError: From<<R as TryFrom<Vec<u8>>>::Error>,
{
let key = self.on_base._tokey(keys);
let sep = self.on_base.base.sep;
let mut collector = Vec::new();
self.on_base
.base
.db
.get_on_io_dup_item_back_iter(
&self.on_base.base.sdb,
Some(&key),
Some(on as u64),
Some([sep]),
|k, o, v| {
collector.push((k.to_vec(), o, v.to_vec()));
Ok(true)
},
)
.map_err(SuberError::DBError)?;
let iter = collector.into_iter().map(move |(k, o, v)| {
let keys = self.on_base._tokeys(&k);
let deserialized: R = self.on_base._des(&v)?;
Ok((keys, o, deserialized))
});
Ok(Box::new(iter))
}
pub fn cnt_on<K: AsRef<[u8]>>(&self, keys: &[K], on: u32) -> Result<usize, SuberError> {
self.on_base.cnt_on(keys, on)
}
pub fn get_item_iter<K: AsRef<[u8]>>(
&self,
keys: &[K],
topive: bool,
) -> Result<Vec<(Vec<Vec<u8>>, Vec<u8>)>, SuberError> {
self.io_dup_suber.get_item_iter(keys, topive)
}
pub fn add<K: AsRef<[u8]>, V: ?Sized + Clone + Into<Vec<u8>>>(
&self,
keys: &[K],
val: &V,
) -> Result<bool, SuberError> {
self.io_dup_suber.add(keys, val)
}
pub fn get_last<K: AsRef<[u8]>, R: TryFrom<Vec<u8>>>(
&self,
keys: &[K],
) -> Result<Option<R>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
{
self.io_dup_suber.get_last(keys)
}
pub fn get_io_dup_val_last<K: AsRef<[u8]>, R: TryFrom<Vec<u8>>>(
&self,
keys: &[K],
) -> Result<Option<R>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
{
let key = self.on_base._tokey(keys);
match self
.on_base
.base
.db
.get_io_dup_val_last(&self.on_base.base.sdb, &key)
{
Ok(Some(val_bytes)) => {
match self.on_base._des(&val_bytes) {
Ok(deserialized) => Ok(Some(deserialized)),
Err(e) => Err(e),
}
}
Ok(None) => Ok(None),
Err(e) => Err(SuberError::DBError(e)),
}
}
pub fn get<K: AsRef<[u8]>, R: TryFrom<Vec<u8>>>(&self, keys: &[K]) -> Result<Vec<R>, SuberError>
where
<R as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
{
self.io_dup_suber.get(keys)
}
pub fn is_dupsort(&self) -> bool {
self.on_base.base.is_dupsort()
}
}
#[cfg(test)]
mod tests {
use crate::keri::db::dbing::keys::on_key;
use crate::keri::db::dbing::{LMDBer, LMDBerBuilder};
use crate::keri::db::subing::oniodup::OnIoDupSuber;
use crate::keri::db::subing::{SuberError, Utf8Codec};
use std::sync::Arc;
use tempfile::tempdir;
#[test]
fn test_on_iodup_suber() -> Result<(), SuberError> {
let temp_dir = tempdir().unwrap();
let _dir_path = temp_dir.path().to_path_buf();
let db = LMDBerBuilder::default()
.name("test")
.temp(true)
.build()
.unwrap();
assert_eq!(db.name(), "test");
assert!(db.opened());
let db_ref = Arc::new(&db);
let onsuber = OnIoDupSuber::<Utf8Codec>::new(db_ref, "bags.", None, false)?;
assert!(onsuber.is_dupsort());
let w = "Blue dog";
let x = "Green tree";
let y = "Red apple";
let z = "White snow";
assert!(onsuber.add_on(&["z"], 0, &w)?);
let bytes: Vec<Vec<u8>> = onsuber.get_on(&["z"], 0)?;
let vals: Vec<String> = bytes
.iter()
.map(|b| String::from_utf8(b.clone()).unwrap())
.collect();
assert_eq!(vals, vec![w.to_string()]);
assert!(onsuber.add_on(&["z"], 0, &x)?);
let bytes: Vec<Vec<u8>> = onsuber.get_on(&["z"], 0)?;
let vals: Vec<String> = bytes
.iter()
.map(|b| String::from_utf8(b.clone()).unwrap())
.collect();
assert_eq!(vals, vec![w.to_string(), x.to_string()]);
assert!(onsuber.add_on(&["z"], 1, &y)?);
let bytes: Vec<Vec<u8>> = onsuber.get_on(&["z"], 1)?;
let vals: Vec<String> = bytes
.iter()
.map(|b| String::from_utf8(b.clone()).unwrap())
.collect();
assert_eq!(vals, vec![y.to_string()]);
assert!(onsuber.add_on(&["z"], 1, &z)?);
let bytes: Vec<Vec<u8>> = onsuber.get_on(&["z"], 1)?;
let vals: Vec<String> = bytes
.iter()
.map(|b| String::from_utf8(b.clone()).unwrap())
.collect();
assert_eq!(vals, vec![y.to_string(), z.to_string()]);
assert_eq!(onsuber.cnt_on(&["z"], 0)?, 4);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["z"], 0)?; for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
let val_string = String::from_utf8(val).unwrap();
items.push((keys_vec, on, val_string));
}
assert_eq!(
items,
vec![
(vec!["z".to_string()], 0, "Blue dog".to_string()),
(vec!["z".to_string()], 0, "Green tree".to_string()),
(vec!["z".to_string()], 1, "Red apple".to_string()),
(vec!["z".to_string()], 1, "White snow".to_string())
]
);
assert!(onsuber.rem_on(&["z"], 0, Some(&w))?);
assert!(onsuber.rem_on(&["z"], 1, None::<&String>)?);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["z"], 0)?;
for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
let val_string = String::from_utf8(val).unwrap();
items.push((keys_vec, on, val_string));
}
assert_eq!(
items,
vec![(vec!["z".to_string()], 0, "Green tree".to_string())]
);
assert!(onsuber.rem_on(&["z"], 0, Some(&x))?);
assert_eq!(onsuber.cnt_on(&["z"], 0)?, 0);
assert_eq!(onsuber.append_on(&["a"], &w)?, 0);
assert_eq!(onsuber.append_on(&["a"], &x)?, 1);
assert_eq!(onsuber.append_on(&["a"], &y)?, 2);
assert_eq!(onsuber.append_on(&["a"], &z)?, 3);
assert_eq!(onsuber.cnt_on(&["a"], 2)?, 2);
assert_eq!(onsuber.cnt_on(&["a"], 4)?, 0);
assert_eq!(onsuber.cnt_on(&["a"], 0)?, 4);
let raw_items = onsuber.get_item_iter(
&["a"] as &[&str],
false, )?;
let items_strings = raw_items
.iter()
.map(|(keys, val)| {
let key_strings = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
(key_strings, String::from_utf8(val.clone()).unwrap())
})
.collect::<Vec<_>>();
assert_eq!(items_strings.len(), 4);
assert_eq!(items_strings[0].1, "Blue dog");
assert_eq!(items_strings[1].1, "Green tree");
assert_eq!(items_strings[2].1, "Red apple");
assert_eq!(items_strings[3].1, "White snow");
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<_, Vec<u8>>(&["a"], 0)?;
for val_result in val_iter {
let raw_bytes = val_result?;
let string_val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
vals.push(string_val);
}
assert_eq!(
vals,
vec![
"Blue dog".to_string(),
"Green tree".to_string(),
"Red apple".to_string(),
"White snow".to_string()
]
);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<_, Vec<u8>>(&["a"], 2)?;
for val_result in val_iter {
let raw_bytes = val_result?;
let string_val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
vals.push(string_val);
}
assert_eq!(
vals,
vec!["Red apple".to_string(), "White snow".to_string()]
);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["a"], 0)?;
for item_result in item_iter {
let (keys, on, raw_bytes) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
let val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
items.push((keys_vec, on, val));
}
assert_eq!(
items,
vec![
(vec!["a".to_string()], 0, "Blue dog".to_string()),
(vec!["a".to_string()], 1, "Green tree".to_string()),
(vec!["a".to_string()], 2, "Red apple".to_string()),
(vec!["a".to_string()], 3, "White snow".to_string())
]
);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["a"], 2)?;
for item_result in item_iter {
let (keys, on, raw_bytes) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
let val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
items.push((keys_vec, on, val));
}
assert_eq!(
items,
vec![
(vec!["a".to_string()], 2, "Red apple".to_string()),
(vec!["a".to_string()], 3, "White snow".to_string())
]
);
assert!(onsuber.add(&[on_key("b".as_bytes(), 0, None)], &w)?);
assert!(onsuber.add(&[on_key("b".as_bytes(), 1, None)], &x)?);
assert!(onsuber.add(&[on_key("bc".as_bytes(), 0, None)], &y)?);
assert!(onsuber.add(&[on_key("ac".as_bytes(), 0, None)], &z)?);
assert_eq!(onsuber.cnt_on(&["b"], 0)?, 2);
assert_eq!(onsuber.cnt_on(&["ac"], 2)?, 0);
assert_eq!(onsuber.cnt_on(&[""], 0)?, 8);
let mut items = Vec::new();
for item_result in onsuber.get_item_iter::<Vec<u8>>(&[] as &[Vec<u8>], false)? {
let (keys, raw_bytes) = item_result;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
let val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
items.push((keys_vec, val));
}
assert_eq!(items.len(), 8);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["b"], 0)?;
for item_result in item_iter {
let (keys, on, raw_bytes) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
let val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
items.push((keys_vec, on, val));
}
assert_eq!(
items,
vec![
(vec!["b".to_string()], 0, "Blue dog".to_string()),
(vec!["b".to_string()], 1, "Green tree".to_string())
]
);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<_, Vec<u8>>(&["b"], 0)?;
for val_result in val_iter {
let raw_bytes = val_result?;
let string_val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
vals.push(string_val);
}
assert_eq!(vals, vec!["Blue dog".to_string(), "Green tree".to_string()]);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<_, Vec<u8>>(&["b"], 0)?;
for val_result in val_iter {
let raw_bytes = val_result?;
let string_val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
vals.push(string_val);
}
assert_eq!(vals, vec!["Blue dog".to_string(), "Green tree".to_string()]);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["b"], 0)?;
for item_result in item_iter {
let (keys, on, raw_bytes) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
let val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
items.push((keys_vec, on, val));
}
assert_eq!(
items,
vec![
(vec!["b".to_string()], 0, "Blue dog".to_string()),
(vec!["b".to_string()], 1, "Green tree".to_string())
]
);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["b", ""], 0)?;
for item_result in item_iter {
let (keys, on, raw_bytes) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
let val = String::from_utf8(raw_bytes).expect("Invalid UTF-8 sequence");
items.push((keys_vec, on, val));
}
assert!(items.is_empty());
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<_, Vec<u8>>(&["b", ""], 0)?;
for val_result in val_iter {
vals.push(val_result?);
}
assert!(vals.is_empty());
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&[""], 0)?;
for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
items.push((keys_vec, on, val));
}
assert_eq!(items.len(), 8);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<_, Vec<u8>>(&[""], 0)?;
for val_result in val_iter {
vals.push(val_result?);
}
assert_eq!(vals.len(), 8);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<&str, Vec<u8>>(&[], 0)?;
for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
items.push((keys_vec, on, val));
}
assert_eq!(items.len(), 8);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<&str, Vec<u8>>(&[], 0)?;
for val_result in val_iter {
vals.push(val_result?);
}
assert_eq!(vals.len(), 8);
assert!(onsuber.add(&[on_key("a".as_bytes(), 0, None)], &z)?);
assert!(onsuber.add(&[on_key("a".as_bytes(), 1, None)], &y)?);
assert!(onsuber.add(&[on_key("a".as_bytes(), 2, None)], &x)?);
assert!(onsuber.add(&[on_key("a".as_bytes(), 3, None)], &w)?);
assert_eq!(onsuber.cnt_on(&["a"], 0)?, 8);
assert_eq!(onsuber.cnt_on(&["a"], 2)?, 4);
assert_eq!(onsuber.cnt_on(&["a"], 4)?, 0);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["a"], 0)?;
for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
items.push((keys_vec, on, val));
}
assert_eq!(items.len(), 8);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<_, Vec<u8>>(&["a"], 0)?;
for val_result in val_iter {
vals.push(val_result?);
}
assert_eq!(vals.len(), 8);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_back_iter::<_, Vec<u8>>(&["a"], 4)?;
for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
items.push((keys_vec, on, val));
}
assert_eq!(items.len(), 8);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_back_iter::<_, Vec<u8>>(&["a"], 4)?;
for val_result in val_iter {
vals.push(val_result?);
}
assert_eq!(vals.len(), 8);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["a"], 2)?;
for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
items.push((keys_vec, on, val));
}
assert_eq!(items.len(), 4);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_iter::<_, Vec<u8>>(&["a"], 2)?;
for val_result in val_iter {
vals.push(val_result?);
}
assert_eq!(vals.len(), 4);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_back_iter::<_, Vec<u8>>(&["a"], 1)?;
for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
items.push((keys_vec, on, val));
}
assert_eq!(items.len(), 4);
let mut vals = Vec::new();
let val_iter = onsuber.get_on_back_iter::<_, Vec<u8>>(&["a"], 1)?;
for val_result in val_iter {
vals.push(val_result?);
}
assert_eq!(vals.len(), 4);
assert_eq!(onsuber.append_on(&["a"], &x)?, 4);
assert_eq!(onsuber.cnt_on(&["a"], 0)?, 9);
assert!(onsuber.rem_on(&["a"], 1, None::<&String>)?);
assert!(!onsuber.rem_on(&["a"], 1, None::<&String>)?);
assert!(onsuber.rem_on(&["a"], 3, None::<&String>)?);
assert!(!onsuber.rem_on(&["a"], 3, None::<&String>)?);
assert_eq!(onsuber.cnt_on(&["a"], 0)?, 5);
let mut items = Vec::new();
let item_iter = onsuber.get_on_item_iter::<_, Vec<u8>>(&["a"], 0)?;
for item_result in item_iter {
let (keys, on, val) = item_result?;
let keys_vec = keys
.iter()
.map(|k| String::from_utf8(k.clone()).unwrap())
.collect::<Vec<_>>();
items.push((keys_vec, on, val));
}
assert_eq!(items.len(), 5);
Ok(())
}
}