feat: v0.1.8

This commit is contained in:
2023-11-05 19:38:19 +08:00
parent 349c166a91
commit 7667e17240
5 changed files with 158 additions and 4 deletions

2
Cargo.lock generated
View File

@@ -571,7 +571,7 @@ dependencies = [
[[package]]
name = "room-rs"
version = "0.1.7"
version = "0.1.8"
dependencies = [
"chrono",
"futures-channel",

View File

@@ -1,6 +1,6 @@
[package]
name = "room-rs"
version = "0.1.7"
version = "0.1.8"
authors = ["Hatter Jiang@Pixelbook <jht5945@gmail.com>"]
edition = "2018"

View File

@@ -25,6 +25,11 @@ Enter room:
}
```
or
```
.enter room-id:<roomid> client-id:<clientid>
```
Exit room:
```json
{
@@ -32,6 +37,11 @@ Exit room:
}
```
or
```
.exit
```
Destroy room:
```json
{
@@ -39,6 +49,11 @@ Destroy room:
}
```
or
```
.destroy
```
List room peers:
```json
{
@@ -46,6 +61,11 @@ List room peers:
}
```
or
```
.list-peers
```
Broadcast room message:
```json
{
@@ -54,6 +74,11 @@ Broadcast room message:
}
```
or
```
.broadcast data:<message>
```
Send room peer message:
```json
{
@@ -63,6 +88,11 @@ Send room peer message:
}
```
or
```
.peer peer-id:<peerclientid> data:<message>
```
Test with command line:
> WebSocket cat: https://www.npmjs.com/package/wscat

View File

@@ -163,7 +163,7 @@ fn handle_text_message(handle_context: &mut HandleContext, tx: &Tx, addr: Socket
}
}
let room_message = match serde_json::from_str::<RoomMessage>(&msg) {
let room_message = match RoomMessage::parse(&msg) {
Ok(room_message) => room_message,
Err(e) => {
warning!("Parse message: from: {:?} - {:?}, failed: {}", handle_context.room_id, handle_context.client_id, e);

View File

@@ -1,7 +1,9 @@
use rust_util::XResult;
use serde::{Deserialize, Serialize};
use crate::types::{Tx, TxSendMessage};
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum RoomMessageType {
#[serde(rename = "Enter")]
CreateOrEnter,
@@ -39,6 +41,21 @@ pub struct RoomMessage {
pub data: Option<String>,
}
impl RoomMessage {
pub fn parse(msg: &str) -> XResult<Self> {
if let Ok(room_message) = serde_json::from_str::<RoomMessage>(msg) {
return Ok(room_message);
}
if msg.starts_with('.') {
let msg_parts = parse_message_parts(msg);
if !msg_parts.is_empty() {
return parse_message_parts_to_room_message(&msg_parts);
}
}
simple_error!("Not valid room message.")
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RoomMessageDown {
@@ -138,3 +155,110 @@ impl RoomMessageDown {
}
}
}
fn parse_message_parts_to_room_message(msg_parts: &[String]) -> XResult<RoomMessage> {
let room_message_type = get_room_message_type(&msg_parts[0])?;
let mut message_id = None;
let mut room_id = None;
let mut client_id = None;
let mut peer_id = None;
let mut data = None;
msg_parts.iter().skip(1).for_each(|part| {
let before_colon = part.chars().take_while(|c| *c != ':').collect::<String>();
let after_colon = part.chars().skip_while(|c| *c != ':').skip(1).collect::<String>();
match before_colon.as_str() {
"message_id" | "message-id" => { message_id = Some(after_colon); }
"room_id" | "room-id" => { room_id = Some(after_colon); }
"client_id" | "client-id" => { client_id = Some(after_colon); }
"peer_id" | "peer-id" => { peer_id = Some(after_colon); }
"data" => { data = Some(after_colon); }
_ => debugging!("Unknown key: {}", before_colon),
}
});
Ok(RoomMessage {
r#type: room_message_type,
message_id,
room_id,
client_id,
peer_id,
data,
})
}
pub fn get_room_message_type(first_part: &str) -> XResult<RoomMessageType> {
let room_message_type = match first_part {
"create-or-enter" | "enter" => RoomMessageType::CreateOrEnter,
"exit" => RoomMessageType::Exit,
"destroy" => RoomMessageType::Destroy,
"listpeers" | "list-peers" => RoomMessageType::ListPeers,
"broadcast" => RoomMessageType::Broadcast,
"peer" => RoomMessageType::Peer,
_ => return simple_error!("Unknown message type: {}", first_part),
};
Ok(room_message_type)
}
fn parse_message_parts(msg: &str) -> Vec<String> {
let mut msg_parts = vec![];
let mut in_quote = false;
let mut is_back_slash = false;
let mut last_part = vec![];
for c in msg.chars().skip(1) {
if is_back_slash {
last_part.push(c);
is_back_slash = false;
continue;
}
match c {
' ' if in_quote => {
last_part.push(c);
}
' ' => {
if !last_part.is_empty() {
msg_parts.push(last_part.iter().collect::<String>());
last_part.clear();
}
}
'\\' => {
is_back_slash = true;
}
'\'' => {
in_quote = !in_quote;
}
_ => {
last_part.push(c);
}
}
}
if !last_part.is_empty() {
msg_parts.push(last_part.iter().collect::<String>());
}
msg_parts
}
#[test]
fn test_room_message_parse() {
let room_message = RoomMessage::parse(".enter").unwrap();
assert_eq!(RoomMessageType::CreateOrEnter, room_message.r#type);
assert_eq!(None, room_message.message_id);
assert_eq!(None, room_message.room_id);
assert_eq!(None, room_message.client_id);
assert_eq!(None, room_message.peer_id);
assert_eq!(None, room_message.data);
let room_message = RoomMessage::parse(".enter message-id:123 room-id:'ROOM ID'").unwrap();
assert_eq!(RoomMessageType::CreateOrEnter, room_message.r#type);
assert_eq!(Some("123".to_string()), room_message.message_id);
assert_eq!(Some("ROOM ID".to_string()), room_message.room_id);
assert_eq!(None, room_message.client_id);
assert_eq!(None, room_message.peer_id);
assert_eq!(None, room_message.data);
let room_message = RoomMessage::parse(".peer client-id:'CLIENT ID' peer_id:PEER 'data:DATA ---'").unwrap();
assert_eq!(RoomMessageType::Peer, room_message.r#type);
assert_eq!(None, room_message.message_id);
assert_eq!(None, room_message.room_id);
assert_eq!(Some("CLIENT ID".to_string()), room_message.client_id);
assert_eq!(Some("PEER".to_string()), room_message.peer_id);
assert_eq!(Some("DATA ---".to_string()), room_message.data);
}