Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Cargo.toml

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cargo toml lacks the MSRV bump to 1.81 to use core::error::Error.

Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ description = "A flexible and secure key storage interface for working with cryp
keywords = ["crypto", "storage", "keys", "signatures", "security"]

[dependencies]
anyhow = "1"
thiserror = "2"
async-trait = "0.1"
thiserror = { version = "2", optional = true, default-features = false }
async-trait = { version = "0.1", optional = true }

[features]
default = ["send-sync-storage"]
default = ["std", "send-sync-storage"]
std = ["thiserror/std", "async-trait"]
send-sync-storage = []
no-std = ["thiserror", "async-trait"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a side note: cargo feature flags should be additive. Usually, you don't need a no_std feature flag if your modes of operations include no_std and std. You always include thiserror and async-trait as non-optional dependencies because you need them for no_std anyway. And then you only need the std feature flag which additionally activates their respective std flags.

In this specific case, the reason is more semantically rather than technical because currently enabling both std and no_std wouldn't conflict. Later, they might diverge and break the promise. As you don't cfg(feature = "no_std") anything, it should be fine to remove this.

30 changes: 28 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,21 @@

use thiserror::Error;

pub type Result<T, E = Error> = std::result::Result<T, E>;
#[cfg(not(feature = "std"))]
extern crate alloc;

#[cfg(not(feature = "std"))]
use alloc::boxed::Box;

#[cfg(feature = "std")]
use std::error::Error as StdError;

#[cfg(not(feature = "std"))]
use core::error::Error as CoreError;
Comment on lines +12 to +16

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[cfg(feature = "std")]
use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
use core::error::Error as CoreError;
use core::error::Error as CoreError;

std::error::Error is a reexport of core::error::Error so you don't need to differentiate between them, you can simplify this to always using the core version. Similarly, you can always use alloc::string::String and alloc::boxed::Box and it will be the same types as the std versions if the std library is available.

So in the end, your own Error enum does not even need feature-gated duplication.


pub type Result<T, E = Error> = core::result::Result<T, E>;

#[cfg(feature = "std")]
#[derive(Debug, Error)]
pub enum Error {
#[error("key with ID {0} could not be found")]
Expand All @@ -14,5 +27,18 @@ pub enum Error {
#[error("failed to generate key with provided options")]
InvalidOptions,
#[error(transparent)]
Other(anyhow::Error),
Other(Box<dyn StdError + Send + Sync>),
}

#[cfg(not(feature = "std"))]
#[derive(Debug, Error)]
pub enum Error {
#[error("key with ID {0} could not be found")]
KeyNotFound(alloc::string::String),
#[error("unable to communicate with key store: {0}")]
StoreDisconnected(alloc::string::String),
#[error("failed to generate key with provided options")]
InvalidOptions,
#[error(transparent)]
Other(Box<dyn CoreError + Send + Sync>),
}
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
// Copyright 2020-2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate std;

#[cfg(not(feature = "std"))]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest you remove this gate and simply always use the alloc types. You could even enable #![forbid(clippy::std_instead_of_alloc, clippy::std_instead_of_core)] to force yourself into using the alloc and the core types over the std types where available.

extern crate alloc;

mod error;
mod signature_scheme;
mod signer;
Expand Down
3 changes: 3 additions & 0 deletions src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

use async_trait::async_trait;

#[cfg(not(feature = "std"))]
use alloc::boxed::Box;

use crate::Result;
use crate::SignatureScheme;

Expand Down
3 changes: 3 additions & 0 deletions src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

use async_trait::async_trait;

#[cfg(not(feature = "std"))]
use alloc::boxed::Box;

use crate::signature_scheme::SignatureScheme;
use crate::signer::Signer;
use crate::Result;
Expand Down