ferroui_remote_protocol/ferro_remote_message_guid_attribute.rs
1use crate::guid::Guid;
2use crate::metsys_bson::BsonClass;
3
4/// The identifier of a message class on the wire: the header of every
5/// message carries it, and the receiving end finds the class by it.
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7pub struct FerroRemoteMessageGuidAttribute {
8 guid: Guid,
9}
10
11impl FerroRemoteMessageGuidAttribute {
12 /// The attribute with the identifier of the given text (`Guid.Parse`). A
13 /// text that is not an identifier fails the build of the constant.
14 pub const fn new(guid: &str) -> FerroRemoteMessageGuidAttribute {
15 FerroRemoteMessageGuidAttribute { guid: Guid::parse_const(guid) }
16 }
17
18 pub const fn guid(&self) -> Guid {
19 self.guid
20 }
21}
22
23/// A class that carries the attribute: the counterpart of
24/// `GetCustomAttribute<FerroRemoteMessageGuidAttribute>()` on a type.
25/// [`ferro_remote_message_guid!`](crate::ferro_remote_message_guid) puts the
26/// attribute on a class.
27pub trait FerroRemoteMessage: BsonClass {
28 const ATTRIBUTE: FerroRemoteMessageGuidAttribute;
29}
30
31/// Puts the identifier attribute on a message class and gives the class the
32/// identifier as the constant `GUID`:
33///
34/// ```ignore
35/// ferro_remote_message_guid!(MeasureViewportMessage, "6E3C5310-E2B1-4C3D-8688-01183AA48C5B");
36/// ```
37///
38/// The class also has to be in the table of its assembly
39/// ([`Assembly`](crate::Assembly)) for a resolver to find it.
40#[macro_export]
41macro_rules! ferro_remote_message_guid {
42 ($class:ident, $guid:literal) => {
43 impl $crate::FerroRemoteMessage for $class {
44 const ATTRIBUTE: $crate::FerroRemoteMessageGuidAttribute =
45 $crate::FerroRemoteMessageGuidAttribute::new($guid);
46 }
47
48 impl $class {
49 /// The identifier of the message class on the wire.
50 pub const GUID: $crate::Guid = <$class as $crate::FerroRemoteMessage>::ATTRIBUTE.guid();
51 }
52 };
53}