iroh_blobs/get/
error.rs

1//! Error returned from get operations
2use std::io;
3
4use iroh::endpoint::{ConnectionError, ReadError, VarInt, WriteError};
5use n0_error::{stack_error, AnyError};
6
7use crate::get::fsm::{
8    AtBlobHeaderNextError, AtClosingNextError, ConnectedNextError, DecodeError, InitialNextError,
9};
10
11/// Failures for a get operation
12#[stack_error(derive, add_meta)]
13pub enum GetError {
14    #[error(transparent)]
15    InitialNext {
16        #[error(from)]
17        source: InitialNextError,
18    },
19    #[error(transparent)]
20    ConnectedNext {
21        #[error(from)]
22        source: ConnectedNextError,
23    },
24    #[error(transparent)]
25    AtBlobHeaderNext {
26        #[error(from)]
27        source: AtBlobHeaderNextError,
28    },
29    #[error(transparent)]
30    Decode {
31        #[error(from)]
32        source: DecodeError,
33    },
34    #[error(transparent)]
35    IrpcSend {
36        #[error(from)]
37        source: irpc::channel::SendError,
38    },
39    #[error(transparent)]
40    AtClosingNext {
41        #[error(from)]
42        source: AtClosingNextError,
43    },
44    #[error("local failure")]
45    LocalFailure { source: AnyError },
46    #[error("bad request")]
47    BadRequest { source: AnyError },
48}
49
50impl GetError {
51    pub fn iroh_error_code(&self) -> Option<VarInt> {
52        if let Some(ReadError::Reset(code)) = self
53            .remote_read()
54            .and_then(|source| source.get_ref())
55            .and_then(|e| e.downcast_ref::<iroh::endpoint::ReadError>())
56        {
57            Some(*code)
58        } else if let Some(WriteError::Stopped(code)) = self
59            .remote_write()
60            .and_then(|source| source.get_ref())
61            .and_then(|e| e.downcast_ref::<iroh::endpoint::WriteError>())
62        {
63            Some(*code)
64        } else if let Some(ConnectionError::ApplicationClosed(ac)) = self
65            .open()
66            .and_then(|source| source.get_ref())
67            .and_then(|e| e.downcast_ref::<iroh::endpoint::ConnectionError>())
68        {
69            Some(ac.error_code)
70        } else {
71            None
72        }
73    }
74
75    pub fn remote_write(&self) -> Option<&io::Error> {
76        match self {
77            Self::ConnectedNext {
78                source: ConnectedNextError::Write { source, .. },
79                ..
80            } => Some(source),
81            _ => None,
82        }
83    }
84
85    pub fn open(&self) -> Option<&io::Error> {
86        match self {
87            Self::InitialNext {
88                source: InitialNextError::Open { source, .. },
89                ..
90            } => Some(source),
91            _ => None,
92        }
93    }
94
95    pub fn remote_read(&self) -> Option<&io::Error> {
96        match self {
97            Self::AtBlobHeaderNext {
98                source: AtBlobHeaderNextError::Read { source, .. },
99                ..
100            } => Some(source),
101            Self::Decode {
102                source: DecodeError::Read { source, .. },
103                ..
104            } => Some(source),
105            Self::AtClosingNext {
106                source: AtClosingNextError::Read { source, .. },
107                ..
108            } => Some(source),
109            _ => None,
110        }
111    }
112
113    pub fn local_write(&self) -> Option<&io::Error> {
114        match self {
115            Self::Decode {
116                source: DecodeError::Write { source, .. },
117                ..
118            } => Some(source),
119            _ => None,
120        }
121    }
122}
123
124pub type GetResult<T> = std::result::Result<T, GetError>;