Skip to content

Commit

Permalink
Merge pull request #49 from mchodzikiewicz/master
Browse files Browse the repository at this point in the history
Add defmt, bump heapless, add additional CI build variants, fix serde+no_std
  • Loading branch information
00imvj00 authored Dec 28, 2024
2 parents 5bf355b + 6e06377 commit 0f1ce9d
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 15 deletions.
23 changes: 22 additions & 1 deletion .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ on:

jobs:
build:

runs-on: ubuntu-latest

steps:
Expand All @@ -17,3 +16,25 @@ jobs:
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
- name: Build serde
run: cargo build --verbose --features=derive
- name: Run tests serde
run: cargo test --verbose --features=derive
- name: Build no_std
run: cargo build --verbose --no-default-features
- name: Run tests no_std
run: cargo test --verbose --no-default-features
- name: Build no_std
run: cargo build --verbose --no-default-features --features=derive
- name: Run tests no_std
run: cargo test --verbose --no-default-features --features=derive
- name: Build defmt
run: cargo build --verbose --no-default-features --features=defmt
- name: Run tests defmt
run: cargo test --verbose --no-default-features --features=defmt
- name: Build defmt derive
run: cargo build --verbose --no-default-features --features=defmt --features=derive
- name: Run tests defmt derive
run: cargo test --verbose --no-default-features --features=defmt --features=derive


10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ license = "Apache-2.0"
default = ["std"]

# Implements serde::{Serialize,Deserialize} on mqttrs::Pid.
derive = ["serde"]
std = ["bytes", "bytes/std", "serde/std"]
derive = ["serde", "heapless/serde"]
std = ["bytes/std", "serde/std"]
defmt = ["dep:defmt", "heapless/defmt-03"]

[dependencies]
bytes = { version = "1.0", default-features = false, optional = true }
bytes = { version = "1.0", default-features = false}
serde = { version = "1.0", features = ["derive"], optional = true }
heapless = "0.7"
heapless = { version = "0.8" }
defmt = { version = "0.3.10", optional = true }

[dev-dependencies]
proptest = "0.10.0"
18 changes: 16 additions & 2 deletions src/connect.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
#[cfg(feature = "defmt")]
use defmt::Format;
use crate::{decoder::*, encoder::*, *};
#[cfg(not(feature = "std"))]
use heapless::String;
#[cfg(feature = "std")]
use std::string::String;
use core::str::FromStr;


/// Protocol version.
///
/// Sent in [`Connect`] packet.
///
/// [`Connect`]: struct.Connect.html
///
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Protocol {
/// [MQTT 3.1.1] is the most commonly implemented version. [MQTT 5] isn't yet supported my by
Expand All @@ -23,8 +33,8 @@ impl Protocol {
match (name, level) {
("MQIsdp", 3) => Ok(Protocol::MQIsdp),
("MQTT", 4) => Ok(Protocol::MQTT311),
_ => Err(Error::InvalidProtocol(name.into(), level)),
}
_ => Err(Error::InvalidProtocol(String::from_str(name).unwrap(), 0)),
}
}
pub(crate) fn from_buffer<'a>(buf: &'a [u8], offset: &mut usize) -> Result<Self, Error> {
let protocol_name = read_str(buf, offset)?;
Expand Down Expand Up @@ -61,6 +71,7 @@ impl Protocol {
///
/// [Connect]: struct.Connect.html
/// [MQTT 3.1.3.3]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718031
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, PartialEq)]
pub struct LastWill<'a> {
pub topic: &'a str,
Expand All @@ -75,6 +86,7 @@ pub struct LastWill<'a> {
///
/// [Connack]: struct.Connack.html
/// [MQTT 3.2.2.3]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718035
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ConnectReturnCode {
Accepted,
Expand Down Expand Up @@ -111,6 +123,7 @@ impl ConnectReturnCode {
/// Connect packet ([MQTT 3.1]).
///
/// [MQTT 3.1]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718028
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, PartialEq)]
pub struct Connect<'a> {
pub protocol: Protocol,
Expand All @@ -125,6 +138,7 @@ pub struct Connect<'a> {
/// Connack packet ([MQTT 3.2]).
///
/// [MQTT 3.2]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718033
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Connack {
pub session_present: bool,
Expand Down
35 changes: 35 additions & 0 deletions src/decoder_test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::*;
use bytes::BytesMut;
use subscribe::LimitedString;
use core::str::FromStr;

macro_rules! header {
($t:ident, $d:expr, $q:ident, $r:expr) => {
Expand Down Expand Up @@ -421,6 +422,7 @@ fn test_pub_comp() {
};
}

#[cfg(feature = "std")]
#[test]
fn test_subscribe() {
let mut data: &[u8] = &[
Expand All @@ -439,6 +441,25 @@ fn test_subscribe() {
}
}

#[cfg(not(feature = "std"))]
#[test]
fn test_subscribe() {
let mut data: &[u8] = &[
0b10000010, 8, 0, 10, 0, 3, 'a' as u8, '/' as u8, 'b' as u8, 0,
];
match decode_slice(&mut data) {
Ok(Some(Packet::Subscribe(s))) => {
assert_eq!(s.pid.get(), 10);
let t = SubscribeTopic {
topic_path: LimitedString::from_str("a/b").unwrap(),
qos: QoS::AtMostOnce,
};
assert_eq!(s.topics.get(0), Some(&t));
}
other => panic!("Failed decode: {:?}", other),
}
}

#[test]
fn test_suback() {
let mut data: &[u8] = &[0b10010000, 3, 0, 10, 0b00000010];
Expand All @@ -454,6 +475,7 @@ fn test_suback() {
}
}

#[cfg(feature = "std")]
#[test]
fn test_unsubscribe() {
let mut data: &[u8] = &[0b10100010, 5, 0, 10, 0, 1, 'a' as u8];
Expand All @@ -466,6 +488,19 @@ fn test_unsubscribe() {
}
}

#[cfg(not(feature = "std"))]
#[test]
fn test_unsubscribe() {
let mut data: &[u8] = &[0b10100010, 5, 0, 10, 0, 1, 'a' as u8];
match decode_slice(&mut data) {
Ok(Some(Packet::Unsubscribe(a))) => {
assert_eq!(a.pid.get(), 10);
assert_eq!(a.topics.get(0), Some(&LimitedString::from_str("a").unwrap()));
}
other => panic!("Failed decode: {:?}", other),
}
}

#[test]
fn test_unsub_ack() {
let mut data: &[u8] = &[0b10110000, 2, 0, 10];
Expand Down
19 changes: 18 additions & 1 deletion src/encoder_test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::*;
use core::convert::TryFrom;
use subscribe::{LimitedString, LimitedVec};
use core::str::FromStr;

#[cfg(feature = "std")]
use bytes::BytesMut;
Expand Down Expand Up @@ -130,7 +131,7 @@ fn test_pubcomp() {
// assert_decode!(Packet::Pubcomp(_), &packet);
assert_decode_slice!(Packet::Pubcomp(_), &packet, 4);
}

#[cfg(feature = "std")]
#[test]
fn test_subscribe() {
let stopic = SubscribeTopic {
Expand All @@ -143,6 +144,19 @@ fn test_subscribe() {
assert_decode_slice!(Packet::Subscribe(_), &packet, 10);
}

#[cfg(not(feature = "std"))]
#[test]
fn test_subscribe() {
let stopic = SubscribeTopic {
topic_path: LimitedString::from_str("a/b").unwrap(),
qos: QoS::ExactlyOnce,
};
let topics: LimitedVec<SubscribeTopic> = [stopic].iter().cloned().collect();
let packet = Subscribe::new(Pid::try_from(345).unwrap(), topics).into();
// assert_decode!(Packet::Subscribe(_), &packet);
assert_decode_slice!(Packet::Subscribe(_), &packet, 10);
}

#[test]
fn test_suback() {
let return_codes = [SubscribeReturnCodes::Success(QoS::ExactlyOnce)]
Expand All @@ -156,7 +170,10 @@ fn test_suback() {

#[test]
fn test_unsubscribe() {
#[cfg(feature = "std")]
let topics: LimitedVec<LimitedString> = [LimitedString::from("a/b")].iter().cloned().collect();
#[cfg(not(feature = "std"))]
let topics: LimitedVec<LimitedString> = [LimitedString::from_str("a/b").unwrap()].iter().cloned().collect();

let packet = Unsubscribe::new(Pid::try_from(12321).unwrap(), topics).into();
// assert_decode!(Packet::Unsubscribe(_), &packet);
Expand Down
5 changes: 5 additions & 0 deletions src/packet.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#[cfg(feature = "defmt")]
use defmt::Format;

use crate::*;

/// Base enum for all MQTT packet types.
Expand All @@ -24,6 +27,7 @@ use crate::*;
///
/// [`encode()`]: fn.encode.html
/// [`decode_slice()`]: fn.decode_slice.html
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, PartialEq)]
pub enum Packet<'a> {
/// [MQTT 3.1](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718028)
Expand Down Expand Up @@ -107,6 +111,7 @@ packet_from_borrowed!(Connect, Publish);
packet_from!(Suback, Connack, Subscribe, Unsubscribe);

/// Packet type variant, without the associated data.
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum PacketType {
Connect,
Expand Down
3 changes: 3 additions & 0 deletions src/publish.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#[cfg(feature = "defmt")]
use defmt::Format;
use crate::{decoder::*, encoder::*, *};

/// Publish packet ([MQTT 3.3]).
///
/// [MQTT 3.3]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718037
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, PartialEq)]
pub struct Publish<'a> {
pub dup: bool,
Expand Down
21 changes: 15 additions & 6 deletions src/subscribe.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
#[cfg(feature = "defmt")]
use defmt::Format;
use crate::{decoder::*, encoder::*, *};
#[cfg(feature = "derive")]
use serde::{Deserialize, Serialize};

#[cfg(feature = "std")]
pub(crate) type LimitedVec<T> = std::vec::Vec<T>;
pub type LimitedVec<T> = std::vec::Vec<T>;
#[cfg(not(feature = "std"))]
pub(crate) type LimitedVec<T> = heapless::Vec<T, 5>;
pub type LimitedVec<T> = heapless::Vec<T, 5>;

#[cfg(feature = "std")]
pub(crate) type LimitedString = std::string::String;
pub type LimitedString = std::string::String;
#[cfg(not(feature = "std"))]
pub(crate) type LimitedString = heapless::String<256>;
pub type LimitedString = heapless::String<256>;

use core::str::FromStr;

/// Subscribe topic.
///
/// [Subscribe] packets contain a `Vec` of those.
///
/// [Subscribe]: struct.Subscribe.html
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
pub struct SubscribeTopic {
Expand All @@ -26,7 +31,7 @@ pub struct SubscribeTopic {

impl SubscribeTopic {
pub(crate) fn from_buffer(buf: &[u8], offset: &mut usize) -> Result<Self, Error> {
let topic_path = LimitedString::from(read_str(buf, offset)?);
let topic_path = LimitedString::from_str(read_str(buf, offset)?).unwrap();
let qos = QoS::from_u8(buf[*offset])?;
*offset += 1;
Ok(SubscribeTopic { topic_path, qos })
Expand All @@ -38,6 +43,7 @@ impl SubscribeTopic {
/// [Suback] packets contain a `Vec` of those.
///
/// [Suback]: struct.Subscribe.html
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SubscribeReturnCodes {
Success(QoS),
Expand Down Expand Up @@ -67,6 +73,7 @@ impl SubscribeReturnCodes {
/// Subscribe packet ([MQTT 3.8]).
///
/// [MQTT 3.8]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718063
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, PartialEq)]
pub struct Subscribe {
pub pid: Pid,
Expand All @@ -76,6 +83,7 @@ pub struct Subscribe {
/// Subsack packet ([MQTT 3.9]).
///
/// [MQTT 3.9]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718068
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, PartialEq)]
pub struct Suback {
pub pid: Pid,
Expand All @@ -85,6 +93,7 @@ pub struct Suback {
/// Unsubscribe packet ([MQTT 3.10]).
///
/// [MQTT 3.10]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718072
#[cfg_attr(feature = "defmt",derive(Format))]
#[derive(Debug, Clone, PartialEq)]
pub struct Unsubscribe {
pub pid: Pid,
Expand Down Expand Up @@ -155,7 +164,7 @@ impl Unsubscribe {

let mut topics = LimitedVec::new();
while *offset < payload_end {
let _res = topics.push(LimitedString::from(read_str(buf, offset)?));
let _res = topics.push(LimitedString::from_str(read_str(buf, offset)?).unwrap());

#[cfg(not(feature = "std"))]
_res.map_err(|_| Error::InvalidLength)?;
Expand Down
Loading

0 comments on commit 0f1ce9d

Please sign in to comment.