grapple_frc_msgs/
lib.rs

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}