payjoin/core/send/v2/
error.rs

1use core::fmt;
2
3use crate::ohttp::DirectoryResponseError;
4use crate::uri::url_ext::ParseReceiverPubkeyParamError;
5
6/// Error returned when request could not be created.
7///
8/// This error can currently only happen due to programmer mistake.
9/// `unwrap()`ing it is thus considered OK in Rust but you may achieve nicer message by displaying
10/// it.
11#[derive(Debug)]
12pub struct CreateRequestError(InternalCreateRequestError);
13
14#[derive(Debug)]
15pub(crate) enum InternalCreateRequestError {
16    Url(crate::into_url::Error),
17    Hpke(crate::hpke::HpkeError),
18    OhttpEncapsulation(crate::ohttp::OhttpEncapsulationError),
19    ParseReceiverPubkey(ParseReceiverPubkeyParamError),
20    MissingOhttpConfig,
21    Expired(std::time::SystemTime),
22}
23
24impl fmt::Display for CreateRequestError {
25    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26        use InternalCreateRequestError::*;
27
28        match &self.0 {
29            Url(e) => write!(f, "cannot parse url: {e:#?}"),
30            Hpke(e) => write!(f, "v2 error: {e}"),
31            OhttpEncapsulation(e) => write!(f, "v2 error: {e}"),
32            ParseReceiverPubkey(e) => write!(f, "cannot parse receiver public key: {e}"),
33            MissingOhttpConfig =>
34                write!(f, "no ohttp configuration with which to make a v2 request available"),
35            Expired(expiry) => write!(f, "session expired at {expiry:?}"),
36        }
37    }
38}
39
40impl std::error::Error for CreateRequestError {
41    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
42        use InternalCreateRequestError::*;
43
44        match &self.0 {
45            Url(error) => Some(error),
46            Hpke(error) => Some(error),
47            OhttpEncapsulation(error) => Some(error),
48            ParseReceiverPubkey(error) => Some(error),
49            MissingOhttpConfig => None,
50            Expired(_) => None,
51        }
52    }
53}
54
55impl From<InternalCreateRequestError> for CreateRequestError {
56    fn from(value: InternalCreateRequestError) -> Self { CreateRequestError(value) }
57}
58
59impl From<crate::into_url::Error> for CreateRequestError {
60    fn from(value: crate::into_url::Error) -> Self {
61        CreateRequestError(InternalCreateRequestError::Url(value))
62    }
63}
64
65impl From<ParseReceiverPubkeyParamError> for CreateRequestError {
66    fn from(value: ParseReceiverPubkeyParamError) -> Self {
67        CreateRequestError(InternalCreateRequestError::ParseReceiverPubkey(value))
68    }
69}
70
71/// Error returned for v2-specific payload encapsulation errors.
72#[derive(Debug)]
73pub struct EncapsulationError(InternalEncapsulationError);
74
75#[derive(Debug)]
76pub(crate) enum InternalEncapsulationError {
77    /// The HPKE failed.
78    Hpke(crate::hpke::HpkeError),
79    /// The directory returned a bad response
80    DirectoryResponse(DirectoryResponseError),
81}
82
83impl fmt::Display for EncapsulationError {
84    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85        use InternalEncapsulationError::*;
86
87        match &self.0 {
88            Hpke(error) => write!(f, "HPKE error: {error}"),
89            DirectoryResponse(e) => write!(f, "Directory response error: {e}"),
90        }
91    }
92}
93
94impl std::error::Error for EncapsulationError {
95    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
96        use InternalEncapsulationError::*;
97
98        match &self.0 {
99            Hpke(error) => Some(error),
100            DirectoryResponse(e) => Some(e),
101        }
102    }
103}
104
105impl From<InternalEncapsulationError> for EncapsulationError {
106    fn from(value: InternalEncapsulationError) -> Self { EncapsulationError(value) }
107}
108
109impl From<InternalEncapsulationError> for super::ResponseError {
110    fn from(value: InternalEncapsulationError) -> Self {
111        super::InternalValidationError::V2Encapsulation(value.into()).into()
112    }
113}