Repository: cberner/redb
Pull request #145 (2022-01-31 05:35:24)

Fix get_range() to work with integer types, along with other cleanups


Patch:
diff --git a/benches/common.rs b/benches/common.rs
index 22be213..fe2771f 100644
--- a/benches/common.rs
+++ b/benches/common.rs
@@ -67,16 +67,32 @@ impl<'a> BenchDatabase for RedbBenchDatabase<'a> {
     }
 }
 
+pub struct RedbBenchAccessGuard<'b> {
+    access_guard: redb::AccessGuard<'b, [u8]>,
+}
+
+impl<'b> RedbBenchAccessGuard<'b> {
+    fn new(access_guard: redb::AccessGuard<'b, [u8]>) -> Self {
+        Self { access_guard }
+    }
+}
+
+impl<'b> AsRef<[u8]> for RedbBenchAccessGuard<'b> {
+    fn as_ref(&self) -> &[u8] {
+        self.access_guard.to_value()
+    }
+}
+
 pub struct RedbBenchReadTransaction<'a> {
     _txn: redb::ReadOnlyDatabaseTransaction<'a>,
     table: redb::ReadOnlyTable<'a, [u8], [u8]>,
 }
 
 impl<'a, 'b> BenchReadTransaction<'b> for RedbBenchReadTransaction<'a> {
-    type Output = redb::AccessGuard<'b, [u8]>;
+    type Output = RedbBenchAccessGuard<'b>;
 
-    fn get(&'b self, key: &[u8]) -> Option<redb::AccessGuard<'b, [u8]>> {
-        self.table.get(key).unwrap()
+    fn get(&'b self, key: &[u8]) -> Option<RedbBenchAccessGuard<'b>> {
+        self.table.get(key).unwrap().map(RedbBenchAccessGuard::new)
     }
 
     fn exists_after(&'b self, key: &[u8]) -> bool {
diff --git a/src/table.rs b/src/table.rs
index 8b7dc68..e7926d4 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -2,6 +2,7 @@ use crate::error::Error;
 use crate::tree_store::{AccessGuardMut, BtreeEntry, BtreeRangeIter, PageNumber, Storage};
 use crate::types::{RedbKey, RedbValue, WithLifetime};
 use crate::AccessGuard;
+use std::borrow::Borrow;
 use std::cell::Cell;
 use std::marker::PhantomData;
 use std::ops::RangeBounds;
@@ -82,7 +83,7 @@ impl<'s, K: RedbKey + ?Sized, V: RedbValue + ?Sized> ReadableTable<K, V> for Tab
             .get::<K, V>(key.as_bytes().as_ref(), self.table_root.get())
     }
 
-    fn get_range<'a, T: RangeBounds<KR> + 'a, KR: AsRef<K>>(
+    fn get_range<'a, T: RangeBounds<KR> + 'a, KR: Borrow<K>>(
         &'a self,
         range: T,
     ) -> Result<RangeIter<T, KR, K, V>, Error> {
@@ -91,7 +92,7 @@ impl<'s, K: RedbKey + ?Sized, V: RedbValue + ?Sized> ReadableTable<K, V> for Tab
             .map(RangeIter::new)
     }
 
-    fn get_range_reversed<'a, T: RangeBounds<KR> + 'a, KR: AsRef<K>>(
+    fn get_range_reversed<'a, T: RangeBounds<KR> + 'a, KR: Borrow<K>>(
         &'a self,
         range: T,
     ) -> Result<RangeIter<T, KR, K, V>, Error> {
@@ -112,12 +113,12 @@ impl<'s, K: RedbKey + ?Sized, V: RedbValue + ?Sized> ReadableTable<K, V> for Tab
 pub trait ReadableTable<K: RedbKey + ?Sized, V: RedbValue + ?Sized> {
     fn get(&self, key: &K) -> Result<Option<AccessGuard<V>>, Error>;
 
-    fn get_range<'a, T: RangeBounds<KR> + 'a, KR: AsRef<K>>(
+    fn get_range<'a, T: RangeBounds<KR> + 'a, KR: Borrow<K>>(
         &'a self,
         range: T,
     ) -> Result<RangeIter<T, KR, K, V>, Error>;
 
-    fn get_range_reversed<'a, T: RangeBounds<KR> + 'a, KR: AsRef<K>>(
+    fn get_range_reversed<'a, T: RangeBounds<KR> + 'a, KR: Borrow<K>>(
         &'a self,
         range: T,
     ) -> Result<RangeIter<T, KR, K, V>, Error>;
@@ -156,7 +157,7 @@ impl<'s, K: RedbKey + ?Sized, V: RedbValue + ?Sized> ReadableTable<K, V>
             .get::<K, V>(key.as_bytes().as_ref(), self.table_root)
     }
 
-    fn get_range<'a, T: RangeBounds<KR> + 'a, KR: AsRef<K>>(
+    fn get_range<'a, T: RangeBounds<KR> + 'a, KR: Borrow<K>>(
         &'a self,
         range: T,
     ) -> Result<RangeIter<T, KR, K, V>, Error> {
@@ -165,7 +166,7 @@ impl<'s, K: RedbKey + ?Sized, V: RedbValue + ?Sized> ReadableTable<K, V>
             .map(RangeIter::new)
     }
 
-    fn get_range_reversed<'a, T: RangeBounds<KR> + 'a, KR: AsRef<K>>(
+    fn get_range_reversed<'a, T: RangeBounds<KR> + 'a, KR: Borrow<K>>(
         &'a self,
         range: T,
     ) -> Result<RangeIter<T, KR, K, V>, Error> {
@@ -186,7 +187,7 @@ impl<'s, K: RedbKey + ?Sized, V: RedbValue + ?Sized> ReadableTable<K, V>
 pub struct RangeIter<
     'a,
     T: RangeBounds<KR>,
-    KR: AsRef<K>,
+    KR: Borrow<K>,
     K: RedbKey + ?Sized + 'a,
     V: RedbValue + ?Sized + 'a,
 > {
@@ -196,7 +197,7 @@ pub struct RangeIter<
 impl<
         'a,
         T: RangeBounds<KR>,
-        KR: AsRef<K>,
+        KR: Borrow<K>,
         K: RedbKey + ?Sized + 'a,
         V: RedbValue + ?Sized + 'a,
     > RangeIter<'a, T, KR, K, V>
@@ -238,12 +239,6 @@ mod test {
     fn custom_ordering() {
         struct ReverseKey(Vec<u8>);
 
-        impl AsRef<ReverseKey> for ReverseKey {
-            fn as_ref(&self) -> &ReverseKey {
-                self
-            }
-        }
-
         impl RedbValue for ReverseKey {
             type View = RefLifetime<[u8]>;
             type ToBytes = RefAsBytesLifetime<[u8]>;
diff --git a/src/tree_store/btree_iters.rs b/src/tree_store/btree_iters.rs
index 9eef84a..fea73b1 100644
--- a/src/tree_store/btree_iters.rs
+++ b/src/tree_store/btree_iters.rs
@@ -4,6 +4,7 @@ use crate::tree_store::btree_iters::RangeIterState::{Internal, Leaf};
 use crate::tree_store::page_store::{Page, PageImpl, TransactionalMemory};
 use crate::tree_store::{BtreeEntry, PageNumber};
 use crate::types::{RedbKey, RedbValue};
+use std::borrow::Borrow;
 use std::collections::Bound;
 use std::marker::PhantomData;
 use std::ops::RangeBounds;
@@ -11,27 +12,27 @@ use std::ops::RangeBounds;
 fn bound_contains_key<
     'a,
     T: RangeBounds<KR>,
-    KR: AsRef<K> + ?Sized + 'a,
+    KR: Borrow<K> + ?Sized + 'a,
     K: RedbKey + ?Sized + 'a,
 >(
     range: &T,
     key: &[u8],
 ) -> bool {
     if let Bound::Included(start) = range.start_bound() {
-        if K::compare(key, start.as_ref().as_bytes().as_ref()).is_lt() {
+        if K::compare(key, start.borrow().as_bytes().as_ref()).is_lt() {
             return false;
         }
     } else if let Bound::Excluded(start) = range.start_bound() {
-        if K::compare(key, start.as_ref().as_bytes().as_ref()).is_le() {
+        if K::compare(key, start.borrow().as_bytes().as_ref()).is_le() {
             return false;
         }
     }
     if let Bound::Included(end) = range.end_bound() {
-        if K::compare(key, end.as_ref().as_bytes().as_ref()).is_gt() {
+        if K::compare(key, end.borrow().as_bytes().as_ref()).is_gt() {
             return false;
         }
     } else if let Bound::Excluded(end) = range.end_bound() {
-        if K::compare(key, end.as_ref().as_bytes().as_ref()).is_ge() {
+        if K::compare(key, end.borrow().as_bytes().as_ref()).is_ge() {
             return false;
         }
     }
@@ -224,7 +225,7 @@ pub(in crate) fn page_numbers_iter_start_state(page: PageImpl) -> RangeIterState
 pub struct BtreeRangeIter<
     'a,
     T: RangeBounds<KR>,
-    KR: AsRef<K> + ?Sized + 'a,
+    KR: Borrow<K> + ?Sized + 'a,
     K: RedbKey + ?Sized + 'a,
     V: RedbValue + ?Sized + 'a,
 > {
@@ -243,7 +244,7 @@ pub struct BtreeRangeIter<
 impl<
         'a,
         T: RangeBounds<KR>,
-        KR: AsRef<K> + ?Sized + 'a,
+        KR: Borrow<K> + ?Sized + 'a,
         K: RedbKey + ?Sized + 'a,
         V: RedbValue + ?Sized + 'a,
     > BtreeRangeIter<'a, T, KR, K, V>
@@ -302,21 +303,21 @@ impl<
                     #[allow(clippy::collapsible_else_if)]
                     if self.reversed {
                         if let Bound::Included(start) = self.query_range.start_bound() {
-                            if K::compare(entry.key(), start.as_ref().as_bytes().as_ref()).is_lt() {
+                            if K::compare(entry.key(), start.borrow().as_bytes().as_ref()).is_lt() {
                                 self.next = None;
                             }
                         } else if let Bound::Excluded(start) = self.query_range.start_bound() {
-                            if K::compare(entry.key(), start.as_ref().as_bytes().as_ref()).is_le() {
+                            if K::compare(entry.key(), start.borrow().as_bytes().as_ref()).is_le() {
                                 self.next = None;
                             }
                         }
                     } else {
                         if let Bound::Included(end) = self.query_range.end_bound() {
-                            if K::compare(entry.key(), end.as_ref().as_bytes().as_ref()).is_gt() {
+                            if K::compare(entry.key(), end.borrow().as_bytes().as_ref()).is_gt() {
                                 self.next = None;
                             }
                         } else if let Bound::Excluded(end) = self.query_range.end_bound() {
-                            if K::compare(entry.key(), end.as_ref().as_bytes().as_ref()).is_ge() {
+                            if K::compare(entry.key(), end.borrow().as_bytes().as_ref()).is_ge() {
                                 self.next = None;
                             }
                         }
diff --git a/src/tree_store/storage.rs b/src/tree_store/storage.rs
index 7431b11..bc18344 100644
--- a/src/tree_store/storage.rs
+++ b/src/tree_store/storage.rs
@@ -10,6 +10,7 @@ use crate::tree_store::{AccessGuardMut, BtreeEntry, BtreeRangeIter};
 use crate::types::{RedbKey, RedbValue, WithLifetime};
 use crate::Error;
 use memmap2::MmapRaw;
+use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
 use std::cmp::{max, min};
 use std::collections::{BTreeSet, Bound};
@@ -232,7 +233,7 @@ impl Storage {
         root_page: Option<PageNumber>,
     ) -> Result<Option<TableDefinition>, Error> {
         if let Some(found) = self.get::<[u8], [u8]>(name, root_page)? {
-            let definition = TableDefinition::from_bytes(found.as_ref());
+            let definition = TableDefinition::from_bytes(found.to_value());
             if definition.get_type() != table_type {
                 return Err(Error::TableTypeMismatch(format!(
                     "{:?} is not of type {:?}",
@@ -590,7 +591,7 @@ impl Storage {
     pub(in crate) fn get_range<
         'a,
         T: RangeBounds<KR>,
-        KR: AsRef<K> + ?Sized + 'a,
+        KR: Borrow<K> + ?Sized + 'a,
         K: RedbKey + ?Sized + 'a,
         V: RedbValue + ?Sized + 'a,
     >(
@@ -604,7 +605,7 @@ impl Storage {
                     let start_state = find_iter_start::<K>(
                         self.mem.get_page(root),
                         None,
-                        k.as_ref().as_bytes().as_ref(),
+                        k.borrow().as_bytes().as_ref(),
                         &self.mem,
                     );
                     Ok(BtreeRangeIter::new(start_state, range, &self.mem))
@@ -623,7 +624,7 @@ impl Storage {
     pub(in crate) fn get_range_reversed<
         'a,
         T: RangeBounds<KR>,
-        KR: AsRef<K> + ?Sized + 'a,
+        KR: Borrow<K> + ?Sized + 'a,
         K: RedbKey + ?Sized + 'a,
         V: RedbValue + ?Sized + 'a,
     >(
@@ -637,7 +638,7 @@ impl Storage {
                     let start_state = find_iter_start_reversed::<K>(
                         self.mem.get_page(root),
                         None,
-                        k.as_ref().as_bytes().as_ref(),
+                        k.borrow().as_bytes().as_ref(),
                         &self.mem,
                     );
                     Ok(BtreeRangeIter::new_reversed(start_state, range, &self.mem))
@@ -694,9 +695,3 @@ impl<'a, V: RedbValue + ?Sized> AccessGuard<'a, V> {
         V::from_bytes(&self.page.memory()[self.offset..(self.offset + self.len)])
     }
 }
-
-impl<'a> AsRef<[u8]> for AccessGuard<'a, [u8]> {
-    fn as_ref(&self) -> &[u8] {
-        &self.page.memory()[self.offset..(self.offset + self.len)]
-    }
-}


Test patch:
diff --git a/tests/basic_tests.rs b/tests/basic_tests.rs
index 620235c..fe416d4 100644
--- a/tests/basic_tests.rs
+++ b/tests/basic_tests.rs
@@ -1,4 +1,5 @@
-use redb::{Database, Error, ReadOnlyTable, ReadableTable, Table};
+use redb::{Database, Error, RangeIter, ReadOnlyTable, ReadableTable, Table};
+use std::ops::{Range, RangeFull};
 use tempfile::NamedTempFile;
 
 #[test]
@@ -33,9 +34,9 @@ fn multiple_tables() {
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"1").unwrap();
     let table2: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"2").unwrap();
     assert_eq!(table.len().unwrap(), 1);
-    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().to_value());
     assert_eq!(table2.len().unwrap(), 1);
-    assert_eq!(b"world2", table2.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"world2", table2.get(b"hello").unwrap().unwrap().to_value());
 }
 
 #[test]
@@ -61,7 +62,7 @@ fn abort() {
     let write_txn = db.begin_write().unwrap();
     let mut table: Table<[u8], [u8]> = write_txn.open_table(b"x").unwrap();
     table.insert(b"hello", b"aborted").unwrap();
-    assert_eq!(b"aborted", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"aborted", table.get(b"hello").unwrap().unwrap().to_value());
     write_txn.abort().unwrap();
 
     let read_txn = db.begin_read().unwrap();
@@ -75,7 +76,7 @@ fn abort() {
 
     let read_txn = db.begin_read().unwrap();
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
-    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().to_value());
     assert_eq!(table.len().unwrap(), 1);
 }
 
@@ -90,7 +91,7 @@ fn insert_overwrite() {
 
     let read_txn = db.begin_read().unwrap();
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
-    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().to_value());
 
     let write_txn = db.begin_write().unwrap();
     let mut table: Table<[u8], [u8]> = write_txn.open_table(b"x").unwrap();
@@ -99,7 +100,10 @@ fn insert_overwrite() {
 
     let read_txn = db.begin_read().unwrap();
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
-    assert_eq!(b"replaced", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(
+        b"replaced",
+        table.get(b"hello").unwrap().unwrap().to_value()
+    );
 }
 
 #[test]
@@ -116,7 +120,7 @@ fn insert_reserve() {
 
     let read_txn = db.begin_read().unwrap();
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
-    assert_eq!(value, table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(value, table.get(b"hello").unwrap().unwrap().to_value());
 }
 
 #[test]
@@ -131,7 +135,7 @@ fn delete() {
 
     let read_txn = db.begin_read().unwrap();
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
-    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().to_value());
     assert_eq!(table.len().unwrap(), 2);
 
     let write_txn = db.begin_write().unwrap();
@@ -160,7 +164,7 @@ fn no_dirty_reads() {
 
     let read_txn = db.begin_read().unwrap();
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
-    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().to_value());
 }
 
 #[test]
@@ -174,7 +178,7 @@ fn read_isolation() {
 
     let read_txn = db.begin_read().unwrap();
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
-    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().to_value());
 
     let write_txn = db.begin_write().unwrap();
     let mut write_table: Table<[u8], [u8]> = write_txn.open_table(b"x").unwrap();
@@ -186,11 +190,17 @@ fn read_isolation() {
     let read_txn2 = db.begin_read().unwrap();
     let table2: ReadOnlyTable<[u8], [u8]> = read_txn2.open_table(b"x").unwrap();
     assert!(table2.get(b"hello").unwrap().is_none());
-    assert_eq!(b"world2", table2.get(b"hello2").unwrap().unwrap().as_ref());
-    assert_eq!(b"world3", table2.get(b"hello3").unwrap().unwrap().as_ref());
+    assert_eq!(
+        b"world2",
+        table2.get(b"hello2").unwrap().unwrap().to_value()
+    );
+    assert_eq!(
+        b"world3",
+        table2.get(b"hello3").unwrap().unwrap().to_value()
+    );
     assert_eq!(table2.len().unwrap(), 2);
 
-    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().as_ref());
+    assert_eq!(b"world", table.get(b"hello").unwrap().unwrap().to_value());
     assert!(table.get(b"hello2").unwrap().is_none());
     assert!(table.get(b"hello3").unwrap().is_none());
     assert_eq!(table.len().unwrap(), 1);
@@ -224,11 +234,11 @@ fn i128_type() {
     let read_txn = db.begin_read().unwrap();
     let table: ReadOnlyTable<i128, i128> = read_txn.open_table(b"x").unwrap();
     assert_eq!(-2, table.get(&-1).unwrap().unwrap().to_value());
-    // TODO: enable this test
-    // let mut iter: RangeIter<RangeFull, i128, i128, i128> = table.get_range(..).unwrap();
-    // for i in -11..10 {
-    //     assert_eq!(iter.next().unwrap().1, i);
-    // }
+    let mut iter: RangeIter<RangeFull, i128, i128, i128> = table.get_range(..).unwrap();
+    for i in -11..10 {
+        assert_eq!(iter.next().unwrap().1, i);
+    }
+    assert!(iter.next().is_none());
 }
 
 #[test]
@@ -244,3 +254,85 @@ fn f32_type() {
     let table: ReadOnlyTable<u8, f32> = read_txn.open_table(b"x").unwrap();
     assert_eq!(0.3, table.get(&0).unwrap().unwrap().to_value());
 }
+
+#[test]
+fn owned_get_signatures() {
+    let tmpfile: NamedTempFile = NamedTempFile::new().unwrap();
+    let db = unsafe { Database::open(tmpfile.path(), 1024 * 1024).unwrap() };
+    let write_txn = db.begin_write().unwrap();
+    let mut table: Table<u32, u32> = write_txn.open_table(b"x").unwrap();
+    for i in 0..10 {
+        table.insert(&i, &(i + 1)).unwrap();
+    }
+    write_txn.commit().unwrap();
+
+    let read_txn = db.begin_read().unwrap();
+    let table: ReadOnlyTable<u32, u32> = read_txn.open_table(b"x").unwrap();
+
+    assert_eq!(2, table.get(&1).unwrap().unwrap().to_value());
+
+    let mut iter: RangeIter<RangeFull, u32, u32, u32> = table.get_range(..).unwrap();
+    for i in 0..10 {
+        assert_eq!(iter.next().unwrap().1, i + 1);
+    }
+    assert!(iter.next().is_none());
+    let mut iter: RangeIter<Range<u32>, u32, u32, u32> = table.get_range(0..10).unwrap();
+    for i in 0..10 {
+        assert_eq!(iter.next().unwrap().1, i + 1);
+    }
+    assert!(iter.next().is_none());
+    let mut iter: RangeIter<Range<&u32>, u32, u32, u32> = table.get_range(&0..&10).unwrap();
+    for i in 0..10 {
+        assert_eq!(iter.next().unwrap().1, i + 1);
+    }
+    assert!(iter.next().is_none());
+}
+
+#[test]
+fn ref_get_signatures() {
+    let tmpfile: NamedTempFile = NamedTempFile::new().unwrap();
+    let db = unsafe { Database::open(tmpfile.path(), 1024 * 1024).unwrap() };
+    let write_txn = db.begin_write().unwrap();
+    let mut table: Table<[u8], [u8]> = write_txn.open_table(b"x").unwrap();
+    for i in 0..10 {
+        table.insert(&[i], &[i + 1]).unwrap();
+    }
+    write_txn.commit().unwrap();
+
+    let read_txn = db.begin_read().unwrap();
+    let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
+
+    let zero = vec![0u8];
+    assert_eq!(&[1], table.get(&[0]).unwrap().unwrap().to_value());
+    assert_eq!(&[1], table.get(b"\0").unwrap().unwrap().to_value());
+    assert_eq!(&[1], table.get(&zero).unwrap().unwrap().to_value());
+
+    let start = vec![0u8];
+    let end = vec![10u8];
+    let mut iter: RangeIter<RangeFull, &[u8], [u8], [u8]> = table.get_range(..).unwrap();
+    for i in 0..10 {
+        assert_eq!(iter.next().unwrap().1, &[i + 1]);
+    }
+    assert!(iter.next().is_none());
+
+    let mut iter: RangeIter<Range<&[u8]>, &[u8], [u8], [u8]> =
+        table.get_range(start.as_slice()..&end).unwrap();
+    for i in 0..10 {
+        assert_eq!(iter.next().unwrap().1, &[i + 1]);
+    }
+    assert!(iter.next().is_none());
+
+    let mut iter = table.get_range(start..end).unwrap();
+    for i in 0..10 {
+        assert_eq!(iter.next().unwrap().1, &[i + 1]);
+    }
+    assert!(iter.next().is_none());
+
+    let mut iter = table
+        .get_range([0u8].as_slice()..[10u8].as_slice())
+        .unwrap();
+    for i in 0..10 {
+        assert_eq!(iter.next().unwrap().1, &[i + 1]);
+    }
+    assert!(iter.next().is_none());
+}
diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs
index f89bba3..6783130 100644
--- a/tests/integration_tests.rs
+++ b/tests/integration_tests.rs
@@ -70,7 +70,7 @@ fn non_durable_commit_persistence() {
         for i in &key_order {
             let (key, value) = &pairs[*i % pairs.len()];
             let result = &table.get(key).unwrap().unwrap();
-            assert_eq!(result.as_ref(), value);
+            assert_eq!(result.to_value(), value);
         }
     }
 }
@@ -106,7 +106,7 @@ fn persistence() {
         for i in &key_order {
             let (key, value) = &pairs[*i % pairs.len()];
             let result = &table.get(key).unwrap().unwrap();
-            assert_eq!(result.as_ref(), value);
+            assert_eq!(result.to_value(), value);
         }
     }
 }
@@ -383,7 +383,7 @@ fn non_durable_read_isolation() {
     let read_table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
     assert_eq!(
         b"world",
-        read_table.get(b"hello").unwrap().unwrap().as_ref()
+        read_table.get(b"hello").unwrap().unwrap().to_value()
     );
 
     let write_txn = db.begin_write().unwrap();
@@ -398,17 +398,17 @@ fn non_durable_read_isolation() {
     assert!(read_table2.get(b"hello").unwrap().is_none());
     assert_eq!(
         b"world2",
-        read_table2.get(b"hello2").unwrap().unwrap().as_ref()
+        read_table2.get(b"hello2").unwrap().unwrap().to_value()
     );
     assert_eq!(
         b"world3",
-        read_table2.get(b"hello3").unwrap().unwrap().as_ref()
+        read_table2.get(b"hello3").unwrap().unwrap().to_value()
     );
     assert_eq!(read_table2.len().unwrap(), 2);
 
     assert_eq!(
         b"world",
-        read_table.get(b"hello").unwrap().unwrap().as_ref()
+        read_table.get(b"hello").unwrap().unwrap().to_value()
     );
     assert!(read_table.get(b"hello2").unwrap().is_none());
     assert!(read_table.get(b"hello3").unwrap().is_none());
@@ -431,7 +431,7 @@ fn range_query() {
     let table: ReadOnlyTable<[u8], [u8]> = read_txn.open_table(b"x").unwrap();
     let start = vec![3u8];
     let end = vec![7u8];
-    let mut iter = table.get_range(start.as_slice()..end.as_slice()).unwrap();
+    let mut iter = table.get_range(start..end).unwrap();
     for i in 3..7u8 {
         let (key, value) = iter.next().unwrap();
         assert_eq!(&[i], key);