|
@@ -2,6 +2,8 @@ use std::str::FromStr;
|
|
|
|
|
|
use thiserror::Error;
|
|
|
|
|
|
+use aspect_util::prelude::*;
|
|
|
+
|
|
|
use crate::ident::DeviceIdent;
|
|
|
|
|
|
pub const MAX_ARG_BYTE_LEN: usize = 255;
|
|
@@ -21,19 +23,39 @@ pub enum Error {
|
|
|
MalformedDeviceId(String),
|
|
|
}
|
|
|
|
|
|
-#[derive(Clone, Debug)]
|
|
|
-pub enum MessageQueueId {
|
|
|
- /// Device's personal queue.
|
|
|
- Device(DeviceIdent),
|
|
|
+/// Describes a simplex channel from one device to another.
|
|
|
+#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
|
|
+pub struct D2DChannelSpec {
|
|
|
+ pub src: DeviceIdent,
|
|
|
+ pub dest: DeviceIdent,
|
|
|
+}
|
|
|
|
|
|
- /// Device-to-device queue, source -> dest.
|
|
|
- D2D(DeviceIdent, DeviceIdent),
|
|
|
+impl D2DChannelSpec {
|
|
|
+ pub fn new(src: DeviceIdent, dest: DeviceIdent) -> Self {
|
|
|
+ Self { src, dest }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+aspect_util::inst_struct_codec! {
|
|
|
+ D2DChannelSpec {
|
|
|
+ src: DeviceIdent,
|
|
|
+ dest: DeviceIdent
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
+#[derive(Clone, Debug)]
|
|
|
+pub enum MessageQueueId {
|
|
|
/// Homeserver message queue, used for control messages.
|
|
|
Server(String),
|
|
|
|
|
|
- /// Generic queue type, maybe make it application programmable?
|
|
|
+ /// Generic queue type, maybe make it user programmable?
|
|
|
Generic(String),
|
|
|
+
|
|
|
+ /// Device's personal queue.
|
|
|
+ Device(DeviceIdent),
|
|
|
+
|
|
|
+ /// Device-to-device queue, source -> dest.
|
|
|
+ D2D(D2DChannelSpec),
|
|
|
// TODO channel ID, space ID?
|
|
|
}
|
|
|
|
|
@@ -42,26 +64,33 @@ impl FromStr for MessageQueueId {
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
match s.split_once(":") {
|
|
|
- Some((ty_str, arg_str)) => match ty_str {
|
|
|
- "device" => {
|
|
|
- let did = DeviceIdent::from_str(arg_str)
|
|
|
- .map_err(|_| Error::MalformedDeviceId(arg_str.to_owned()))?;
|
|
|
- Ok(MessageQueueId::Device(did))
|
|
|
+ Some((ty_str, arg_str)) => {
|
|
|
+ let arg_len = arg_str.as_bytes().len();
|
|
|
+ if arg_len > MAX_ARG_BYTE_LEN {
|
|
|
+ return Err(Error::ArgTooLong(arg_len));
|
|
|
}
|
|
|
- "d2d" => match arg_str.split_once(",") {
|
|
|
- Some((lhs, rhs)) => {
|
|
|
- let src_id = DeviceIdent::from_str(lhs)
|
|
|
- .map_err(|_| Error::MalformedDeviceId(lhs.to_owned()))?;
|
|
|
- let dest_id = DeviceIdent::from_str(rhs)
|
|
|
- .map_err(|_| Error::MalformedDeviceId(rhs.to_owned()))?;
|
|
|
- Ok(MessageQueueId::D2D(src_id, dest_id))
|
|
|
+
|
|
|
+ match ty_str {
|
|
|
+ "server" => Ok(MessageQueueId::Server(arg_str.to_owned())),
|
|
|
+ "generic" => Ok(MessageQueueId::Generic(arg_str.to_owned())),
|
|
|
+ "device" => {
|
|
|
+ let did = DeviceIdent::from_str(arg_str)
|
|
|
+ .map_err(|_| Error::MalformedDeviceId(arg_str.to_owned()))?;
|
|
|
+ Ok(MessageQueueId::Device(did))
|
|
|
}
|
|
|
- None => Err(Error::Malformed(s.to_owned())),
|
|
|
- },
|
|
|
- "server" => Ok(MessageQueueId::Server(arg_str.to_owned())),
|
|
|
- "generic" => Ok(MessageQueueId::Generic(arg_str.to_owned())),
|
|
|
- _ => Err(Error::UnknownType(s.to_owned())),
|
|
|
- },
|
|
|
+ "d2d" => match arg_str.split_once(",") {
|
|
|
+ Some((lhs, rhs)) => {
|
|
|
+ let src_id = DeviceIdent::from_str(lhs)
|
|
|
+ .map_err(|_| Error::MalformedDeviceId(lhs.to_owned()))?;
|
|
|
+ let dest_id = DeviceIdent::from_str(rhs)
|
|
|
+ .map_err(|_| Error::MalformedDeviceId(rhs.to_owned()))?;
|
|
|
+ Ok(MessageQueueId::D2D(D2DChannelSpec::new(src_id, dest_id)))
|
|
|
+ }
|
|
|
+ None => Err(Error::Malformed(s.to_owned())),
|
|
|
+ },
|
|
|
+ _ => Err(Error::UnknownType(s.to_owned())),
|
|
|
+ }
|
|
|
+ }
|
|
|
None => Err(Error::Malformed(s.to_owned())),
|
|
|
}
|
|
|
}
|
|
@@ -71,9 +100,18 @@ impl ToString for MessageQueueId {
|
|
|
fn to_string(&self) -> String {
|
|
|
match self {
|
|
|
Self::Device(id) => format!("device:{id}"),
|
|
|
- Self::D2D(src_id, dest_id) => format!("d2d:{src_id},{dest_id}"),
|
|
|
+ Self::D2D(D2DChannelSpec { src, dest }) => format!("d2d:{src},{dest}"),
|
|
|
Self::Server(name) => format!("server:{name}"),
|
|
|
Self::Generic(name) => format!("generic:{name}"),
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+aspect_util::inst_enum_codec! {
|
|
|
+ MessageQueueId u8 {
|
|
|
+ 0 => Server(field String),
|
|
|
+ 1 => Generic(field String),
|
|
|
+ 2 => Device(field DeviceIdent),
|
|
|
+ 3 => D2D(field D2DChannelSpec),
|
|
|
+ }
|
|
|
+}
|