Add essential packets
This commit is contained in:
parent
286ace55b4
commit
7458eac931
6 changed files with 190 additions and 55 deletions
|
|
@ -4,13 +4,15 @@ use hex::ToHex;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::macros::id_alias;
|
||||
|
||||
// TODO Use base64 representation instead
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
||||
pub struct Id(#[serde(with = "hex")] [u8; 32]);
|
||||
struct Id(#[serde(with = "hex")] [u8; 32]);
|
||||
|
||||
impl Id {
|
||||
pub fn of(str: &str) -> Self {
|
||||
fn of(str: &str) -> Self {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(str);
|
||||
Self(hasher.finalize().into())
|
||||
|
|
@ -22,3 +24,8 @@ impl fmt::Display for Id {
|
|||
write!(f, "{}", self.0.encode_hex::<String>())
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent misuse of one id as another by only making the aliases public.
|
||||
id_alias!(MessageId);
|
||||
id_alias!(SessionId);
|
||||
id_alias!(Identity);
|
||||
|
|
|
|||
|
|
@ -1,44 +1,9 @@
|
|||
mod id;
|
||||
mod macros;
|
||||
mod message;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub mod packets;
|
||||
mod user;
|
||||
|
||||
pub use self::id::*;
|
||||
use self::macros::packets;
|
||||
pub use self::message::*;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct HelloCmd {
|
||||
pub id: Id,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum HelloRpl {
|
||||
Success { id: Id },
|
||||
InvalidName { reason: String },
|
||||
NameAlreadyUsed,
|
||||
}
|
||||
|
||||
// Create a Cmd enum for all commands and a Rpl enum for all replies, as well as
|
||||
// TryFrom impls for the individual command and reply structs.
|
||||
packets! {
|
||||
Hello(HelloCmd, HelloRpl),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum Packet {
|
||||
Cmd {
|
||||
id: u64,
|
||||
#[serde(flatten)]
|
||||
cmd: Cmd,
|
||||
},
|
||||
Rpl {
|
||||
id: u64,
|
||||
#[serde(flatten)]
|
||||
rpl: Rpl,
|
||||
},
|
||||
}
|
||||
pub use self::user::*;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,36 @@
|
|||
// Use `pub(crate) use <macro_name>` to make a macro importable from elsewhere.
|
||||
// See https://stackoverflow.com/a/31749071
|
||||
|
||||
macro_rules! id_alias {
|
||||
($name:ident) => {
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
||||
pub struct $name(Id);
|
||||
|
||||
impl $name {
|
||||
pub fn of(str: &str) -> Self {
|
||||
Self(Id::of(str))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use id_alias;
|
||||
|
||||
macro_rules! packets {
|
||||
( $( $name:ident($cmd:ident, $rpl:ident), )* ) => {
|
||||
(
|
||||
$( cmd $cmdName:ident($cmd:ident, $rpl:ident), )* // Commands with reply
|
||||
$( ntf $ntfName:ident($ntf:ident), )* // Notifications
|
||||
) => {
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "name", content = "data")]
|
||||
pub enum Cmd {
|
||||
$( $name($cmd), )*
|
||||
$( $cmdName($cmd), )*
|
||||
}
|
||||
|
||||
$(
|
||||
|
|
@ -11,7 +38,7 @@ macro_rules! packets {
|
|||
type Error = ();
|
||||
fn try_from(cmd: Cmd) -> Result<Self, Self::Error> {
|
||||
match cmd {
|
||||
Cmd::$name(val) => Ok(val),
|
||||
Cmd::$cmdName(val) => Ok(val),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +48,7 @@ macro_rules! packets {
|
|||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "name", content = "data")]
|
||||
pub enum Rpl {
|
||||
$( $name($rpl), )*
|
||||
$( $cmdName($rpl), )*
|
||||
}
|
||||
|
||||
$(
|
||||
|
|
@ -29,7 +56,25 @@ macro_rules! packets {
|
|||
type Error = ();
|
||||
fn try_from(rpl: Rpl) -> Result<Self, Self::Error> {
|
||||
match rpl {
|
||||
Rpl::$name(val) => Ok(val),
|
||||
Rpl::$cmdName(val) => Ok(val),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "name", content = "data")]
|
||||
pub enum Ntf {
|
||||
$( $ntfName($ntf), )*
|
||||
}
|
||||
|
||||
$(
|
||||
impl std::convert::TryFrom<Ntf> for $ntf {
|
||||
type Error = ();
|
||||
fn try_from(ntf: Ntf) -> Result<Self, Self::Error> {
|
||||
match ntf {
|
||||
Ntf::$ntfName(val) => Ok(val),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +83,4 @@ macro_rules! packets {
|
|||
};
|
||||
}
|
||||
|
||||
// Make macro importable from elsewhere
|
||||
// See https://stackoverflow.com/a/31749071
|
||||
pub(crate) use packets;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Id;
|
||||
use crate::{ Identity, MessageId};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Message {
|
||||
pub pred: Option<Id>,
|
||||
pub parent: Option<Id>,
|
||||
pub identity: Id,
|
||||
pub pred: Option<MessageId>,
|
||||
pub parent: Option<MessageId>,
|
||||
pub identity: Identity,
|
||||
pub nick: String,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn id(&self) -> Id {
|
||||
pub fn id(&self) -> MessageId {
|
||||
let pred = match self.pred {
|
||||
Some(id) => format!("{id}"),
|
||||
None => "none".to_string(),
|
||||
|
|
@ -22,9 +22,9 @@ impl Message {
|
|||
None => "none".to_string(),
|
||||
};
|
||||
let identity = self.identity;
|
||||
let nick = Id::of(&self.nick);
|
||||
let content = Id::of(&self.content);
|
||||
let nick = MessageId::of(&self.nick);
|
||||
let content = MessageId::of(&self.content);
|
||||
let str = format!("message {pred} {parent} {identity} {nick} {content}");
|
||||
Id::of(&str)
|
||||
MessageId::of(&str)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
110
cove-core/src/packets.rs
Normal file
110
cove-core/src/packets.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::macros::packets;
|
||||
use crate::{Message, MessageId, User};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct HelloCmd {
|
||||
pub nick: String,
|
||||
pub identity: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum HelloRpl {
|
||||
Success {
|
||||
you: User,
|
||||
others: Vec<User>,
|
||||
last_message: MessageId,
|
||||
},
|
||||
NickTooLong,
|
||||
IdentityTooLong,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct NickCmd {
|
||||
pub nick: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum NickRpl {
|
||||
Success { you: User },
|
||||
NickTooLong,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct SendCmd {
|
||||
pub parent: Option<MessageId>,
|
||||
pub nick: Option<String>,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum SendRpl {
|
||||
Success { message: Message },
|
||||
NickTooLong,
|
||||
ContentTooLong,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct WhoCmd;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct WhoRpl {
|
||||
you: User,
|
||||
others: Vec<User>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct JoinNtf {
|
||||
user: User,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct NickNtf {
|
||||
user: User,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct PartNtf {
|
||||
user: User,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct SendNtf {
|
||||
message: Message,
|
||||
}
|
||||
|
||||
// Create a Cmd enum for all commands, a Rpl enum for all replies and a Ntf enum
|
||||
// for all notifications, as well as TryFrom impls for the individual structs.
|
||||
packets! {
|
||||
cmd Hello(HelloCmd, HelloRpl),
|
||||
cmd Nick(NickCmd, NickRpl),
|
||||
cmd Send(SendCmd, SendRpl),
|
||||
cmd Who(WhoCmd, WhoRpl),
|
||||
ntf Join(JoinNtf),
|
||||
ntf Nick(NickNtf),
|
||||
ntf Part(PartNtf),
|
||||
ntf Send(SendNtf),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum Packet {
|
||||
Cmd {
|
||||
id: u64,
|
||||
#[serde(flatten)]
|
||||
cmd: Cmd,
|
||||
},
|
||||
Rpl {
|
||||
id: u64,
|
||||
#[serde(flatten)]
|
||||
rpl: Rpl,
|
||||
},
|
||||
Ntf {
|
||||
#[serde(flatten)]
|
||||
ntf: Ntf,
|
||||
},
|
||||
}
|
||||
10
cove-core/src/user.rs
Normal file
10
cove-core/src/user.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Identity, SessionId};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct User {
|
||||
nick: String,
|
||||
identity: Identity,
|
||||
sid: SessionId,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue