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