Skip to content

Commit ef11460

Browse files
convert ipld/hamt
1 parent 748ef08 commit ef11460

File tree

7 files changed

+74
-44
lines changed

7 files changed

+74
-44
lines changed

ipld/hamt/src/error.rs

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
11
// Copyright 2019-2022 ChainSafe Systems
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

4-
use std::error::Error as StdError;
5-
64
use fvm_ipld_blockstore::Blockstore;
7-
use fvm_ipld_encoding::{CborStore, CborStoreError, Error as EncodingError};
5+
use fvm_ipld_encoding::{CborStoreError, Error as EncodingError};
86
use thiserror::Error;
97

108
/// HAMT Error
119
#[derive(Debug, Error)]
1210
pub enum Error<BS: Blockstore> {
13-
/// Maximum depth error
14-
#[error("Maximum depth reached")]
15-
MaxDepth,
16-
/// Hash bits does not support greater than 8 bit width
17-
#[error("HashBits does not support retrieving more than 8 bits")]
18-
InvalidHashBitLen,
11+
#[error("hashbits: {0}")]
12+
HashBits(#[from] HashBitsError),
1913
/// This should be treated as a fatal error, must have at least one pointer in node
2014
#[error("Invalid HAMT format, node cannot have 0 pointers")]
2115
ZeroPointers,
@@ -27,3 +21,36 @@ pub enum Error<BS: Blockstore> {
2721
#[error("encoding error {0}")]
2822
Encoding(#[from] EncodingError),
2923
}
24+
25+
impl<BS: Blockstore> From<CborStoreError<BS>> for Error<BS> {
26+
fn from(err: CborStoreError<BS>) -> Self {
27+
match err {
28+
CborStoreError::Blockstore(err) => Error::Blockstore(err),
29+
CborStoreError::Encoding(err) => Error::Encoding(err),
30+
}
31+
}
32+
}
33+
34+
#[derive(Debug, Error)]
35+
pub enum EitherError<U, BS: Blockstore> {
36+
#[error("user: {0}")]
37+
User(U),
38+
#[error("hamt: {0}")]
39+
Hamt(#[from] Error<BS>),
40+
}
41+
42+
impl<U, BS: Blockstore> From<CborStoreError<BS>> for EitherError<U, BS> {
43+
fn from(err: CborStoreError<BS>) -> Self {
44+
EitherError::Hamt(err.into())
45+
}
46+
}
47+
48+
#[derive(Error, Debug)]
49+
pub enum HashBitsError {
50+
/// Maximum depth error
51+
#[error("Maximum depth reached")]
52+
MaxDepth,
53+
/// Hash bits does not support greater than 8 bit width
54+
#[error("HashBits does not support retrieving more than 8 bits")]
55+
InvalidLen,
56+
}

ipld/hamt/src/hamt.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use multihash::Code;
1212
use serde::de::DeserializeOwned;
1313
use serde::{Serialize, Serializer};
1414

15+
use crate::error::EitherError;
1516
use crate::node::Node;
1617
use crate::{Error, Hash, HashAlgorithm, Sha256, DEFAULT_BIT_WIDTH};
1718

@@ -82,12 +83,12 @@ where
8283
}
8384

8485
/// Lazily instantiate a hamt from this root Cid.
85-
pub fn load(cid: &Cid, store: BS) -> Result<Self, Error> {
86+
pub fn load(cid: &Cid, store: BS) -> Result<Self, Error<BS>> {
8687
Self::load_with_bit_width(cid, store, DEFAULT_BIT_WIDTH)
8788
}
8889

8990
/// Lazily instantiate a hamt from this root Cid with a specified bit width.
90-
pub fn load_with_bit_width(cid: &Cid, store: BS, bit_width: u32) -> Result<Self, Error> {
91+
pub fn load_with_bit_width(cid: &Cid, store: BS, bit_width: u32) -> Result<Self, Error<BS>> {
9192
match store.get_cbor(cid)? {
9293
Some(root) => Ok(Self {
9394
root,
@@ -100,7 +101,7 @@ where
100101
}
101102

102103
/// Sets the root based on the Cid of the root node using the Hamt store
103-
pub fn set_root(&mut self, cid: &Cid) -> Result<(), Error> {
104+
pub fn set_root(&mut self, cid: &Cid) -> Result<(), Error<BS>> {
104105
match self.store.get_cbor(cid)? {
105106
Some(root) => self.root = root,
106107
None => return Err(Error::CidNotFound(cid.to_string())),
@@ -136,7 +137,7 @@ where
136137
/// map.set(37, "b".to_string()).unwrap();
137138
/// map.set(37, "c".to_string()).unwrap();
138139
/// ```
139-
pub fn set(&mut self, key: K, value: V) -> Result<Option<V>, Error>
140+
pub fn set(&mut self, key: K, value: V) -> Result<Option<V>, Error<BS>>
140141
where
141142
V: PartialEq,
142143
{
@@ -171,7 +172,7 @@ where
171172
/// let c = map.set_if_absent(30, "c".to_string()).unwrap();
172173
/// assert_eq!(c, true);
173174
/// ```
174-
pub fn set_if_absent(&mut self, key: K, value: V) -> Result<bool, Error>
175+
pub fn set_if_absent(&mut self, key: K, value: V) -> Result<bool, Error<BS>>
175176
where
176177
V: PartialEq,
177178
{
@@ -200,7 +201,7 @@ where
200201
/// assert_eq!(map.get(&2).unwrap(), None);
201202
/// ```
202203
#[inline]
203-
pub fn get<Q: ?Sized>(&self, k: &Q) -> Result<Option<&V>, Error>
204+
pub fn get<Q: ?Sized>(&self, k: &Q) -> Result<Option<&V>, Error<BS>>
204205
where
205206
K: Borrow<Q>,
206207
Q: Hash + Eq,
@@ -232,7 +233,7 @@ where
232233
/// assert_eq!(map.contains_key(&2).unwrap(), false);
233234
/// ```
234235
#[inline]
235-
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> Result<bool, Error>
236+
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> Result<bool, Error<BS>>
236237
where
237238
K: Borrow<Q>,
238239
Q: Hash + Eq,
@@ -263,7 +264,7 @@ where
263264
/// assert_eq!(map.delete(&1).unwrap(), Some((1, "a".to_string())));
264265
/// assert_eq!(map.delete(&1).unwrap(), None);
265266
/// ```
266-
pub fn delete<Q: ?Sized>(&mut self, k: &Q) -> Result<Option<(K, V)>, Error>
267+
pub fn delete<Q: ?Sized>(&mut self, k: &Q) -> Result<Option<(K, V)>, Error<BS>>
267268
where
268269
K: Borrow<Q>,
269270
Q: Hash + Eq,
@@ -273,7 +274,7 @@ where
273274
}
274275

275276
/// Flush root and return Cid for hamt
276-
pub fn flush(&mut self) -> Result<Cid, Error> {
277+
pub fn flush(&mut self) -> Result<Cid, Error<BS>> {
277278
self.root.flush(self.store.borrow())?;
278279
Ok(self.store.put_cbor(&self.root, Code::Blake2b256)?)
279280
}
@@ -301,15 +302,15 @@ where
301302
/// let mut total = 0;
302303
/// map.for_each(|_, v: &u64| {
303304
/// total += v;
304-
/// Ok(())
305+
/// Ok::<(), ()>(())
305306
/// }).unwrap();
306307
/// assert_eq!(total, 3);
307308
/// ```
308309
#[inline]
309-
pub fn for_each<F>(&self, mut f: F) -> Result<(), Error>
310+
pub fn for_each<F, U>(&self, mut f: F) -> Result<(), EitherError<U, BS>>
310311
where
311312
V: DeserializeOwned,
312-
F: FnMut(&K, &V) -> anyhow::Result<()>,
313+
F: FnMut(&K, &V) -> Result<(), U>,
313314
{
314315
self.root.for_each(self.store.borrow(), &mut f)
315316
}

ipld/hamt/src/hash_bits.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use std::cmp::Ordering;
55

6-
use crate::{Error, HashedKey};
6+
use crate::{HashBitsError, HashedKey};
77

88
/// Helper struct which indexes and allows returning bits from a hashed key
99
#[derive(Debug, Clone, Copy)]
@@ -32,12 +32,12 @@ impl<'a> HashBits<'a> {
3232

3333
/// Returns next `i` bits of the hash and returns the value as an integer and returns
3434
/// Error when maximum depth is reached
35-
pub fn next(&mut self, i: u32) -> Result<u32, Error> {
35+
pub fn next(&mut self, i: u32) -> Result<u32, HashBitsError> {
3636
if i > 8 {
37-
return Err(Error::InvalidHashBitLen);
37+
return Err(HashBitsError::InvalidLen);
3838
}
3939
if (self.consumed + i) as usize > self.b.len() * 8 {
40-
return Err(Error::MaxDepth);
40+
return Err(HashBitsError::MaxDepth);
4141
}
4242
Ok(self.next_bits(i))
4343
}
@@ -94,11 +94,11 @@ mod tests {
9494
assert_eq!(hb.next(5).unwrap(), 0b01010);
9595
assert_eq!(hb.next(6).unwrap(), 0b111111);
9696
assert_eq!(hb.next(8).unwrap(), 0b11111111);
97-
assert!(matches!(hb.next(9), Err(Error::InvalidHashBitLen)));
97+
assert!(matches!(hb.next(9), Err(HashBitsError::InvalidLen)));
9898
for _ in 0..28 {
9999
// Iterate through rest of key to test depth
100100
hb.next(8).unwrap();
101101
}
102-
assert!(matches!(hb.next(1), Err(Error::MaxDepth)));
102+
assert!(matches!(hb.next(1), Err(HashBitsError::MaxDepth)));
103103
}
104104
}

ipld/hamt/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod pointer;
2121
pub use forest_hash_utils::{BytesKey, Hash};
2222
use serde::{Deserialize, Serialize};
2323

24-
pub use self::error::Error;
24+
pub use self::error::*;
2525
pub use self::hamt::Hamt;
2626
pub use self::hash::*;
2727
pub use self::hash_algorithm::*;

ipld/hamt/src/node.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use super::bitfield::Bitfield;
1616
use super::hash_bits::HashBits;
1717
use super::pointer::Pointer;
1818
use super::{Error, Hash, HashAlgorithm, KeyValuePair, MAX_ARRAY_WIDTH};
19+
use crate::error::EitherError;
1920

2021
/// Node in Hamt tree which contains bitfield of set indexes and pointers to nodes
2122
#[derive(Debug)]
@@ -85,7 +86,7 @@ where
8586
store: &S,
8687
bit_width: u32,
8788
overwrite: bool,
88-
) -> Result<(Option<V>, bool), Error>
89+
) -> Result<(Option<V>, bool), Error<S>>
8990
where
9091
V: PartialEq,
9192
{
@@ -107,7 +108,7 @@ where
107108
k: &Q,
108109
store: &S,
109110
bit_width: u32,
110-
) -> Result<Option<&V>, Error>
111+
) -> Result<Option<&V>, Error<S>>
111112
where
112113
K: Borrow<Q>,
113114
Q: Eq + Hash,
@@ -121,7 +122,7 @@ where
121122
k: &Q,
122123
store: &S,
123124
bit_width: u32,
124-
) -> Result<Option<(K, V)>, Error>
125+
) -> Result<Option<(K, V)>, Error<S>>
125126
where
126127
K: Borrow<Q>,
127128
Q: Eq + Hash,
@@ -135,9 +136,9 @@ where
135136
self.pointers.is_empty()
136137
}
137138

138-
pub(crate) fn for_each<S, F>(&self, store: &S, f: &mut F) -> Result<(), Error>
139+
pub(crate) fn for_each<S, F, U>(&self, store: &S, f: &mut F) -> Result<(), EitherError<U, S>>
139140
where
140-
F: FnMut(&K, &V) -> anyhow::Result<()>,
141+
F: FnMut(&K, &V) -> Result<(), U>,
141142
S: Blockstore,
142143
{
143144
for p in &self.pointers {
@@ -150,7 +151,7 @@ where
150151
node
151152
} else {
152153
#[cfg(not(feature = "ignore-dead-links"))]
153-
return Err(Error::CidNotFound(cid.to_string()));
154+
return Err(Error::CidNotFound(cid.to_string()).into());
154155

155156
#[cfg(feature = "ignore-dead-links")]
156157
continue;
@@ -164,7 +165,7 @@ where
164165
Pointer::Dirty(n) => n.for_each(store, f)?,
165166
Pointer::Values(kvs) => {
166167
for kv in kvs {
167-
f(kv.0.borrow(), kv.1.borrow())?;
168+
f(kv.0.borrow(), kv.1.borrow()).map_err(EitherError::User)?;
168169
}
169170
}
170171
}
@@ -178,7 +179,7 @@ where
178179
q: &Q,
179180
store: &S,
180181
bit_width: u32,
181-
) -> Result<Option<&KeyValuePair<K, V>>, Error>
182+
) -> Result<Option<&KeyValuePair<K, V>>, Error<S>>
182183
where
183184
K: Borrow<Q>,
184185
Q: Eq + Hash,
@@ -194,7 +195,7 @@ where
194195
depth: u64,
195196
key: &Q,
196197
store: &S,
197-
) -> Result<Option<&KeyValuePair<K, V>>, Error>
198+
) -> Result<Option<&KeyValuePair<K, V>>, Error<S>>
198199
where
199200
K: Borrow<Q>,
200201
Q: Eq + Hash,
@@ -244,7 +245,7 @@ where
244245
value: V,
245246
store: &S,
246247
overwrite: bool,
247-
) -> Result<(Option<V>, bool), Error>
248+
) -> Result<(Option<V>, bool), Error<S>>
248249
where
249250
V: PartialEq,
250251
{
@@ -364,7 +365,7 @@ where
364365
depth: u64,
365366
key: &Q,
366367
store: &S,
367-
) -> Result<Option<(K, V)>, Error>
368+
) -> Result<Option<(K, V)>, Error<S>>
368369
where
369370
K: Borrow<Q>,
370371
Q: Hash + Eq,
@@ -427,7 +428,7 @@ where
427428
}
428429
}
429430

430-
pub fn flush<S: Blockstore>(&mut self, store: &S) -> Result<(), Error> {
431+
pub fn flush<S: Blockstore>(&mut self, store: &S) -> Result<(), Error<S>> {
431432
for pointer in &mut self.pointers {
432433
if let Pointer::Dirty(node) = pointer {
433434
// Flush cached sub node to clear it's cache

ipld/hamt/src/pointer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::cmp::Ordering;
55
use std::convert::{TryFrom, TryInto};
66

77
use cid::Cid;
8+
use fvm_ipld_blockstore::Blockstore;
89
use libipld_core::ipld::Ipld;
910
use once_cell::unsync::OnceCell;
1011
use serde::de::{self, DeserializeOwned};
@@ -111,7 +112,7 @@ where
111112

112113
/// Internal method to cleanup children, to ensure consistent tree representation
113114
/// after deletes.
114-
pub(crate) fn clean(&mut self) -> Result<(), Error> {
115+
pub(crate) fn clean<BS: Blockstore>(&mut self) -> Result<(), Error<BS>> {
115116
match self {
116117
Pointer::Dirty(n) => match n.pointers.len() {
117118
0 => Err(Error::ZeroPointers),

ipld/hamt/tests/hamt_tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ fn for_each() {
273273
hamt.for_each(|k, v| {
274274
assert_eq!(k, v);
275275
count += 1;
276-
Ok(())
276+
Ok::<(), ()>(())
277277
})
278278
.unwrap();
279279
assert_eq!(count, 200);
@@ -291,7 +291,7 @@ fn for_each() {
291291
hamt.for_each(|k, v| {
292292
assert_eq!(k, v);
293293
count += 1;
294-
Ok(())
294+
Ok::<(), ()>(())
295295
})
296296
.unwrap();
297297
assert_eq!(count, 200);
@@ -301,7 +301,7 @@ fn for_each() {
301301
hamt.for_each(|k, v| {
302302
assert_eq!(k, v);
303303
count += 1;
304-
Ok(())
304+
Ok::<(), ()>(())
305305
})
306306
.unwrap();
307307
assert_eq!(count, 200);

0 commit comments

Comments
 (0)