iroh_blobs/get/
error.rs

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