Skip to content

Commit 8d18fe9

Browse files
committed
Remove bincode-core and serde dependencies
- Manual serialization * Faster * Very simple in this case as all of the hard work splitting fields into bytes was already done * Serdes and bincode can be annoying to integrate with no_std - Ended up being far easier than porting to bincode2 - No need to pad the serialization_len by 1 byte anymore (for the serialization length)
1 parent d34ef8c commit 8d18fe9

File tree

4 files changed

+64
-103
lines changed

4 files changed

+64
-103
lines changed

hid-io-protocol/Cargo.toml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,18 @@ device = []
2727
# server feature is intended for use with full user-space applications
2828
# with access to std for loggging messages
2929
# Mostly no_std with some minor exceptions
30-
server = ["log", "bincode_core/std"]
30+
server = ["log"]
3131

3232
# Adds defmt support to useful enums and structs
3333
defmt-impl = ["defmt", "heapless/defmt-impl"]
3434

3535

3636
[dependencies]
37-
arraydeque = { version = "^0.4", default-features = false }
38-
bincode_core = { git = "https://github.com/bincode-org/bincode-core.git", version = "0.1.0" }
39-
defmt = { version = "0.2", optional = true }
37+
arraydeque = { version = "0.4", default-features = false }
38+
defmt = { version = "0.3", optional = true }
4039
heapless = { version = "0.7" }
41-
log = { version = "^0.4", default-features = false, optional = true }
42-
num_enum = { version = "^0.5", default-features = false }
43-
serde = { version = "^1.0", default-features = false }
40+
log = { version = "0.4", default-features = false, optional = true }
41+
num_enum = { version = "0.5", default-features = false }
4442

4543

4644
[dev-dependencies]

hid-io-protocol/src/lib.rs

Lines changed: 50 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,10 @@ pub mod test;
3131

3232
// ----- Crates -----
3333

34-
use bincode_core::{serialize, BufferWriter};
3534
use core::convert::TryFrom;
3635
use core::fmt;
3736
use heapless::Vec;
3837
use num_enum::{IntoPrimitive, TryFromPrimitive};
39-
use serde::ser::{self, Serialize, SerializeSeq, Serializer};
4038

4139
#[cfg(feature = "server")]
4240
use log::{error, warn};
@@ -136,6 +134,8 @@ pub enum HidIoCommandId {
136134
#[derive(Debug)]
137135
#[cfg_attr(feature = "defmt-impl", derive(defmt::Format))]
138136
pub enum HidIoParseError {
137+
BufferNotReady,
138+
BufferDataTooSmall(usize),
139139
InvalidContinuedIdByte(u8),
140140
InvalidHidIoCommandId(u32),
141141
InvalidPacketIdWidth(u8),
@@ -515,9 +515,9 @@ impl<const H: usize> HidIoPacketBuffer<H> {
515515
/// Returns the currently computed serialized length of the
516516
/// buffer. Can change based on the struct fields.
517517
pub fn serialized_len(&self) -> u32 {
518-
// Sync packets have a serialized length of 1 (+1 for length)
518+
// Sync packets have a serialized length of 1
519519
if self.ptype == HidIoPacketType::Sync {
520-
return 1 + 1;
520+
return 1;
521521
}
522522

523523
let hdr_len = self.hdr_len();
@@ -531,8 +531,7 @@ impl<const H: usize> HidIoPacketBuffer<H> {
531531
0
532532
};
533533

534-
// Extra byte is a type field from the serializer
535-
fullpackets + partialpacket + 1
534+
fullpackets + partialpacket
536535
}
537536

538537
/// Append payload data
@@ -674,48 +673,6 @@ impl<const H: usize> HidIoPacketBuffer<H> {
674673
/// Serialize HidIoPacketBuffer
675674
///
676675
/// # Remarks
677-
/// Provides a raw data vector to the serialized data.
678-
/// Removes some of the header that Serialize from serde prepends.
679-
pub fn serialize_buffer<'a>(
680-
&mut self,
681-
data: &'a mut [u8],
682-
) -> Result<&'a [u8], HidIoParseError> {
683-
let options = bincode_core::config::DefaultOptions::new();
684-
let mut writer = BufferWriter::new(data);
685-
let len;
686-
687-
// Serialize
688-
match serialize(&self, &mut writer, options) {
689-
Ok(_) => {}
690-
Err(_e) => {
691-
error!("Parse error: {:?}", _e);
692-
return Err(HidIoParseError::SerializationError);
693-
}
694-
};
695-
696-
// Make sure serialization worked
697-
len = writer.written_len();
698-
if self.ptype == HidIoPacketType::Sync && len < 2
699-
|| self.ptype != HidIoPacketType::Sync && len < 5
700-
{
701-
error!(
702-
"Serialization too small: {} -> {:02X?}",
703-
len,
704-
writer.written_buffer()
705-
);
706-
return Err(HidIoParseError::SerializationFailedResultTooSmall(len));
707-
}
708-
709-
// Slice off the first byte (type) header bytes from serde
710-
let slice = &data[1..len as usize];
711-
Ok(slice)
712-
}
713-
}
714-
715-
impl<const H: usize> Serialize for HidIoPacketBuffer<H> {
716-
/// Serializer for HidIoPacketBuffer
717-
///
718-
/// # Remarks
719676
/// Determine cont, width, upper_len and len fields
720677
/// According to this C-Struct:
721678
///
@@ -730,17 +687,17 @@ impl<const H: usize> Serialize for HidIoPacketBuffer<H> {
730687
/// uint8_t data[0]; // Start of data payload (may start with Id)
731688
/// };
732689
/// ```
733-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
734-
where
735-
S: Serializer,
736-
{
690+
pub fn serialize_buffer<'a>(&self, data: &'a mut [u8]) -> Result<&'a [u8], HidIoParseError> {
737691
// Check if buffer is ready to serialize
738692
if !self.done {
739-
return Err(ser::Error::custom("HidIoPacketBuffer is not 'done'"));
693+
return Err(HidIoParseError::BufferNotReady);
740694
}
741695

742696
// --- First Packet ---
743697

698+
// Keep track of the serialization buffer position
699+
let mut pos = 0;
700+
744701
// Determine id_width
745702
let id_width = self.id_width();
746703

@@ -785,9 +742,7 @@ impl<const H: usize> Serialize for HidIoPacketBuffer<H> {
785742
for idx in 0..id_width_len {
786743
let id = (self.id as u32 >> (idx * 8)) as u8;
787744
if id_vec.push(id).is_err() {
788-
return Err(ser::Error::custom(
789-
"HidIoPacketBuffer failed to convert Id into bytes, vec add failed.",
790-
));
745+
return Err(HidIoParseError::VecAddFailed);
791746
}
792747
}
793748

@@ -804,31 +759,19 @@ impl<const H: usize> Serialize for HidIoPacketBuffer<H> {
804759
// upper_len - 2 bits
805760
(upper_len & 0x3);
806761

762+
// Header byte is always serialized
763+
pos = serialize_byte(data, hdr_byte, pos)?;
764+
807765
// Determine if this is a sync packet (much simpler serialization)
808766
if self.ptype == HidIoPacketType::Sync {
809-
let mut state = serializer.serialize_seq(Some(0))?;
810-
state.serialize_element(&hdr_byte)?;
811-
return state.end();
767+
return Ok(data);
812768
}
813769

814-
// Serialize as a sequence
815-
let mut state = serializer.serialize_seq(Some(0))?;
816-
817-
// Serialize header
818-
state.serialize_element(&hdr_byte)?;
819-
820770
// Serialize length
821-
state.serialize_element(&len)?;
822-
823-
// If SYNC packet
824-
if self.ptype == HidIoPacketType::Sync {
825-
return state.end();
826-
}
771+
pos = serialize_byte(data, len, pos)?;
827772

828773
// Serialize id
829-
for id_byte in &id_vec {
830-
state.serialize_element(id_byte)?;
831-
}
774+
pos = serialize_bytes(data, &id_vec[..id_width_len as usize], pos)?;
832775

833776
// Serialize payload data
834777
// We can't just serialize directly (extra info is included), serialize each element of vector separately
@@ -839,13 +782,11 @@ impl<const H: usize> Serialize for HidIoPacketBuffer<H> {
839782
// Payload that's available
840783
&self.data[0..data_len as usize]
841784
};
842-
for elem in slice {
843-
state.serialize_element(elem)?;
844-
}
785+
pos = serialize_bytes(data, slice, pos)?;
845786

846787
// Finish serialization if no more payload left
847788
if !cont {
848-
return state.end();
789+
return Ok(data);
849790
}
850791

851792
// Determine how much payload is left
@@ -897,15 +838,13 @@ impl<const H: usize> Serialize for HidIoPacketBuffer<H> {
897838
(upper_len & 0x3);
898839

899840
// Serialize header
900-
state.serialize_element(&hdr_byte)?;
841+
pos = serialize_byte(data, hdr_byte, pos)?;
901842

902843
// Serialize length
903-
state.serialize_element(&len)?;
844+
pos = serialize_byte(data, len, pos)?;
904845

905846
// Serialize id
906-
for id_byte in &id_vec {
907-
state.serialize_element(id_byte)?;
908-
}
847+
pos = serialize_bytes(data, &id_vec[..id_width_len as usize], pos)?;
909848

910849
// Serialize payload data
911850
// We can't just serialize directly (extra info is included), serialize each element of vector separately
@@ -917,18 +856,42 @@ impl<const H: usize> Serialize for HidIoPacketBuffer<H> {
917856
data_len as usize
918857
};
919858
let slice = &self.data[last_slice_index..slice_end];
920-
for elem in slice {
921-
state.serialize_element(elem)?;
922-
}
859+
pos = serialize_bytes(data, slice, pos)?;
923860

924861
// Recalculate how much payload is left
925862
payload_left -= (slice_end - last_slice_index) as u32;
926863
last_slice_index += payload_len as usize;
927864
}
928865

929866
// --- Finish serialization ---
930-
state.end()
867+
Ok(data)
868+
}
869+
}
870+
871+
/// Very simple error checking function for byte serialization
872+
/// Returns the new serialization index pointer
873+
fn serialize_byte(data: &mut [u8], byte: u8, pos: usize) -> Result<usize, HidIoParseError> {
874+
// Make sure buffer is large enough
875+
if pos >= data.len() {
876+
return Err(HidIoParseError::BufferDataTooSmall(pos - 1));
877+
}
878+
879+
data[pos] = byte;
880+
Ok(pos + 1)
881+
}
882+
883+
/// Very simple error checking function for byte array serialization
884+
/// Returns the new serialization index pointer
885+
fn serialize_bytes(data: &mut [u8], bytes: &[u8], pos: usize) -> Result<usize, HidIoParseError> {
886+
// Make sure buffer is large enough
887+
if pos + bytes.len() > data.len() && !bytes.is_empty() {
888+
return Err(HidIoParseError::BufferDataTooSmall(pos - 1));
889+
}
890+
891+
for (i, byte) in bytes.iter().enumerate() {
892+
data[pos + i] = *byte;
931893
}
894+
Ok(pos + bytes.len())
932895
}
933896

934897
impl fmt::Display for HidIoPacketType {

hid-io-protocol/src/test.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fn setup_logging_lite() -> Result<(), LogError> {
4949

5050
/// Loopback helper
5151
/// Serializes, deserializes, then checks if same as original
52-
fn loopback_serializer<const H: usize>(mut buffer: HidIoPacketBuffer<H>, data: &mut [u8]) {
52+
fn loopback_serializer<const H: usize>(buffer: HidIoPacketBuffer<H>, data: &mut [u8]) {
5353
// Serialize
5454
let data = match buffer.serialize_buffer(data) {
5555
Ok(data) => data,
@@ -119,7 +119,7 @@ fn sync_payload_test() {
119119
};
120120

121121
// Run loopback serializer, handles all test validation
122-
let mut data = [0u8; 2];
122+
let mut data = [0u8; 1];
123123
loopback_serializer(buffer, &mut data);
124124
}
125125

@@ -146,7 +146,7 @@ fn no_payload_test() {
146146
};
147147

148148
// Run loopback serializer, handles all test validation
149-
let mut data = [0u8; 5];
149+
let mut data = [0u8; 4];
150150
loopback_serializer(buffer, &mut data);
151151
}
152152

@@ -171,7 +171,7 @@ fn single_byte_payload_test() {
171171
};
172172

173173
// Run loopback serializer, handles all test validation
174-
let mut data = [0u8; 6];
174+
let mut data = [0u8; 5];
175175
loopback_serializer(buffer, &mut data);
176176
}
177177

@@ -196,7 +196,7 @@ fn full_packet_payload_test() {
196196
};
197197

198198
// Run loopback serializer, handles all test validation
199-
let mut data = [0u8; 65];
199+
let mut data = [0u8; 64];
200200
loopback_serializer(buffer, &mut data);
201201
}
202202

@@ -221,7 +221,7 @@ fn two_packet_continued_payload_test() {
221221
};
222222

223223
// Run loopback serializer, handles all test validation
224-
let mut data = [0u8; 128];
224+
let mut data = [0u8; 118];
225225
loopback_serializer(buffer, &mut data);
226226
}
227227

@@ -246,7 +246,7 @@ fn three_packet_continued_payload_test() {
246246
};
247247

248248
// Run loopback serializer, handles all test validation
249-
let mut data = [0u8; 200];
249+
let mut data = [0u8; 182];
250250
loopback_serializer(buffer, &mut data);
251251
}
252252

@@ -270,7 +270,7 @@ fn four_packet_continued_payload_test() {
270270
};
271271

272272
// Run loopback serializer, handles all test validation
273-
let mut data = [0u8; 257];
273+
let mut data = [0u8; 256];
274274
loopback_serializer(buffer, &mut data);
275275
}
276276

src/device/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl HidIoEndpoint {
8181

8282
pub fn send_packet(
8383
&mut self,
84-
mut packet: mailbox::HidIoPacketBuffer,
84+
packet: mailbox::HidIoPacketBuffer,
8585
) -> Result<(), std::io::Error> {
8686
debug!(
8787
"Sending {:x?} len:{} chunk:{}",

0 commit comments

Comments
 (0)