cat_dev/fsemul/pcfs/sata/proto/
ping.rs

1//! Definitions for the `PING` packet type, and it's response types.
2//!
3//! Ping packets are much like ping packet types in any sort of scenario, they
4//! are built to check availability. Not to mention ping packets confer what
5//! features are enabled.
6
7use crate::errors::NetworkParseError;
8use bytes::{Buf, BufMut, Bytes, BytesMut};
9use valuable::{Fields, NamedField, NamedValues, StructDef, Structable, Valuable, Value, Visit};
10
11/// A ZST that represents a ping packet coming in.
12#[derive(Copy, Clone, Debug, PartialEq, Eq, Valuable)]
13pub struct SataPingPacketBody;
14
15impl SataPingPacketBody {
16	#[must_use]
17	pub const fn new() -> Self {
18		Self
19	}
20}
21
22impl Default for SataPingPacketBody {
23	fn default() -> Self {
24		Self
25	}
26}
27
28impl TryFrom<Bytes> for SataPingPacketBody {
29	type Error = NetworkParseError;
30
31	fn try_from(value: Bytes) -> Result<Self, Self::Error> {
32		if !value.is_empty() {
33			return Err(NetworkParseError::UnexpectedTrailer(
34				"SataPingPacketBody",
35				value,
36			));
37		}
38
39		Ok(Self)
40	}
41}
42
43impl From<&SataPingPacketBody> for Bytes {
44	fn from(_: &SataPingPacketBody) -> Self {
45		Bytes::new()
46	}
47}
48
49impl From<SataPingPacketBody> for Bytes {
50	fn from(_: SataPingPacketBody) -> Self {
51		Bytes::new()
52	}
53}
54
55/// A response to a `PING` over the Sata protocol of `PCFS`.
56#[derive(Clone, Debug, PartialEq, Eq)]
57pub struct SataPongBody {
58	/// If Fast File I/O is enabled and supported by both sides.
59	fast_file_io_enabled: bool,
60	/// If Combined Send/Recv is enabled and supported by both sides.
61	combined_send_recv_enabled: bool,
62}
63
64impl SataPongBody {
65	#[must_use]
66	pub const fn new(ffio_enabled: bool, csr_enabled: bool) -> Self {
67		Self {
68			fast_file_io_enabled: ffio_enabled,
69			combined_send_recv_enabled: csr_enabled,
70		}
71	}
72
73	#[must_use]
74	pub const fn ffio_enabled(&self) -> bool {
75		self.fast_file_io_enabled
76	}
77
78	pub const fn set_ffio_enabled(&mut self, enabled: bool) {
79		self.fast_file_io_enabled = enabled;
80	}
81
82	#[must_use]
83	pub const fn combined_send_recv_enabled(&self) -> bool {
84		self.combined_send_recv_enabled
85	}
86
87	pub const fn set_combined_send_recv_enabled(&mut self, enabled: bool) {
88		self.combined_send_recv_enabled = enabled;
89	}
90}
91
92impl From<&SataPongBody> for Bytes {
93	fn from(value: &SataPongBody) -> Self {
94		let mut buff = BytesMut::with_capacity(8);
95
96		buff.put_u32(0x0); // Success! - This is a return code.
97		buff.put_u32(
98			match (value.fast_file_io_enabled, value.combined_send_recv_enabled) {
99				(true, true) => 0xCAFE_0003,
100				(true, false) => 0xCAFE_0001,
101				(false, true) => 0xCAFE_0002,
102				(false, false) => 0x0000_0000,
103			},
104		);
105
106		buff.freeze()
107	}
108}
109
110impl From<SataPongBody> for Bytes {
111	fn from(value: SataPongBody) -> Self {
112		Self::from(&value)
113	}
114}
115
116impl TryFrom<Bytes> for SataPongBody {
117	type Error = NetworkParseError;
118
119	fn try_from(mut value: Bytes) -> Result<Self, Self::Error> {
120		if value.len() < 0x8 {
121			return Err(NetworkParseError::FieldNotLongEnough(
122				"SataPongBody",
123				"Body",
124				0x8,
125				value.len(),
126				value,
127			));
128		}
129		if value.len() > 0x8 {
130			return Err(NetworkParseError::UnexpectedTrailer(
131				"SataPongBody",
132				value.slice(0x8..),
133			));
134		}
135
136		// Get the return code.
137		let rc = value.get_u32();
138		if rc != 0 {
139			return Err(NetworkParseError::ErrorCode(rc));
140		}
141		let flags = value.get_u32();
142
143		Ok(Self {
144			fast_file_io_enabled: flags == 0xCAFE_0003 || flags == 0xCAFE_0001,
145			combined_send_recv_enabled: flags == 0xCAFE_0003 || flags == 0xCAFE_0002,
146		})
147	}
148}
149
150const SATA_PONG_BODY_FIELDS: &[NamedField<'static>] = &[
151	NamedField::new("fast_file_io_enabled"),
152	NamedField::new("combined_send_recv_enabled"),
153];
154
155impl Structable for SataPongBody {
156	fn definition(&self) -> StructDef<'_> {
157		StructDef::new_static("SataPongBody", Fields::Named(SATA_PONG_BODY_FIELDS))
158	}
159}
160
161impl Valuable for SataPongBody {
162	fn as_value(&self) -> Value<'_> {
163		Value::Structable(self)
164	}
165
166	fn visit(&self, visitor: &mut dyn Visit) {
167		visitor.visit_named_fields(&NamedValues::new(
168			SATA_PONG_BODY_FIELDS,
169			&[
170				Valuable::as_value(&self.fast_file_io_enabled),
171				Valuable::as_value(&self.combined_send_recv_enabled),
172			],
173		));
174	}
175}