homestar_invocation/
error.rs

1//! Error types and implementations for [Invocation] interaction(s).
2//!
3//! [Invocation]: crate::Invocation
4
5use crate::{
6    task::instruction::{Args, Input},
7    Unit,
8};
9use libipld::Ipld;
10use serde::de::Error as DeError;
11use std::io;
12
13/// Generic error type for [Invocation] use cases.
14///
15/// [Invocation]: crate::Invocation
16#[derive(thiserror::Error, Debug)]
17pub enum Error<T> {
18    /// Error encoding structure to a Cid.
19    #[error("failed to encode CID: {0}")]
20    CidEncode(#[from] libipld::cid::Error),
21    /// Error thrown when condition or dynamic check is not met.
22    #[error("condition not met: {0}")]
23    ConditionNotMet(String),
24    /// Failure to decode/encode from/to DagCbor.
25    ///
26    /// The underlying error is a [anyhow::Error], per the
27    /// DagCborCodec implementation.
28    #[error("failed to decode/encode DAG-CBOR: {0}")]
29    DagCborTranslation(#[from] anyhow::Error),
30    /// Error converting from Ipld structure via [serde].
31    ///
32    /// Transparently forwards from [libipld::error::SerdeError]'s `source` and
33    /// `Display` methods through to an underlying error.
34    #[error("cannot convert from Ipld structure: {0}")]
35    FromIpld(#[from] libipld::error::SerdeError),
36    /// Error with a [libipld::multibase] encoding/decoding.
37    #[error("failed to decode/encode structure: {0}")]
38    FromMultibase(#[from] libipld::multibase::Error),
39    /// Invalid match discriminant or enumeration.
40    #[error("invalid discriminant {0:#?}")]
41    InvalidDiscriminant(T),
42    /// Error related to a missing a field in a structure or key
43    /// in a map.
44    #[error("no {0} field set")]
45    MissingField(String),
46    /// Error during parsing a [Url].
47    ///
48    /// Transparently forwards from [url::ParseError]'s `source` and
49    /// `Display` methods through to an underlying error.
50    ///
51    /// [Url]: url::Url
52    #[error(transparent)]
53    ParseResource(#[from] url::ParseError),
54    /// Generic unknown error.
55    #[error("unknown error")]
56    Unknown,
57    /// Unexpcted Ipld type.
58    #[error("unexpected Ipld type: {0:#?}")]
59    UnexpectedIpldType(Ipld),
60    /// Error when attempting to interpret a sequence of [u8]
61    /// as a string.
62    ///
63    /// Transparently forwards from [std::str::Utf8Error]'s `source` and
64    /// `Display` methods through to an underlying error.
65    #[error(transparent)]
66    Utf8(#[from] std::str::Utf8Error),
67    /// Propagated IO error.
68    #[error("error writing data to console: {0}")]
69    Io(#[from] io::Error),
70}
71
72impl<T> Error<T> {
73    /// Return a [SerdeError] when returning an Ipld structure
74    /// that's not expected at the call-site.
75    ///
76    /// [SerdeError]: libipld::error::SerdeError
77    pub fn unexpected_ipld(ipld: Ipld) -> Self {
78        Error::UnexpectedIpldType(ipld)
79    }
80
81    /// Return an `invalid type` [SerdeError] when not matching an expected
82    /// Ipld list/sequence type.
83    ///
84    /// [SerdeError]: libipld::error::SerdeError
85    pub fn not_an_ipld_list() -> Self {
86        Error::FromIpld(libipld::error::SerdeError::invalid_type(
87            serde::de::Unexpected::Seq,
88            &"an Ipld list / sequence",
89        ))
90    }
91}
92
93impl From<Error<Unit>> for Error<String> {
94    fn from(_err: Error<Unit>) -> Self {
95        Error::Unknown
96    }
97}
98
99impl From<Error<String>> for Error<Unit> {
100    fn from(_err: Error<String>) -> Error<Unit> {
101        Error::Unknown
102    }
103}
104
105impl<T> From<std::convert::Infallible> for Error<T> {
106    fn from(err: std::convert::Infallible) -> Self {
107        match err {}
108    }
109}
110
111/// Error type for parsing [Invocation] [Input]s.
112///
113/// [Invocation]: crate::Invocation
114#[derive(thiserror::Error, Debug)]
115pub enum InputParseError<T> {
116    /// Error converting from Ipld structure via [serde].
117    ///
118    /// Transparently forwards from [libipld::error::SerdeError]'s `source` and
119    /// `Display` methods through to an underlying error.
120    #[error("cannot convert from Ipld structure: {0}")]
121    FromIpld(#[from] libipld::error::SerdeError),
122    /// Error converting from Ipld structure into [Args].
123    #[error("cannot convert from Ipld structure into arguments: {0:#?}")]
124    IpldToArgs(Args<T>),
125    /// Unexpected [Input] in [Task] structure.
126    ///
127    /// [Task]: crate::Task
128    #[error("unexpected task input: {0:#?}")]
129    UnexpectedTaskInput(Input<T>),
130    /// Bubble-up conversion and other general [Invocation errors].
131    ///
132    /// [Invocation errors]: Error
133    #[error(transparent)]
134    Invocation(#[from] Error<T>),
135}
136
137impl<T> From<std::convert::Infallible> for InputParseError<T> {
138    fn from(err: std::convert::Infallible) -> Self {
139        match err {}
140    }
141}
142
143/// Error type for resolving promised Cids within [Invocation] [Input]s.
144///
145/// [Invocation]: crate::Invocation
146#[derive(thiserror::Error, Debug)]
147pub enum ResolveError {
148    /// Generic runtime error.
149    ///
150    /// Transparently forwards from [anyhow::Error]'s `source` and
151    /// `Display` methods through to an underlying error.
152    #[error(transparent)]
153    Runtime(#[from] anyhow::Error),
154    /// Transport error when attempting to resolve [Invocation] [Input]'s Cid.
155    ///
156    /// [Invocation]: crate::Invocation
157    #[error("transport error during resolve phase of input Cid: {0}")]
158    Transport(String),
159    /// Unable to resolve a Cid within an [Invocation]'s [Input].
160    ///
161    /// [Invocation]: crate::Invocation
162    #[error("error resolving input Cid: {0}")]
163    UnresolvedCid(String),
164}
165
166impl From<std::convert::Infallible> for ResolveError {
167    fn from(err: std::convert::Infallible) -> Self {
168        match err {}
169    }
170}