use std::fmt::Display;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error(transparent)]
Attributes(#[from] AttributesError),
#[error(transparent)]
Shares(#[from] SharesError),
#[error(transparent)]
Conversions(#[from] ConversionsError),
#[error(transparent)]
Multibase(#[from] multi_base::Error),
#[error(transparent)]
Multicodec(#[from] multi_codec::Error),
#[error(transparent)]
Multitrait(#[from] multi_trait::Error),
#[error(transparent)]
Multiutil(#[from] multi_util::Error),
#[error(transparent)]
Fmt(#[from] std::fmt::Error),
#[error(transparent)]
Utf8(#[from] std::string::FromUtf8Error),
#[error("Vsss share error: {0}")]
Vsss(String),
#[error("Missing Multisig sigil")]
MissingSigil,
#[error("Duplicate Multikey attribute: {0}")]
DuplicateAttribute(u8),
#[error("Failed Varsig conversion: {0}")]
FailedConversion(String),
#[error("Unsupported signature codec: {0}")]
UnsupportedAlgorithm(String),
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum AttributesError {
#[error("Unsupported signature codec: {0}")]
UnsupportedCodec(multi_codec::Codec),
#[error("Signature data missing")]
MissingSignature,
#[error("Signature missing payload encoding")]
MissingPayloadEncoding,
#[error("Signature missing scheme")]
MissingScheme,
#[error("Signature missing threshold")]
MissingThreshold,
#[error("Signature missing limit")]
MissingLimit,
#[error("Signature missing identifier")]
MissingIdentifier,
#[error("Signature missing threshold data")]
MissingThresholdData,
#[error("Invalid attribute name {0}")]
InvalidAttributeName(String),
#[error("Invalid attribute value {0}")]
InvalidAttributeValue(u8),
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum SharesError {
#[error("Threshold signature has too many shares")]
TooManyShares,
#[error("Missing share data")]
MissingShareData,
#[error("Missing share type")]
MissingShareType,
#[error("Invalid signature scheme type id {0}")]
InvalidSchemeTypeId(u8),
#[error("Invalid share type name {0}")]
InvalidShareTypeName(String),
#[error("Not a signature share")]
NotASignatureShare,
#[error("Is a signature share")]
IsASignatureShare,
#[error("Signature share type mismatch")]
ShareTypeMismatch,
#[error("Signature share combine failed: {0}")]
ShareCombineFailed(String),
#[error("Not enough shares to reconstruct the signature")]
NotEnoughShares,
#[error("Threshold metadata error: {0}")]
MetaEncryption(String),
#[error("Missing threshold metadata key")]
MissingMetaKey,
#[error("Threshold disclosure mode mismatch: expected {expected}, found {found}")]
DisclosureMismatch {
expected: u8,
found: u8,
},
#[error("Duplicate share identifier")]
DuplicateShare,
#[error("Invalid threshold data: {0}")]
InvalidThresholdData(String),
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ConversionsError {
#[error(transparent)]
Ssh(#[from] SshError),
}
#[derive(Debug)]
pub enum SshError {
Sig(ssh_key::Error),
SigLabel(ssh_encoding::LabelError),
}
impl Display for SshError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SshError::Sig(e) => write!(f, "SSH Sig error: {}", e),
SshError::SigLabel(e) => write!(f, "SSH Sig label error: {}", e),
}
}
}
impl std::error::Error for SshError {}
impl From<ssh_key::Error> for SshError {
fn from(e: ssh_key::Error) -> Self {
SshError::Sig(e)
}
}
impl From<ssh_encoding::LabelError> for SshError {
fn from(e: ssh_encoding::LabelError) -> Self {
SshError::SigLabel(e)
}
}
impl Error {
pub fn kind(&self) -> &str {
match self {
Self::Attributes(_) => "Attributes",
Self::Shares(_) => "Shares",
Self::Conversions(_) => "Conversions",
Self::Multibase(_) => "Multibase",
Self::Multicodec(_) => "Multicodec",
Self::Multitrait(_) => "Multitrait",
Self::Multiutil(_) => "Multiutil",
Self::Fmt(_) => "Fmt",
Self::Utf8(_) => "Utf8",
Self::Vsss(_) => "Vsss",
Self::MissingSigil => "MissingSigil",
Self::DuplicateAttribute(_) => "DuplicateAttribute",
Self::FailedConversion(_) => "FailedConversion",
Self::UnsupportedAlgorithm(_) => "UnsupportedAlgorithm",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_kind() {
let err = Error::MissingSigil;
assert_eq!(err.kind(), "MissingSigil");
let err = Error::DuplicateAttribute(42);
assert_eq!(err.kind(), "DuplicateAttribute");
}
#[test]
fn test_error_display() {
let err = Error::MissingSigil;
assert!(err.to_string().contains("sigil"));
let err = Error::UnsupportedAlgorithm("test".to_string());
assert!(err.to_string().contains("test"));
}
#[test]
fn test_error_is_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<Error>();
assert_sync::<Error>();
}
}