anachro_icd/component.rs
1//! # Client Messages
2//!
3//! These are messages that are sent FROM the peripheral
4//! Component/Client, TO the central Arbitrator.
5//!
6//! The [`Component` enum](enum.Component.html) is the top level
7//! message sent by Component/Clients.
8
9use crate::{PubSubPath, Version};
10use serde::{Deserialize, Serialize};
11
12/// Component Message
13///
14/// This is the primary message sent FROM the peripheral
15/// Component/Client, TO the central Arbitrator.
16#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
17pub enum Component<'a> {
18 /// Control Messages
19 ///
20 /// These are used to establish or manage the connection
21 /// between the Component/Client and Arbitrator
22 #[serde(borrow)]
23 Control(Control<'a>),
24
25 /// Pub/Sub messages
26 ///
27 /// These are used to send or receive Pub/Sub messages
28 #[serde(borrow)]
29 PubSub(PubSub<'a>),
30}
31
32/// Pub/Sub Message
33///
34/// These messages are used to communicate on the Pub/Sub
35/// communication layer
36#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
37pub struct PubSub<'a> {
38 /// The path in question, common to all message types
39 #[serde(borrow)]
40 pub path: PubSubPath<'a>,
41
42 /// The pub/sub message type
43 pub ty: PubSubType<'a>,
44}
45
46/// Pub/Sub Message Type
47///
48/// The specific kind of pub/sub message
49#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
50pub enum PubSubType<'a> {
51 /// Publish Message
52 ///
53 /// Publish the given message/payload on the given path
54 Pub { payload: &'a [u8] },
55
56 /// Subscribe Message
57 ///
58 /// Subscribe to the given path
59 Sub,
60
61 /// Unsubscribe Message
62 ///
63 /// Unsubscribe to the given path
64 Unsub,
65}
66
67/// Control Messages
68///
69/// These messages are used to communicate on the control layer
70#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
71pub struct Control<'a> {
72 /// Sequence Number
73 ///
74 /// This number is chosen by the Client/Component, and
75 /// will be echoed back by the Arbitrator when replying
76 pub seq: u16,
77
78 /// Control Message Type
79 ///
80 /// The specific control message
81 #[serde(borrow)]
82 pub ty: ControlType<'a>,
83}
84
85/// Control Message Type
86///
87/// The specific kind of Control Message
88#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
89pub enum ControlType<'a> {
90 /// Register Component
91 ///
92 /// This message is used to establish/reset the connection
93 /// between a given client and an Arbitrator
94 #[serde(borrow)]
95 RegisterComponent(ComponentInfo<'a>),
96
97 /// Register PubSubShortID
98 ///
99 /// This message is used to register a path "short code",
100 /// which can use a u16 instead of a full utf-8 path to save
101 /// message bandwidth
102 #[serde(borrow)]
103 RegisterPubSubShortId(PubSubShort<'a>),
104}
105
106/// Information about this Component/Client needed for
107/// registration
108#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
109pub struct ComponentInfo<'a> {
110 /// The name of the Client/Component
111 #[serde(borrow)]
112 pub name: crate::Name<'a>,
113
114 /// The verson of the Client/Component
115 pub version: Version,
116}
117
118/// Pub/Sub Short Code Registration
119#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
120pub struct PubSubShort<'a> {
121 /// The 'long' UTF-8 path to register
122 pub long_name: &'a str,
123
124 /// The 'short' u16 path to register
125 pub short_id: u16,
126}
127
128#[cfg(test)]
129mod test {
130 use super::*;
131 use postcard::{from_bytes, to_stdvec};
132
133 #[test]
134 fn ser_check() {
135 let name = crate::Name::borrow_from_str("cool-board");
136 let version = Version {
137 major: 0,
138 minor: 1,
139 trivial: 0,
140 misc: 123,
141 };
142
143 let msg = Component::Control(Control {
144 seq: 0x0504,
145 ty: ControlType::RegisterComponent(ComponentInfo { name, version }),
146 });
147
148 let ser_msg = to_stdvec(&msg).unwrap();
149 assert_eq!(
150 &ser_msg[..],
151 &[
152 0x00, // Component::Control
153 0x04, 0x05, // seq
154 0x00, // ControlType::RegisterComponent
155 0x0A, b'c', b'o', b'o', b'l', b'-', b'b', b'o', b'a', b'r', b'd', 0x00, 0x01, 0x00,
156 123,
157 ]
158 );
159
160 let deser_msg: Component = from_bytes(&ser_msg).unwrap();
161
162 assert_eq!(msg, deser_msg);
163 }
164}