1use 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#[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>;