cat_dev/fsemul/pcfs/sata/proto/
create_folder.rs1use crate::{errors::NetworkParseError, fsemul::pcfs::errors::PcfsApiError};
6use bytes::{BufMut, Bytes, BytesMut};
7use std::ffi::CStr;
8use valuable::{Fields, NamedField, NamedValues, StructDef, Structable, Valuable, Value, Visit};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct SataCreateFolderPacketBody {
15 path: String,
26 set_write_mode: bool,
28}
29
30impl SataCreateFolderPacketBody {
31 pub fn new(path: String, set_write_mode: bool) -> Result<Self, PcfsApiError> {
42 if path.len() > 511 {
43 return Err(PcfsApiError::PathTooLong(path));
44 }
45
46 Ok(Self {
47 path,
48 set_write_mode,
49 })
50 }
51
52 #[must_use]
53 pub fn path(&self) -> &str {
54 self.path.as_str()
55 }
56
57 pub fn set_path(&mut self, new_path: String) -> Result<(), PcfsApiError> {
68 if new_path.len() > 511 {
69 return Err(PcfsApiError::PathTooLong(new_path));
70 }
71
72 self.path = new_path;
73 Ok(())
74 }
75
76 #[must_use]
77 pub const fn will_set_write_mode(&self) -> bool {
78 self.set_write_mode
79 }
80
81 pub const fn set_write_mode(&mut self, will_set: bool) {
84 self.set_write_mode = will_set;
85 }
86}
87
88impl TryFrom<Bytes> for SataCreateFolderPacketBody {
89 type Error = NetworkParseError;
90
91 fn try_from(value: Bytes) -> Result<Self, Self::Error> {
92 if value.len() < 0x204 {
93 return Err(NetworkParseError::FieldNotLongEnough(
94 "SataCreateDirectory",
95 "Body",
96 0x204,
97 value.len(),
98 value,
99 ));
100 }
101 if value.len() > 0x204 {
102 return Err(NetworkParseError::UnexpectedTrailer(
103 "SataCreateDirectory",
104 value.slice(0x204..),
105 ));
106 }
107
108 let path_c_str =
109 CStr::from_bytes_until_nul(&value[..0x200]).map_err(NetworkParseError::BadCString)?;
110 let mode = u32::from_be_bytes([value[0x200], value[0x201], value[0x202], value[0x203]]);
111
112 Ok(Self {
113 path: path_c_str.to_str()?.to_owned(),
114 set_write_mode: mode & 0x222 != 0,
115 })
116 }
117}
118
119impl From<&SataCreateFolderPacketBody> for Bytes {
120 fn from(value: &SataCreateFolderPacketBody) -> Self {
121 let mut result = BytesMut::with_capacity(0x204);
122 result.extend_from_slice(value.path.as_bytes());
123 result.extend(BytesMut::zeroed(0x200 - result.len()));
126 result.put_u32(if value.set_write_mode { 0x666 } else { 0x444 });
127 result.freeze()
128 }
129}
130
131impl From<SataCreateFolderPacketBody> for Bytes {
132 fn from(value: SataCreateFolderPacketBody) -> Self {
133 Self::from(&value)
134 }
135}
136
137const SATA_CREATE_FOLDER_PACKET_BODY_FIELDS: &[NamedField<'static>] = &[NamedField::new("path")];
138
139impl Structable for SataCreateFolderPacketBody {
140 fn definition(&self) -> StructDef<'_> {
141 StructDef::new_static(
142 "SataCreateDirectoryPacketBody",
143 Fields::Named(SATA_CREATE_FOLDER_PACKET_BODY_FIELDS),
144 )
145 }
146}
147
148impl Valuable for SataCreateFolderPacketBody {
149 fn as_value(&self) -> Value<'_> {
150 Value::Structable(self)
151 }
152
153 fn visit(&self, visitor: &mut dyn Visit) {
154 visitor.visit_named_fields(&NamedValues::new(
155 SATA_CREATE_FOLDER_PACKET_BODY_FIELDS,
156 &[Valuable::as_value(&self.path)],
157 ));
158 }
159}