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

1//! Definitions for the `SetFilePosition` packet type, and it's response types.
2//!
3//! This can change the location of an already open file, similar to what you'd
4//! do before reading a file or writing a file.
5
6use crate::{errors::NetworkParseError, fsemul::pcfs::sata::proto::MoveToFileLocation};
7use bytes::{Buf, BufMut, Bytes, BytesMut};
8use valuable::{Fields, NamedField, NamedValues, StructDef, Structable, Valuable, Value, Visit};
9
10/// A packet to set the position of an already open file.
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct SataSetFilePositionPacketBody {
13	handle: i32,
14	move_to_pointer: MoveToFileLocation,
15}
16
17impl SataSetFilePositionPacketBody {
18	/// Create a new set file position packet.
19	#[must_use]
20	pub const fn new(file_descriptor: i32, move_to: MoveToFileLocation) -> Self {
21		Self {
22			handle: file_descriptor,
23			move_to_pointer: move_to,
24		}
25	}
26
27	#[must_use]
28	pub const fn file_descriptor(&self) -> i32 {
29		self.handle
30	}
31
32	pub const fn set_file_descriptor(&mut self, new_fd: i32) {
33		self.handle = new_fd;
34	}
35
36	#[must_use]
37	pub const fn move_to_pointer(&self) -> MoveToFileLocation {
38		self.move_to_pointer
39	}
40
41	pub const fn set_move_to_pointer(&mut self, new_move: MoveToFileLocation) {
42		self.move_to_pointer = new_move;
43	}
44}
45
46impl From<&SataSetFilePositionPacketBody> for Bytes {
47	fn from(value: &SataSetFilePositionPacketBody) -> Self {
48		let mut buff = BytesMut::with_capacity(8);
49
50		buff.put_i32(value.handle);
51		buff.put_u32(u32::from(value.move_to_pointer));
52
53		buff.freeze()
54	}
55}
56
57impl From<SataSetFilePositionPacketBody> for Bytes {
58	fn from(value: SataSetFilePositionPacketBody) -> Self {
59		Self::from(&value)
60	}
61}
62
63impl TryFrom<Bytes> for SataSetFilePositionPacketBody {
64	type Error = NetworkParseError;
65
66	fn try_from(mut value: Bytes) -> Result<Self, Self::Error> {
67		if value.len() < 8 {
68			return Err(NetworkParseError::FieldNotLongEnough(
69				"SataSetFilePosition",
70				"Body",
71				8,
72				value.len(),
73				value,
74			));
75		}
76		// Packets _can_ come with an extra padded 4 bytes...
77		if value.len() > 12 {
78			return Err(NetworkParseError::UnexpectedTrailer(
79				"SataSetFilePosition",
80				value.slice(12..),
81			));
82		}
83
84		let handle = value.get_i32();
85		let move_to_ptr = value.get_u32();
86
87		Ok(Self {
88			handle,
89			move_to_pointer: MoveToFileLocation::try_from(move_to_ptr)?,
90		})
91	}
92}
93
94const SATA_SET_FILE_POSITION_PACKET_BODY_FIELDS: &[NamedField<'static>] = &[
95	NamedField::new("handle"),
96	NamedField::new("move_to_pointer"),
97];
98
99impl Structable for SataSetFilePositionPacketBody {
100	fn definition(&self) -> StructDef<'_> {
101		StructDef::new_static(
102			"SataSetFilePositionPacketBody",
103			Fields::Named(SATA_SET_FILE_POSITION_PACKET_BODY_FIELDS),
104		)
105	}
106}
107
108impl Valuable for SataSetFilePositionPacketBody {
109	fn as_value(&self) -> Value<'_> {
110		Value::Structable(self)
111	}
112
113	fn visit(&self, visitor: &mut dyn Visit) {
114		visitor.visit_named_fields(&NamedValues::new(
115			SATA_SET_FILE_POSITION_PACKET_BODY_FIELDS,
116			&[
117				Valuable::as_value(&self.handle),
118				Valuable::as_value(&self.move_to_pointer),
119			],
120		));
121	}
122}