iscsi_client_rs/models/logout/
common.rs1use std::fmt;
8
9use anyhow::{Result, bail};
10use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
11
12#[derive(Debug, Default, PartialEq, Clone)]
14#[repr(u8)]
15pub enum LogoutReason {
16 #[default]
18 CloseSession = 0x00,
19 CloseConnection = 0x01,
21 RemoveConnectionForRecovery = 0x02,
23}
24
25impl LogoutReason {
26 #[inline]
28 pub fn as_u8(&self) -> u8 {
29 match self {
30 LogoutReason::CloseSession => 0x00,
31 LogoutReason::CloseConnection => 0x01,
32 LogoutReason::RemoveConnectionForRecovery => 0x02,
33 }
34 }
35}
36
37impl TryFrom<u8> for LogoutReason {
38 type Error = anyhow::Error;
39
40 fn try_from(value: u8) -> Result<Self> {
41 Ok(match value {
42 0x00 => LogoutReason::CloseSession,
43 0x01 => LogoutReason::CloseConnection,
44 0x02 => LogoutReason::RemoveConnectionForRecovery,
45 other => bail!("unexpected logout code {other}"),
46 })
47 }
48}
49
50impl fmt::Display for LogoutReason {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 use LogoutReason::*;
53 let s = match self {
54 CloseSession => "CloseSession",
55 CloseConnection => "CloseConnection",
56 RemoveConnectionForRecovery => "RemoveConnectionForRecovery",
57 };
58 f.write_str(s)
59 }
60}
61
62#[repr(transparent)]
67#[derive(
68 Copy, Clone, Debug, PartialEq, Eq, FromBytes, IntoBytes, KnownLayout, Immutable,
69)]
70pub struct RawLogoutReason(u8);
71
72impl Default for RawLogoutReason {
73 #[inline]
74 fn default() -> Self {
75 Self(LogoutReason::CloseSession.as_u8())
76 }
77}
78
79impl RawLogoutReason {
80 #[inline]
82 pub const fn raw(self) -> u8 {
83 self.0
84 }
85
86 #[inline]
88 pub const fn from_raw(v: u8) -> Self {
89 Self(v)
90 }
91
92 #[inline]
94 pub fn decode(self) -> Result<LogoutReason> {
95 LogoutReason::try_from(self.0)
96 }
97
98 #[inline]
100 pub fn encode(&mut self, r: LogoutReason) {
101 self.0 = r.as_u8();
102 }
103}
104
105impl TryFrom<RawLogoutReason> for LogoutReason {
108 type Error = anyhow::Error;
109
110 #[inline]
111 fn try_from(w: RawLogoutReason) -> Result<Self> {
112 w.decode()
113 }
114}
115
116impl From<LogoutReason> for RawLogoutReason {
117 #[inline]
118 fn from(r: LogoutReason) -> Self {
119 Self(r.as_u8())
120 }
121}
122
123impl From<&LogoutReason> for RawLogoutReason {
124 #[inline]
125 fn from(r: &LogoutReason) -> Self {
126 Self(r.as_u8())
127 }
128}
129
130#[derive(Debug, Default, PartialEq, Eq)]
132#[repr(u8)]
133pub enum LogoutResponseCode {
134 #[default]
136 Success = 0x00,
137 CidNotFound = 0x01,
139 RecoveryNotSupported = 0x02,
141 CleanupFailed = 0x03,
143}
144
145impl LogoutResponseCode {
146 #[inline]
148 pub fn as_u8(&self) -> u8 {
149 match self {
150 LogoutResponseCode::Success => 0x00,
151 LogoutResponseCode::CidNotFound => 0x01,
152 LogoutResponseCode::RecoveryNotSupported => 0x02,
153 LogoutResponseCode::CleanupFailed => 0x03,
154 }
155 }
156}
157
158impl TryFrom<u8> for LogoutResponseCode {
159 type Error = anyhow::Error;
160
161 fn try_from(v: u8) -> Result<Self> {
162 Ok(match v {
163 0x00 => LogoutResponseCode::Success,
164 0x01 => LogoutResponseCode::CidNotFound,
165 0x02 => LogoutResponseCode::RecoveryNotSupported,
166 0x03 => LogoutResponseCode::CleanupFailed,
167 other => bail!("invalid LogoutResponseCode: {other:#04x}"),
168 })
169 }
170}
171
172impl fmt::Display for LogoutResponseCode {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 use LogoutResponseCode::*;
175 let s = match self {
176 Success => "Success",
177 CidNotFound => "CidNotFound",
178 RecoveryNotSupported => "RecoveryNotSupported",
179 CleanupFailed => "CleanupFailed",
180 };
181 f.write_str(s)
182 }
183}
184
185#[repr(transparent)]
190#[derive(Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, KnownLayout, Immutable)]
191pub struct RawLogoutResponseCode(u8);
192
193impl Default for RawLogoutResponseCode {
194 #[inline]
195 fn default() -> Self {
196 Self(LogoutResponseCode::Success.as_u8())
197 }
198}
199
200impl RawLogoutResponseCode {
201 #[inline]
203 pub const fn raw(self) -> u8 {
204 self.0
205 }
206
207 #[inline]
209 pub const fn from_raw(v: u8) -> Self {
210 Self(v)
211 }
212
213 #[inline]
215 pub fn decode(self) -> Result<LogoutResponseCode> {
216 LogoutResponseCode::try_from(self.0)
217 }
218
219 #[inline]
221 pub fn encode(&mut self, r: LogoutResponseCode) {
222 self.0 = r.as_u8();
223 }
224}
225
226impl TryFrom<RawLogoutResponseCode> for LogoutResponseCode {
227 type Error = anyhow::Error;
228
229 #[inline]
230 fn try_from(w: RawLogoutResponseCode) -> Result<Self> {
231 w.decode()
232 }
233}
234
235impl From<LogoutResponseCode> for RawLogoutResponseCode {
236 #[inline]
237 fn from(r: LogoutResponseCode) -> Self {
238 Self(r.as_u8())
239 }
240}
241
242impl From<&LogoutResponseCode> for RawLogoutResponseCode {
243 #[inline]
244 fn from(r: &LogoutResponseCode) -> Self {
245 Self(r.as_u8())
246 }
247}
248
249impl fmt::Debug for RawLogoutResponseCode {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 let decoded = match self.decode() {
252 Ok(st) => format!("{st:?}"),
253 Err(_e) => format!("invalid(0x{:02X})", self.raw()),
254 };
255
256 write!(f, "RawScsiStatus {{ {:?} }}", decoded)
257 }
258}