1#![cfg_attr(all(not(feature="std"), not(test)), no_std)]
2
3extern crate alloc;
4
5pub mod grapple;
6#[cfg(feature = "ni")]
7pub mod ni;
8pub mod macros;
9pub mod bridge;
10
11pub use binmarshal;
12
13use binmarshal::BitWriter;
14use binmarshal::Demarshal;
15use binmarshal::Marshal;
16use binmarshal::MarshalUpdate;
17use bounded_static::ToStatic;
18use grapple::MANUFACTURER_GRAPPLE;
19use grapple::MaybeFragment;
20use grapple::errors::GrappleResult;
21
22pub const DEVICE_TYPE_BROADCAST: u8 = 0x00;
23pub const DEVICE_TYPE_FIRMWARE_UPGRADE: u8 = 31;
24pub const DEVICE_ID_BROADCAST: u8 = 0x3F;
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, ToStatic)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
29pub struct MessageId {
30 pub device_type: u8,
31 pub manufacturer: u8,
32 pub api_class: u8,
33 pub api_index: u8,
34 pub device_id: u8,
35}
36
37impl From<u32> for MessageId {
38 fn from(value: u32) -> Self {
39 Self {
40 device_type: ((value >> 6+4+6+8) & 0b11111) as u8,
41 manufacturer: ((value >> 6+4+6) & 0b11111111) as u8,
42 api_class: ((value >> 6+4) & 0b111111) as u8,
43 api_index: ((value >> 6) & 0b1111) as u8,
44 device_id: (value & 0b111111) as u8
45 }
46 }
47}
48
49impl From<MessageId> for u32 {
50 fn from(v: MessageId) -> Self {
51 (v.device_id as u32 & 0b111111)
52 | ((v.api_index as u32 & 0b1111) << 6)
53 | ((v.api_class as u32 & 0b111111) << (6+4))
54 | ((v.manufacturer as u32 & 0b11111111) << (6+4+6))
55 | ((v.device_type as u32 & 0b11111) << (6+4+6+8))
56 }
57}
58
59impl Marshal for MessageId {
60 fn write<W: binmarshal::BitWriter>(&self, writer: &mut W, ctx: ()) -> Result<(), binmarshal::MarshalError> {
61 Into::<u32>::into(*self).write(writer, ctx)
62 }
63}
64
65impl<'dm> Demarshal<'dm, ()> for MessageId {
66 fn read(view: &mut binmarshal::BitView<'dm>, ctx: ()) -> Result<Self, binmarshal::MarshalError> {
67 Ok(Into::<Self>::into(u32::read(view, ctx)?))
68 }
69}
70
71#[derive(Debug, Clone, PartialEq, Marshal, Demarshal, MarshalUpdate, ToStatic)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
74pub struct Message<'a> {
75 pub id: MessageId,
76
77 #[marshal(
78 ctx = "construct",
79 ctx_type = MessageId,
80 ctx_member(field = "device_type", member = "id.device_type"),
81 ctx_member(field = "manufacturer", member = "id.manufacturer"),
82 ctx_member(field = "api_class", member = "id.api_class"),
83 ctx_member(field = "api_index", member = "id.api_index"),
84 ctx_member(field = "device_id", member = "id.device_id"),
85 )]
86 #[cfg_attr(feature = "serde", serde(borrow))]
87 pub msg: ManufacturerMessage<'a>
88}
89
90impl<'a> Message<'a> {
91 pub fn new(device_id: u8, msg: ManufacturerMessage<'a>) -> Self {
92 let mut newmsg = Self {
93 id: MessageId {
94 device_type: 0,
95 manufacturer: 0,
96 api_class: 0,
97 api_index: 0,
98 device_id,
99 },
100 msg,
101 };
102
103 newmsg.update(&mut ());
104
105 newmsg
106 }
107}
108
109impl<'a> Validate for Message<'a> {
110 fn validate(&self) -> GrappleResult<()> {
111 self.msg.validate()
112 }
113}
114
115#[derive(Debug, Clone, PartialEq, Marshal, Demarshal, MarshalUpdate, ToStatic)]
116#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
117#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
118#[marshal(ctx = MessageId, tag = "ctx.manufacturer")]
119pub enum ManufacturerMessage<'a> {
120 #[cfg(feature = "ni")]
121 #[marshal(tag = "ni::MANUFACTURER_NI")]
122 Ni(
123 #[marshal(ctx = "forward")]
124 ni::NiDeviceMessage
125 ),
126 #[marshal(tag = "MANUFACTURER_GRAPPLE")]
127 Grapple(
128 #[marshal(ctx = "coerce", ctx_type = crate::grapple::GrappleMessageId)]
129 #[cfg_attr(feature = "serde", serde(borrow))]
130 MaybeFragment<'a>
131 )
132}
133
134impl<'a> Validate for ManufacturerMessage<'a> {
135 fn validate(&self) -> GrappleResult<()> {
136 match self {
137 #[cfg(feature = "ni")]
138 ManufacturerMessage::Ni(_) => Ok(()),
139 ManufacturerMessage::Grapple(grpl) => grpl.validate(),
140 }
141 }
142}
143
144pub trait Validate {
145 fn validate(&self) -> GrappleResult<()>;
146}