cat_dev/fsemul/pcfs/sata/proto/
change_owner.rs1use crate::{errors::NetworkParseError, fsemul::pcfs::errors::PcfsApiError};
8use bytes::{BufMut, Bytes, BytesMut};
9use std::ffi::CStr;
10use valuable::{Fields, NamedField, NamedValues, StructDef, Structable, Valuable, Value, Visit};
11
12#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct SataChangeOwnerPacketBody {
17 path: String,
28 uid: u32,
30 gid: u32,
32}
33
34impl SataChangeOwnerPacketBody {
35 pub fn new(path: String, uid: u32, gid: u32) -> Result<Self, PcfsApiError> {
46 if path.len() > 511 {
47 return Err(PcfsApiError::PathTooLong(path));
48 }
49
50 Ok(Self { path, uid, gid })
51 }
52
53 #[must_use]
54 pub fn path(&self) -> &str {
55 self.path.as_str()
56 }
57
58 pub fn set_path(&mut self, new_path: String) -> Result<(), PcfsApiError> {
69 if new_path.len() > 511 {
70 return Err(PcfsApiError::PathTooLong(new_path));
71 }
72
73 self.path = new_path;
74 Ok(())
75 }
76
77 #[must_use]
78 pub const fn uid(&self) -> u32 {
79 self.uid
80 }
81
82 pub const fn set_uid(&mut self, new_uid: u32) {
84 self.uid = new_uid;
85 }
86
87 #[must_use]
88 pub const fn gid(&self) -> u32 {
89 self.gid
90 }
91
92 pub const fn set_gid(&mut self, new_gid: u32) {
94 self.gid = new_gid;
95 }
96}
97
98impl TryFrom<Bytes> for SataChangeOwnerPacketBody {
99 type Error = NetworkParseError;
100
101 fn try_from(value: Bytes) -> Result<Self, Self::Error> {
102 if value.len() < 0x208 {
103 return Err(NetworkParseError::FieldNotLongEnough(
104 "SataChangeMode",
105 "Body",
106 0x208,
107 value.len(),
108 value,
109 ));
110 }
111 if value.len() > 0x208 {
112 return Err(NetworkParseError::UnexpectedTrailer(
113 "SataChangeMode",
114 value.slice(0x208..),
115 ));
116 }
117
118 let (path_bytes, num) = value.split_at(0x200);
119 let path_c_str =
120 CStr::from_bytes_until_nul(path_bytes).map_err(NetworkParseError::BadCString)?;
121 let uid = u32::from_be_bytes([num[0], num[1], num[2], num[3]]);
122 let gid = u32::from_be_bytes([num[4], num[5], num[6], num[7]]);
123 let final_path = path_c_str.to_str()?.to_owned();
124
125 Ok(Self {
126 path: final_path,
127 uid,
128 gid,
129 })
130 }
131}
132
133impl From<&SataChangeOwnerPacketBody> for Bytes {
134 fn from(value: &SataChangeOwnerPacketBody) -> Self {
135 let mut result = BytesMut::with_capacity(0x208);
136 result.extend_from_slice(value.path.as_bytes());
137 result.extend(BytesMut::zeroed(0x200 - result.len()));
140 result.put_u32(value.uid);
141 result.put_u32(value.gid);
142 result.freeze()
143 }
144}
145
146impl From<SataChangeOwnerPacketBody> for Bytes {
147 fn from(value: SataChangeOwnerPacketBody) -> Self {
148 Self::from(&value)
149 }
150}
151
152const SATA_CHANGE_OWNER_PACKET_BODY_FIELDS: &[NamedField<'static>] = &[
153 NamedField::new("path"),
154 NamedField::new("uid"),
155 NamedField::new("gid"),
156];
157
158impl Structable for SataChangeOwnerPacketBody {
159 fn definition(&self) -> StructDef<'_> {
160 StructDef::new_static(
161 "SataChangeOwnerPacketBody",
162 Fields::Named(SATA_CHANGE_OWNER_PACKET_BODY_FIELDS),
163 )
164 }
165}
166
167impl Valuable for SataChangeOwnerPacketBody {
168 fn as_value(&self) -> Value<'_> {
169 Value::Structable(self)
170 }
171
172 fn visit(&self, visitor: &mut dyn Visit) {
173 visitor.visit_named_fields(&NamedValues::new(
174 SATA_CHANGE_OWNER_PACKET_BODY_FIELDS,
175 &[
176 Valuable::as_value(&self.path),
177 Valuable::as_value(&self.uid),
178 Valuable::as_value(&self.gid),
179 ],
180 ));
181 }
182}