Skip to content

Commit 8041e1d

Browse files
convert ipld/amt
1 parent ef11460 commit 8041e1d

File tree

5 files changed

+132
-106
lines changed

5 files changed

+132
-106
lines changed

ipld/amt/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ thiserror = "1.0"
1414
once_cell = "1.5"
1515
ahash = { version = "0.7", optional = true }
1616
itertools = "0.10"
17-
anyhow = "1.0.51"
1817
fvm_ipld_blockstore = { version = "0.1", path = "../blockstore" }
1918
fvm_ipld_encoding = { version = "0.1", path = "../encoding" }
2019

ipld/amt/src/amt.rs

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

4-
use anyhow::anyhow;
54
use cid::multihash::Code;
65
use cid::Cid;
76
use fvm_ipld_blockstore::Blockstore;
@@ -11,6 +10,7 @@ use fvm_ipld_encoding::CborStore;
1110
use itertools::sorted;
1211

1312
use super::ValueMut;
13+
use crate::error::EitherError;
1414
use crate::node::{CollapsedNode, Link};
1515
use crate::{
1616
init_sized_vec, nodes_for_height, Error, Node, Root, DEFAULT_BIT_WIDTH, MAX_HEIGHT, MAX_INDEX,
@@ -72,7 +72,7 @@ where
7272
}
7373

7474
/// Constructs an AMT with a blockstore and a Cid of the root of the AMT
75-
pub fn load(cid: &Cid, block_store: BS) -> Result<Self, Error> {
75+
pub fn load(cid: &Cid, block_store: BS) -> Result<Self, Error<BS>> {
7676
// Load root bytes from database
7777
let root: Root<V> = block_store
7878
.get_cbor(cid)?
@@ -97,7 +97,10 @@ where
9797
}
9898

9999
/// Generates an AMT with block store and array of cbor marshallable objects and returns Cid
100-
pub fn new_from_iter(block_store: BS, vals: impl IntoIterator<Item = V>) -> Result<Cid, Error> {
100+
pub fn new_from_iter(
101+
block_store: BS,
102+
vals: impl IntoIterator<Item = V>,
103+
) -> Result<Cid, Error<BS>> {
101104
let mut t = Self::new(block_store);
102105

103106
t.batch_set(vals)?;
@@ -106,7 +109,7 @@ where
106109
}
107110

108111
/// Get value at index of AMT
109-
pub fn get(&self, i: u64) -> Result<Option<&V>, Error> {
112+
pub fn get(&self, i: u64) -> Result<Option<&V>, Error<BS>> {
110113
if i > MAX_INDEX {
111114
return Err(Error::OutOfRange(i));
112115
}
@@ -121,7 +124,7 @@ where
121124
}
122125

123126
/// Set value at index
124-
pub fn set(&mut self, i: u64, val: V) -> Result<(), Error> {
127+
pub fn set(&mut self, i: u64, val: V) -> Result<(), Error<BS>> {
125128
if i > MAX_INDEX {
126129
return Err(Error::OutOfRange(i));
127130
}
@@ -163,7 +166,7 @@ where
163166

164167
/// Batch set (naive for now)
165168
// TODO Implement more efficient batch set to not have to traverse tree and keep cache for each
166-
pub fn batch_set(&mut self, vals: impl IntoIterator<Item = V>) -> Result<(), Error> {
169+
pub fn batch_set(&mut self, vals: impl IntoIterator<Item = V>) -> Result<(), Error<BS>> {
167170
for (i, val) in (0u64..).zip(vals) {
168171
self.set(i, val)?;
169172
}
@@ -172,7 +175,7 @@ where
172175
}
173176

174177
/// Delete item from AMT at index
175-
pub fn delete(&mut self, i: u64) -> Result<Option<V>, Error> {
178+
pub fn delete(&mut self, i: u64) -> Result<Option<V>, Error<BS>> {
176179
if i > MAX_INDEX {
177180
return Err(Error::OutOfRange(i));
178181
}
@@ -243,23 +246,23 @@ where
243246
&mut self,
244247
iter: impl IntoIterator<Item = u64>,
245248
strict: bool,
246-
) -> Result<bool, Error> {
249+
) -> Result<bool, Error<BS>> {
247250
// TODO: optimize this
248251
let mut modified = false;
249252

250253
// Iterate sorted indices. Sorted to safely optimize later.
251254
for i in sorted(iter) {
252255
let found = self.delete(i)?.is_none();
253256
if strict && found {
254-
return Err(anyhow!("no such index {} in Amt for batch delete", i).into());
257+
return Err(Error::BatchDelteNotFound(i));
255258
}
256259
modified |= found;
257260
}
258261
Ok(modified)
259262
}
260263

261264
/// flush root and return Cid used as key in block store
262-
pub fn flush(&mut self) -> Result<Cid, Error> {
265+
pub fn flush(&mut self) -> Result<Cid, Error<BS>> {
263266
self.root.node.flush(&self.block_store)?;
264267
Ok(self.block_store.put_cbor(&self.root, Code::Blake2b256)?)
265268
}
@@ -283,14 +286,14 @@ where
283286
/// let mut values: Vec<(u64, String)> = Vec::new();
284287
/// map.for_each(|i, v| {
285288
/// values.push((i, v.clone()));
286-
/// Ok(())
289+
/// Ok::<_, ()>(())
287290
/// }).unwrap();
288291
/// assert_eq!(&values, &[(1, "One".to_owned()), (4, "Four".to_owned())]);
289292
/// ```
290293
#[inline]
291-
pub fn for_each<F>(&self, mut f: F) -> Result<(), Error>
294+
pub fn for_each<F, U>(&self, mut f: F) -> Result<(), EitherError<U, BS>>
292295
where
293-
F: FnMut(u64, &V) -> anyhow::Result<()>,
296+
F: FnMut(u64, &V) -> Result<(), U>,
294297
{
295298
self.for_each_while(|i, x| {
296299
f(i, x)?;
@@ -300,9 +303,9 @@ where
300303

301304
/// Iterates over each value in the Amt and runs a function on the values, for as long as that
302305
/// function keeps returning `true`.
303-
pub fn for_each_while<F>(&self, mut f: F) -> Result<(), Error>
306+
pub fn for_each_while<F, U>(&self, mut f: F) -> Result<(), EitherError<U, BS>>
304307
where
305-
F: FnMut(u64, &V) -> anyhow::Result<bool>,
308+
F: FnMut(u64, &V) -> Result<bool, U>,
306309
{
307310
self.root
308311
.node
@@ -318,10 +321,10 @@ where
318321

319322
/// Iterates over each value in the Amt and runs a function on the values that allows modifying
320323
/// each value.
321-
pub fn for_each_mut<F>(&mut self, mut f: F) -> Result<(), Error>
324+
pub fn for_each_mut<F, U>(&mut self, mut f: F) -> Result<(), EitherError<U, BS>>
322325
where
323326
V: Clone,
324-
F: FnMut(u64, &mut ValueMut<'_, V>) -> anyhow::Result<()>,
327+
F: FnMut(u64, &mut ValueMut<'_, V>) -> Result<(), U>,
325328
{
326329
self.for_each_while_mut(|i, x| {
327330
f(i, x)?;
@@ -331,12 +334,12 @@ where
331334

332335
/// Iterates over each value in the Amt and runs a function on the values that allows modifying
333336
/// each value, for as long as that function keeps returning `true`.
334-
pub fn for_each_while_mut<F>(&mut self, mut f: F) -> Result<(), Error>
337+
pub fn for_each_while_mut<F, U>(&mut self, mut f: F) -> Result<(), EitherError<U, BS>>
335338
where
336339
// TODO remove clone bound when go-interop doesn't require it.
337340
// (If needed without, this bound can be removed by duplicating function signatures)
338341
V: Clone,
339-
F: FnMut(u64, &mut ValueMut<'_, V>) -> anyhow::Result<bool>,
342+
F: FnMut(u64, &mut ValueMut<'_, V>) -> Result<bool, U>,
340343
{
341344
#[cfg(not(feature = "go-interop"))]
342345
{

ipld/amt/src/error.rs

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
// Copyright 2019-2022 ChainSafe Systems
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

4-
use std::error::Error as StdError;
5-
6-
use anyhow::anyhow;
74
use cid::Error as CidError;
8-
use fvm_ipld_encoding::Error as EncodingError;
5+
use fvm_ipld_blockstore::Blockstore;
6+
use fvm_ipld_encoding::{CborStoreError, Error as EncodingError};
97
use thiserror::Error;
108

119
/// AMT Error
1210
#[derive(Debug, Error)]
13-
pub enum Error {
11+
pub enum Error<BS: Blockstore> {
1412
/// Index referenced it above arbitrary max set
1513
#[error("index {0} out of range for the amt")]
1614
OutOfRange(u64),
@@ -20,49 +18,65 @@ pub enum Error {
2018
/// Error generating a Cid for data
2119
#[error(transparent)]
2220
Cid(#[from] CidError),
23-
/// Error when trying to serialize an AMT without a flushed cache
24-
#[error("Tried to serialize without saving cache, run flush() on Amt before serializing")]
25-
Cached,
2621
/// Serialized vector less than number of bits set
2722
#[error("Vector length does not match bitmap")]
2823
InvalidVecLength,
29-
/// Invalid formatted serialized node.
30-
#[error("Serialized node cannot contain both links and values")]
31-
LinksAndValues,
3224
/// Cid not found in store error
3325
#[error("Cid ({0}) did not match any in database")]
3426
CidNotFound(String),
35-
/// Dynamic error for when the error needs to be forwarded as is.
3627
#[error("{0}")]
37-
Dynamic(anyhow::Error),
28+
CollapsedNode(#[from] CollapsedNodeError),
29+
#[error("no such index {0} in Amt for batch delete")]
30+
BatchDelteNotFound(u64),
31+
#[error("blockstore {0}")]
32+
Blockstore(BS::Error),
33+
#[error("encoding error {0}")]
34+
Encoding(#[from] EncodingError),
3835
}
3936

40-
impl From<String> for Error {
41-
fn from(e: String) -> Self {
42-
Self::Dynamic(anyhow::anyhow!(e))
37+
impl<BS: Blockstore> From<CborStoreError<BS>> for Error<BS> {
38+
fn from(err: CborStoreError<BS>) -> Self {
39+
match err {
40+
CborStoreError::Blockstore(err) => Error::Blockstore(err),
41+
CborStoreError::Encoding(err) => Error::Encoding(err),
42+
}
4343
}
4444
}
4545

46-
impl From<&'static str> for Error {
47-
fn from(e: &'static str) -> Self {
48-
Self::Dynamic(anyhow::anyhow!(e))
49-
}
46+
#[derive(Debug, Error)]
47+
pub enum EitherError<U, BS: Blockstore> {
48+
#[error("user: {0}")]
49+
User(U),
50+
#[error("hamt: {0}")]
51+
Hamt(#[from] Error<BS>),
5052
}
5153

52-
impl From<anyhow::Error> for Error {
53-
fn from(e: anyhow::Error) -> Self {
54-
e.downcast::<Error>().unwrap_or_else(Self::Dynamic)
54+
impl<U, BS: Blockstore> From<CborStoreError<BS>> for EitherError<U, BS> {
55+
fn from(err: CborStoreError<BS>) -> Self {
56+
EitherError::Hamt(err.into())
5557
}
5658
}
5759

58-
impl From<EncodingError> for Error {
59-
fn from(e: EncodingError) -> Self {
60-
Self::Dynamic(anyhow!(e))
61-
}
60+
#[derive(Debug, Error)]
61+
pub enum CollapsedNodeError {
62+
#[error("expected bitfield of length {0}, found bitfield with length {1}")]
63+
LengthMissmatch(usize, usize),
64+
#[error("Bitmap contained more set bits than links provided")]
65+
MoreBitsThanLinks,
66+
#[error("Bitmap contained less set bits than links provided")]
67+
LessBitsThanLinks,
68+
#[error("Bitmap contained more set bits than values provided")]
69+
MoreBitsThanValues,
70+
#[error("Bitmap contained less set bits than values provided")]
71+
LessBitsThanValues,
72+
/// Invalid formatted serialized node.
73+
#[error("Serialized node cannot contain both links and values")]
74+
LinksAndValues,
6275
}
6376

64-
impl From<Box<dyn StdError + Send + Sync>> for Error {
65-
fn from(e: Box<dyn StdError + Send + Sync>) -> Self {
66-
Self::Dynamic(anyhow!(e))
67-
}
77+
#[derive(Debug, Error)]
78+
pub enum SerdeError {
79+
/// Error when trying to serialize an AMT without a flushed cache
80+
#[error("Tried to serialize without saving cache, run flush() on Amt before serializing")]
81+
Cached,
6882
}

0 commit comments

Comments
 (0)