diff options
| author | Fuwn <[email protected]> | 2021-05-01 23:34:55 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2021-05-01 23:34:55 +0000 |
| commit | cb58dab1828f847ffdf51e336c34bc71d973706d (patch) | |
| tree | 7f8bf76c58befda2b901d26ad4bc1980fa9e399f /src/server | |
| parent | ci(actions): fix rust action not running on changes performed on the src dire... (diff) | |
| download | whirl-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/server')
| -rw-r--r-- | src/server/cmd/commands/buddy_list.rs | 14 | ||||
| -rw-r--r-- | src/server/cmd/commands/redirect_id.rs | 9 | ||||
| -rw-r--r-- | src/server/cmd/commands/room_id_request.rs | 6 | ||||
| -rw-r--r-- | src/server/cmd/commands/subscribe_distance.rs | 6 | ||||
| -rw-r--r-- | src/server/cmd/commands/subscribe_room.rs | 6 | ||||
| -rw-r--r-- | src/server/cmd/commands/teleport.rs | 6 | ||||
| -rw-r--r-- | src/server/cmd/commands/text.rs | 39 | ||||
| -rw-r--r-- | src/server/cmd/extendable.rs | 18 | ||||
| -rw-r--r-- | src/server/cmd/mod.rs | 1 | ||||
| -rw-r--r-- | src/server/distributor.rs | 1 | ||||
| -rw-r--r-- | src/server/hub.rs | 3 |
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); { |