aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2021-05-01 23:34:55 +0000
committerFuwn <[email protected]>2021-05-01 23:34:55 +0000
commitcb58dab1828f847ffdf51e336c34bc71d973706d (patch)
tree7f8bf76c58befda2b901d26ad4bc1980fa9e399f /src
parentci(actions): fix rust action not running on changes performed on the src dire... (diff)
downloadwhirl-cb58dab1828f847ffdf51e336c34bc71d973706d.tar.xz
whirl-cb58dab1828f847ffdf51e336c34bc71d973706d.zip
feat(cmds): trait based commands
This commit adds the abiltity to implement a series of given traits for a command, where each command should implement **at least** one of these traits; Parsable, ParsableWithArguments, Creatable. These changed are put in place to ensure that when implementing a command, the proper methods are implemented in the proper format.
Diffstat (limited to 'src')
-rw-r--r--src/server/cmd/commands/buddy_list.rs14
-rw-r--r--src/server/cmd/commands/redirect_id.rs9
-rw-r--r--src/server/cmd/commands/room_id_request.rs6
-rw-r--r--src/server/cmd/commands/subscribe_distance.rs6
-rw-r--r--src/server/cmd/commands/subscribe_room.rs6
-rw-r--r--src/server/cmd/commands/teleport.rs6
-rw-r--r--src/server/cmd/commands/text.rs39
-rw-r--r--src/server/cmd/extendable.rs18
-rw-r--r--src/server/cmd/mod.rs1
-rw-r--r--src/server/distributor.rs1
-rw-r--r--src/server/hub.rs3
11 files changed, 82 insertions, 27 deletions
diff --git a/src/server/cmd/commands/buddy_list.rs b/src/server/cmd/commands/buddy_list.rs
index 2601f1b..7e9722a 100644
--- a/src/server/cmd/commands/buddy_list.rs
+++ b/src/server/cmd/commands/buddy_list.rs
@@ -5,15 +5,18 @@ use std::str::from_utf8;
use bytes::{BufMut, BytesMut};
-use crate::server::cmd::constants::BUDDYLISTNOTIFY;
+use crate::server::cmd::{
+ constants::BUDDYLISTNOTIFY,
+ extendable::{Creatable, Parsable},
+};
#[derive(Clone)]
pub struct BuddyList {
pub buddy: String,
pub add: i8,
}
-impl BuddyList {
- pub fn parse(data: Vec<u8>) -> Self {
+impl Parsable for BuddyList {
+ fn parse(data: Vec<u8>) -> Self {
Self {
buddy: from_utf8(&data[4..data[0] as usize - 1])
.unwrap()
@@ -23,8 +26,9 @@ impl BuddyList {
add: data[data[0] as usize - 1] as i8,
}
}
-
- pub fn create(self) -> Vec<u8> {
+}
+impl Creatable for BuddyList {
+ fn create(self) -> Vec<u8> {
let mut command = BytesMut::new();
// Header
diff --git a/src/server/cmd/commands/redirect_id.rs b/src/server/cmd/commands/redirect_id.rs
index 5153c38..ebfa95b 100644
--- a/src/server/cmd/commands/redirect_id.rs
+++ b/src/server/cmd/commands/redirect_id.rs
@@ -3,15 +3,18 @@
use bytes::{BufMut, BytesMut};
-use crate::{config::Config, server::cmd::constants::REDIRID};
+use crate::{
+ config::Config,
+ server::cmd::{constants::REDIRID, extendable::Creatable},
+};
#[derive(Debug)]
pub struct RedirectId {
pub room_name: String,
pub room_number: i8,
}
-impl RedirectId {
- pub fn create(self) -> Vec<u8> {
+impl Creatable for RedirectId {
+ fn create(self) -> Vec<u8> {
let mut command = BytesMut::new();
// Header
diff --git a/src/server/cmd/commands/room_id_request.rs b/src/server/cmd/commands/room_id_request.rs
index 812374c..cc8dbeb 100644
--- a/src/server/cmd/commands/room_id_request.rs
+++ b/src/server/cmd/commands/room_id_request.rs
@@ -3,12 +3,14 @@
use std::str::from_utf8;
+use crate::server::cmd::extendable::Parsable;
+
#[derive(Debug)]
pub struct RoomIdRequest {
pub room_name: String,
}
-impl RoomIdRequest {
- pub fn parse(data: Vec<u8>) -> Self {
+impl Parsable for RoomIdRequest {
+ fn parse(data: Vec<u8>) -> Self {
Self {
room_name: from_utf8(&data[4..data[0] as usize]).unwrap().to_string(),
}
diff --git a/src/server/cmd/commands/subscribe_distance.rs b/src/server/cmd/commands/subscribe_distance.rs
index 3338573..66f4241 100644
--- a/src/server/cmd/commands/subscribe_distance.rs
+++ b/src/server/cmd/commands/subscribe_distance.rs
@@ -4,13 +4,15 @@
use byteorder::{BigEndian, ReadBytesExt};
use bytes::{Buf, BytesMut};
+use crate::server::cmd::extendable::Parsable;
+
#[derive(Debug)]
pub struct SubscribeDistance {
pub distance: i16,
pub room_number: i16,
}
-impl SubscribeDistance {
- pub fn parse(data: Vec<u8>) -> Self {
+impl Parsable for SubscribeDistance {
+ fn parse(data: Vec<u8>) -> Self {
// https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8
let mut data = BytesMut::from(data.as_slice()).reader();
diff --git a/src/server/cmd/commands/subscribe_room.rs b/src/server/cmd/commands/subscribe_room.rs
index 2c99cbb..d936fff 100644
--- a/src/server/cmd/commands/subscribe_room.rs
+++ b/src/server/cmd/commands/subscribe_room.rs
@@ -4,6 +4,8 @@
use byteorder::{BigEndian, ReadBytesExt};
use bytes::{Buf, BytesMut};
+use crate::server::cmd::extendable::Parsable;
+
#[derive(Debug)]
pub struct SubscribeRoom {
pub room_number: i8,
@@ -12,8 +14,8 @@ pub struct SubscribeRoom {
pub z: f32,
pub distance: f32,
}
-impl SubscribeRoom {
- pub fn parse(data: Vec<u8>) -> Self {
+impl Parsable for SubscribeRoom {
+ fn parse(data: Vec<u8>) -> Self {
// https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8
let mut data = BytesMut::from(data.as_slice()).reader();
diff --git a/src/server/cmd/commands/teleport.rs b/src/server/cmd/commands/teleport.rs
index 2f7b7c5..7a2b55e 100644
--- a/src/server/cmd/commands/teleport.rs
+++ b/src/server/cmd/commands/teleport.rs
@@ -4,6 +4,8 @@
use byteorder::{BigEndian, ReadBytesExt};
use bytes::{Buf, BytesMut};
+use crate::server::cmd::extendable::Parsable;
+
#[derive(Debug)]
pub struct Teleport {
pub room_id: i8,
@@ -14,8 +16,8 @@ pub struct Teleport {
pub z: f32,
pub direction: f32,
}
-impl Teleport {
- pub fn parse(data: Vec<u8>) -> Self {
+impl Parsable for Teleport {
+ fn parse(data: Vec<u8>) -> Self {
// https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8
let mut data = BytesMut::from(data.as_slice()).reader();
diff --git a/src/server/cmd/commands/text.rs b/src/server/cmd/commands/text.rs
index 3029eac..047dedf 100644
--- a/src/server/cmd/commands/text.rs
+++ b/src/server/cmd/commands/text.rs
@@ -5,21 +5,17 @@ use std::str::from_utf8;
use bytes::{BufMut, BytesMut};
-use crate::server::cmd::constants::TEXT;
+use crate::server::cmd::{
+ constants::TEXT,
+ extendable::{Creatable, ParsableWithArguments},
+};
pub struct Text {
pub sender: String,
pub content: String,
}
-impl Text {
- pub fn parse(data: Vec<u8>, username: &str) -> Self {
- Self {
- sender: username.to_string(),
- content: from_utf8(&data[6..]).unwrap().to_string(),
- }
- }
-
- pub fn create(self) -> Vec<u8> {
+impl Creatable for Text {
+ fn create(self) -> Vec<u8> {
let mut command = BytesMut::new();
// Header
@@ -44,3 +40,26 @@ impl Text {
command_as_vec
}
}
+impl ParsableWithArguments for Text {
+ /// The first and only element of `args` *should* be the username of the sender.
+ ///
+ /// There isn't anything currently stopping someone from passing some other value so that might be
+ /// annoying at times.
+ ///
+ /// Realistically, this method is mostly static so the username will *always* be passed properly
+ /// unless someone intentionally commits breaking changes on purpose regarding what is passed to
+ /// to this method where called.
+ ///
+ /// It would be neat to have some sort of ability to statically check if the `args` argument
+ /// contains x number of elements at compile time or something of the sort but the Rust RFC is
+ /// probably not focused on that.
+ ///
+ /// So, right now, trust is in the developers' hands to make sure to pass the right -- number
+ /// -- of elements to `args`.
+ fn parse(data: Vec<u8>, args: &[&str]) -> Self {
+ Self {
+ sender: args[0].to_string(),
+ content: from_utf8(&data[6..]).unwrap().to_string(),
+ }
+ }
+}
diff --git a/src/server/cmd/extendable.rs b/src/server/cmd/extendable.rs
new file mode 100644
index 0000000..e6f3c2b
--- /dev/null
+++ b/src/server/cmd/extendable.rs
@@ -0,0 +1,18 @@
+// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective
+// SPDX-License-Identifier: GPL-3.0-only
+
+pub trait Parsable {
+ fn parse(data: Vec<u8>) -> Self;
+}
+
+pub trait Creatable {
+ fn create(self) -> Vec<u8>;
+}
+
+/// Having to do this makes me with there was operator overloading in Rust.
+///
+/// I *could* do this with a macro but since Text is the only struct that
+/// implements this trait, it shouldn't be that big of a deal.
+pub trait ParsableWithArguments {
+ fn parse(data: Vec<u8>, args: &[&str]) -> Self;
+}
diff --git a/src/server/cmd/mod.rs b/src/server/cmd/mod.rs
index 3e019d3..ef91de7 100644
--- a/src/server/cmd/mod.rs
+++ b/src/server/cmd/mod.rs
@@ -4,5 +4,6 @@
pub mod commands;
pub mod constants;
+pub mod extendable;
mod set_parser;
mod structure;
diff --git a/src/server/distributor.rs b/src/server/distributor.rs
index 8023514..cc8cfac 100644
--- a/src/server/distributor.rs
+++ b/src/server/distributor.rs
@@ -33,6 +33,7 @@ use crate::{
text::Text,
},
constants::*,
+ extendable::{Creatable, Parsable},
},
interaction::{peer::Peer, shared::Shared},
net::{constants::VAR_USERNAME, property_parser::parse_network_property},
diff --git a/src/server/hub.rs b/src/server/hub.rs
index 58e5989..a61e0cc 100644
--- a/src/server/hub.rs
+++ b/src/server/hub.rs
@@ -30,6 +30,7 @@ use crate::{
text::Text,
},
constants::*,
+ extendable::{Creatable, Parsable, ParsableWithArguments},
},
interaction::{peer::Peer, shared::Shared},
net::{constants::VAR_USERNAME, property_parser::parse_network_property},
@@ -112,7 +113,7 @@ impl Server for Hub {
trace!("received session exit from {}", username); break;
}
TEXT => {
- let text = Text::parse(msg.to_vec(), &username);
+ let text = Text::parse(msg.to_vec(), &[&username]);
trace!("received text from {}:{}", username, text.content);
{