iscsi_client_rs/models/
parse.rs1use anyhow::{Result, bail};
9use enum_dispatch::enum_dispatch;
10
11use crate::models::{
12 command::{request::ScsiCommandRequest, response::ScsiCommandResponse},
13 common::{BasicHeaderSegment, SendingData},
14 data::{request::ScsiDataOut, response::ScsiDataIn},
15 login::{request::LoginRequest, response::LoginResponse},
16 logout::{request::LogoutRequest, response::LogoutResponse},
17 nop::{request::NopOutRequest, response::NopInResponse},
18 opcode::{BhsOpcode, Opcode},
19 ready_2_transfer::response::ReadyToTransfer,
20 reject::response::RejectPdu,
21 text::{request::TextRequest, response::TextResponse},
22};
23
24#[enum_dispatch(BasicHeaderSegment, SendingData)]
27#[derive(Debug)]
28pub enum Pdu<'a> {
29 NopOutRequest(&'a mut NopOutRequest),
30 ScsiCommandRequest(&'a mut ScsiCommandRequest),
31 TextRequest(&'a mut TextRequest),
32 LoginRequest(&'a mut LoginRequest),
33 ScsiDataOut(&'a mut ScsiDataOut),
34 NopInResponse(&'a mut NopInResponse),
35 ScsiCommandResponse(&'a mut ScsiCommandResponse),
36 TextResponse(&'a mut TextResponse),
37 LoginResponse(&'a mut LoginResponse),
38 ScsiDataIn(&'a mut ScsiDataIn),
39 RejectPdu(&'a mut RejectPdu),
40 ReadyToTransfer(&'a mut ReadyToTransfer),
41 LogoutRequest(&'a mut LogoutRequest),
42 LogoutResponse(&'a mut LogoutResponse),
43}
44
45impl<'a> Pdu<'a> {
46 pub fn from_bhs_bytes(bytes: &'a mut [u8]) -> Result<Self> {
48 let bhs = BhsOpcode::try_from(bytes[0])
49 .map_err(|e| anyhow::anyhow!("invalid opcode: {}", e))?;
50 match bhs.opcode {
51 Opcode::NopOut => {
52 let req = NopOutRequest::from_bhs_bytes(bytes)?;
53 Ok(Pdu::NopOutRequest(req))
54 },
55 Opcode::NopIn => {
56 let req = NopInResponse::from_bhs_bytes(bytes)?;
57 Ok(Pdu::NopInResponse(req))
58 },
59 Opcode::ScsiCommandReq => {
60 let req = ScsiCommandRequest::from_bhs_bytes(bytes)?;
61 Ok(Pdu::ScsiCommandRequest(req))
62 },
63 Opcode::ScsiCommandResp => {
64 let req = ScsiCommandResponse::from_bhs_bytes(bytes)?;
65 Ok(Pdu::ScsiCommandResponse(req))
66 },
67 Opcode::TextReq => {
68 let req = TextRequest::from_bhs_bytes(bytes)?;
69 Ok(Pdu::TextRequest(req))
70 },
71 Opcode::LoginReq => {
72 let req = LoginRequest::from_bhs_bytes(bytes)?;
73 Ok(Pdu::LoginRequest(req))
74 },
75 Opcode::ScsiDataOut => {
76 let req = ScsiDataOut::from_bhs_bytes(bytes)?;
77 Ok(Pdu::ScsiDataOut(req))
78 },
79 Opcode::LoginResp => {
80 let rsp = LoginResponse::from_bhs_bytes(bytes)?;
81 Ok(Pdu::LoginResponse(rsp))
82 },
83 Opcode::Reject => {
84 let rsp = RejectPdu::from_bhs_bytes(bytes)?;
85 Ok(Pdu::RejectPdu(rsp))
86 },
87 Opcode::ScsiDataIn => {
88 let req = ScsiDataIn::from_bhs_bytes(bytes)?;
89 Ok(Pdu::ScsiDataIn(req))
90 },
91 Opcode::ReadyToTransfer => {
92 let req = ReadyToTransfer::from_bhs_bytes(bytes)?;
93 Ok(Pdu::ReadyToTransfer(req))
94 },
95 Opcode::LogoutReq => {
96 let req = LogoutRequest::from_bhs_bytes(bytes)?;
97 Ok(Pdu::LogoutRequest(req))
98 },
99 Opcode::LogoutResp => {
100 let req = LogoutResponse::from_bhs_bytes(bytes)?;
101 Ok(Pdu::LogoutResponse(req))
102 },
103 other => bail!("unsupported opcode: {:?}", other),
104 }
105 }
106}