summaryrefslogtreecommitdiff
path: root/src/packet
diff options
context:
space:
mode:
Diffstat (limited to 'src/packet')
-rw-r--r--src/packet/mod.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/packet/mod.rs b/src/packet/mod.rs
new file mode 100644
index 0000000..b918dc2
--- /dev/null
+++ b/src/packet/mod.rs
@@ -0,0 +1,59 @@
+// Copyright 2022-2024 Gabriel Bjørnager Jensen.
+
+use crate::checksum::Checksum;
+use crate::deserialise::{Deserialise, DStream};
+use crate::error::Error;
+use crate::serialise::{SStream, Serialise};
+
+use std::mem::size_of;
+
+#[derive(Clone, Debug)]
+pub struct Packet<T: Deserialise + Serialise> {
+ message: T,
+ checksum: Checksum,
+}
+
+impl<T: Deserialise + Serialise> Packet<T> {
+ #[must_use]
+ pub fn encode(message: T) -> Box<[u8]> {
+ let checksum = Checksum::new(&message);
+ let packet = Self { message, checksum };
+
+ SStream::from(&packet).into()
+ }
+
+ pub fn decode(data: &[u8]) -> Result<T, Error> {
+ if data.len() > size_of::<Self>() {
+ return Err(Error::InvalidPackageLength { len: data.len(), ok_len: size_of::<Self>() });
+ }
+
+ let mut data = DStream::from(data);
+
+ let packet = Self::deserialise(&mut data)
+ .map_err(|e| Error::DeserialiseFailure { source: e })?;
+
+ let checksum = Checksum::new(&packet.message);
+
+ if packet.checksum != checksum {
+ return Err(Error::PackageChecksumMismatch { sum: packet.checksum, ok_sum: checksum });
+ }
+
+ Ok(packet.message)
+ }
+}
+
+impl<T: Deserialise + Serialise> Deserialise for Packet<T> {
+ fn deserialise(stream: &mut DStream) -> Result<Self, Box<dyn std::error::Error>> {
+ Ok(Self {
+ message: Deserialise::deserialise(stream)?,
+ checksum: Deserialise::deserialise(stream)?,
+ })
+ }
+}
+
+impl<T: Deserialise + Serialise> Serialise for Packet<T> {
+ fn serialise(&self, stream: &mut SStream) {
+ self.message.serialise(stream);
+ self.checksum.serialise(stream);
+ }
+}