use crate::{errors::NetworkParseError, fsemul::pcfs::errors::PcfsApiError};
use bytes::{Bytes, BytesMut};
use std::ffi::CStr;
use valuable::{Fields, NamedField, NamedValues, StructDef, Structable, Valuable, Value, Visit};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SataRenamePacketBody {
source_path: String,
dest_path: String,
}
impl SataRenamePacketBody {
pub fn new(source_path: String, dest_path: String) -> Result<Self, PcfsApiError> {
if source_path.len() > 511 {
return Err(PcfsApiError::PathTooLong(source_path));
}
if dest_path.len() > 511 {
return Err(PcfsApiError::PathTooLong(dest_path));
}
Ok(Self {
source_path,
dest_path,
})
}
#[must_use]
pub fn source_path(&self) -> &str {
self.source_path.as_str()
}
#[must_use]
pub fn dest_path(&self) -> &str {
self.dest_path.as_str()
}
pub fn set_source_path(&mut self, new_path: String) -> Result<(), PcfsApiError> {
if new_path.len() > 511 {
return Err(PcfsApiError::PathTooLong(new_path));
}
self.source_path = new_path;
Ok(())
}
pub fn set_dest_path(&mut self, new_path: String) -> Result<(), PcfsApiError> {
if new_path.len() > 511 {
return Err(PcfsApiError::PathTooLong(new_path));
}
self.dest_path = new_path;
Ok(())
}
}
impl TryFrom<Bytes> for SataRenamePacketBody {
type Error = NetworkParseError;
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
if value.len() < 0x400 {
return Err(NetworkParseError::FieldNotLongEnough(
"SataRenamePacketBody",
"Body",
0x400,
value.len(),
value,
));
}
if value.len() > 0x400 {
return Err(NetworkParseError::UnexpectedTrailer(
"SataRenamePacketBody",
value.slice(0x400..),
));
}
let source_path_c_str =
CStr::from_bytes_until_nul(&value[..0x200]).map_err(NetworkParseError::BadCString)?;
let dest_path_c_str =
CStr::from_bytes_until_nul(&value[0x200..]).map_err(NetworkParseError::BadCString)?;
Ok(Self {
source_path: source_path_c_str.to_str()?.to_owned(),
dest_path: dest_path_c_str.to_str()?.to_owned(),
})
}
}
impl From<&SataRenamePacketBody> for Bytes {
fn from(value: &SataRenamePacketBody) -> Self {
let mut result = BytesMut::with_capacity(0x400);
result.extend_from_slice(value.source_path.as_bytes());
result.extend(BytesMut::zeroed(0x200 - result.len()));
result.extend_from_slice(value.dest_path.as_bytes());
result.extend(BytesMut::zeroed(0x400 - result.len()));
result.freeze()
}
}
impl From<SataRenamePacketBody> for Bytes {
fn from(value: SataRenamePacketBody) -> Self {
Self::from(&value)
}
}
const SATA_RENAME_PACKET_BODY_FIELDS: &[NamedField<'static>] =
&[NamedField::new("source_path"), NamedField::new("dest_path")];
impl Structable for SataRenamePacketBody {
fn definition(&self) -> StructDef<'_> {
StructDef::new_static(
"SataRenamePacketBody",
Fields::Named(SATA_RENAME_PACKET_BODY_FIELDS),
)
}
}
impl Valuable for SataRenamePacketBody {
fn as_value(&self) -> Value<'_> {
Value::Structable(self)
}
fn visit(&self, visitor: &mut dyn Visit) {
visitor.visit_named_fields(&NamedValues::new(
SATA_RENAME_PACKET_BODY_FIELDS,
&[
Valuable::as_value(&self.source_path),
Valuable::as_value(&self.dest_path),
],
));
}
}