From 0679f10faddf18df163a6591b9224fb9dbee70d5 Mon Sep 17 00:00:00 2001 From: Orne Brocaar Date: Thu, 27 Apr 2023 10:37:34 +0100 Subject: [PATCH] Add feature flags to lrwn crate. This avoids pulling and building unnecessary dependencies for simple use-cases. --- chirpstack/Cargo.toml | 2 +- lrwn/Cargo.toml | 18 +++++-- lrwn/Makefile | 2 +- lrwn/src/aes128.rs | 27 +++++++--- lrwn/src/cflist.rs | 13 +++-- lrwn/src/devaddr.rs | 29 ++++++++--- lrwn/src/dl_settings.rs | 4 +- lrwn/src/eui64.rs | 29 ++++++++--- lrwn/src/fhdr.rs | 7 ++- lrwn/src/lib.rs | 3 ++ lrwn/src/maccommand.rs | 112 +++++++++++++++++++++++++++------------- lrwn/src/mhdr.rs | 10 ++-- lrwn/src/netid.rs | 11 +++- lrwn/src/payload.rs | 21 +++++--- lrwn/src/phy_payload.rs | 48 ++++++++++++++--- lrwn/src/region/mod.rs | 32 ++++++++---- 16 files changed, 267 insertions(+), 101 deletions(-) diff --git a/chirpstack/Cargo.toml b/chirpstack/Cargo.toml index a7f59283..1bf0dd8e 100644 --- a/chirpstack/Cargo.toml +++ b/chirpstack/Cargo.toml @@ -46,7 +46,7 @@ tracing-subscriber = { version = "0.3", features = [ # ChirpStack API definitions chirpstack_api = { path = "../api/rust", features = ["default", "internal"] } -lrwn = { path = "../lrwn" } +lrwn = { path = "../lrwn", features = ["serde", "diesel", "regions", "crypto"] } backend = { path = "../backend" } # HTTP diff --git a/lrwn/Cargo.toml b/lrwn/Cargo.toml index 746d9929..a604e29a 100644 --- a/lrwn/Cargo.toml +++ b/lrwn/Cargo.toml @@ -8,12 +8,15 @@ authors = ["Orne Brocaar "] edition = "2018" repository = "https://github.com/chirpstack/chirpstack" +[package.metadata.docs.rs] +all-features = true + [dependencies] hex = "0.4" -cmac = "0.7" -aes = "0.8" -serde = { version = "1.0", features = ["derive"] } -diesel = { version = "2.0", features = [ "postgres" ] } +cmac = { version = "0.7", optional = true } +aes = { version = "0.8", optional = true } +serde = { version = "1.0", features = ["derive"], optional = true } +diesel = { version = "2.0", features = ["postgres"], optional = true } # Error handling thiserror = "1.0" @@ -21,3 +24,10 @@ anyhow = "1.0" # Misc lazy_static = "1.4" + +[features] +default = [] +diesel = ["dep:diesel", "serde"] +serde = ["dep:serde"] +crypto = ["dep:cmac", "dep:aes"] +regions = [] diff --git a/lrwn/Makefile b/lrwn/Makefile index 199fc044..6fb8af6c 100644 --- a/lrwn/Makefile +++ b/lrwn/Makefile @@ -4,4 +4,4 @@ test: cargo fmt --check cargo clippy - cargo test + cargo test --all-features diff --git a/lrwn/src/aes128.rs b/lrwn/src/aes128.rs index 393bbc40..55975d31 100644 --- a/lrwn/src/aes128.rs +++ b/lrwn/src/aes128.rs @@ -2,16 +2,23 @@ use std::fmt; use std::str::FromStr; use anyhow::Result; -use diesel::backend::{self, Backend}; -use diesel::sql_types::Binary; -use diesel::{deserialize, serialize}; -use serde::de::{self, Visitor}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "diesel")] +use diesel::{ + backend::{self, Backend}, + deserialize, serialize, + sql_types::Binary, +}; +#[cfg(feature = "serde")] +use serde::{ + de::{self, Visitor}, + Deserialize, Deserializer, Serialize, Serializer, +}; use crate::Error; -#[derive(Copy, Clone, PartialEq, Eq, AsExpression, FromSqlRow, Default)] -#[diesel(sql_type = diesel::sql_types::Binary)] +#[derive(Copy, Clone, PartialEq, Eq, Default)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Binary))] pub struct AES128Key([u8; 16]); impl AES128Key { @@ -64,6 +71,7 @@ impl FromStr for AES128Key { } } +#[cfg(feature = "serde")] impl Serialize for AES128Key { fn serialize(&self, serializer: S) -> Result where @@ -73,6 +81,7 @@ impl Serialize for AES128Key { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for AES128Key { fn deserialize(deserialize: D) -> Result where @@ -82,8 +91,10 @@ impl<'de> Deserialize<'de> for AES128Key { } } +#[cfg(feature = "serde")] struct Aes128KeyVisitor; +#[cfg(feature = "serde")] impl<'de> Visitor<'de> for Aes128KeyVisitor { type Value = AES128Key; @@ -99,6 +110,7 @@ impl<'de> Visitor<'de> for Aes128KeyVisitor { } } +#[cfg(feature = "diesel")] impl deserialize::FromSql for AES128Key where DB: Backend, @@ -117,6 +129,7 @@ where } } +#[cfg(feature = "diesel")] impl serialize::ToSql for AES128Key where [u8]: serialize::ToSql, diff --git a/lrwn/src/cflist.rs b/lrwn/src/cflist.rs index b9b1dc2f..fe4f6da9 100644 --- a/lrwn/src/cflist.rs +++ b/lrwn/src/cflist.rs @@ -1,7 +1,9 @@ use anyhow::Result; +#[cfg(feature = "serde")] use serde::Serialize; -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum CFList { Channels(CFListChannels), ChannelMask(CFListChannelMasks), @@ -38,7 +40,8 @@ impl CFList { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct CFListChannels([u32; 5]); impl CFListChannels { @@ -98,7 +101,8 @@ impl CFListChannels { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct CFListChannelMasks(Vec); impl CFListChannelMasks { @@ -141,7 +145,8 @@ impl CFListChannelMasks { /// ChMask encodes the channels usable for uplink access. 0 = channel 1, /// 15 = channel 16. -#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct ChMask([bool; 16]); impl ChMask { diff --git a/lrwn/src/devaddr.rs b/lrwn/src/devaddr.rs index 357498f0..2ea50eca 100644 --- a/lrwn/src/devaddr.rs +++ b/lrwn/src/devaddr.rs @@ -2,8 +2,17 @@ use std::fmt; use std::str::FromStr; use anyhow::Result; -use serde::de::{self, Visitor}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "diesel")] +use diesel::{ + backend::{self, Backend}, + deserialize, serialize, + sql_types::Binary, +}; +#[cfg(feature = "serde")] +use serde::{ + de::{self, Visitor}, + Deserialize, Deserializer, Serialize, Serializer, +}; use super::netid::NetID; use crate::Error; @@ -58,6 +67,7 @@ impl FromStr for DevAddrPrefix { } } +#[cfg(feature = "serde")] impl Serialize for DevAddrPrefix { fn serialize(&self, serializer: S) -> Result where @@ -67,6 +77,7 @@ impl Serialize for DevAddrPrefix { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for DevAddrPrefix { fn deserialize(deserialize: D) -> Result where @@ -76,8 +87,10 @@ impl<'de> Deserialize<'de> for DevAddrPrefix { } } +#[cfg(feature = "serde")] struct DevAddrPrefixVisitor; +#[cfg(feature = "serde")] impl<'de> Visitor<'de> for DevAddrPrefixVisitor { type Value = DevAddrPrefix; @@ -93,8 +106,9 @@ impl<'de> Visitor<'de> for DevAddrPrefixVisitor { } } -#[derive(PartialEq, Eq, Copy, Clone, AsExpression, FromSqlRow, Default)] -#[diesel(sql_type = diesel::sql_types::Binary)] +#[derive(PartialEq, Eq, Copy, Clone, Default)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Binary))] pub struct DevAddr([u8; 4]); impl DevAddr { @@ -226,6 +240,7 @@ impl FromStr for DevAddr { } } +#[cfg(feature = "serde")] impl Serialize for DevAddr { fn serialize(&self, serializer: S) -> Result where @@ -235,10 +250,7 @@ impl Serialize for DevAddr { } } -use diesel::backend::{self, Backend}; -use diesel::sql_types::Binary; -use diesel::{deserialize, serialize}; - +#[cfg(feature = "diesel")] impl deserialize::FromSql for DevAddr where DB: Backend, @@ -257,6 +269,7 @@ where } } +#[cfg(feature = "diesel")] impl serialize::ToSql for DevAddr where [u8]: serialize::ToSql, diff --git a/lrwn/src/dl_settings.rs b/lrwn/src/dl_settings.rs index d0cc9ba4..a4073452 100644 --- a/lrwn/src/dl_settings.rs +++ b/lrwn/src/dl_settings.rs @@ -1,7 +1,9 @@ use anyhow::Result; +#[cfg(feature = "serde")] use serde::Serialize; -#[derive(Serialize, PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct DLSettings { pub opt_neg: bool, pub rx2_dr: u8, diff --git a/lrwn/src/eui64.rs b/lrwn/src/eui64.rs index aab7743b..53420f36 100644 --- a/lrwn/src/eui64.rs +++ b/lrwn/src/eui64.rs @@ -2,13 +2,23 @@ use std::fmt; use std::str::FromStr; use anyhow::Result; -use serde::de::{self, Visitor}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "diesel")] +use diesel::{ + backend::{self, Backend}, + deserialize, serialize, + sql_types::Binary, +}; +#[cfg(feature = "serde")] +use serde::{ + de::{self, Visitor}, + Deserialize, Deserializer, Serialize, Serializer, +}; use crate::Error; -#[derive(Copy, Clone, PartialEq, Eq, Hash, AsExpression, FromSqlRow, Default)] -#[diesel(sql_type = diesel::sql_types::Binary)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Binary))] pub struct EUI64([u8; 8]); impl EUI64 { @@ -69,6 +79,7 @@ impl FromStr for EUI64 { } } +#[cfg(feature = "serde")] impl Serialize for EUI64 { fn serialize(&self, serializer: S) -> Result where @@ -78,6 +89,7 @@ impl Serialize for EUI64 { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for EUI64 { fn deserialize(deserialize: D) -> Result where @@ -87,8 +99,10 @@ impl<'de> Deserialize<'de> for EUI64 { } } +#[cfg(feature = "serde")] struct Eui64Visitor; +#[cfg(feature = "serde")] impl<'de> Visitor<'de> for Eui64Visitor { type Value = EUI64; @@ -104,10 +118,7 @@ impl<'de> Visitor<'de> for Eui64Visitor { } } -use diesel::backend::{self, Backend}; -use diesel::sql_types::Binary; -use diesel::{deserialize, serialize}; - +#[cfg(feature = "diesel")] impl deserialize::FromSql for EUI64 where DB: Backend, @@ -126,6 +137,7 @@ where } } +#[cfg(feature = "diesel")] impl serialize::ToSql for EUI64 where [u8]: serialize::ToSql, @@ -138,6 +150,7 @@ where } } +#[cfg(feature = "diesel")] impl diesel::sql_types::SqlType for EUI64 { type IsNull = diesel::sql_types::is_nullable::NotNull; } diff --git a/lrwn/src/fhdr.rs b/lrwn/src/fhdr.rs index d1e63e89..8f9b5e9f 100644 --- a/lrwn/src/fhdr.rs +++ b/lrwn/src/fhdr.rs @@ -1,10 +1,12 @@ use anyhow::Result; +#[cfg(feature = "serde")] use serde::Serialize; use super::devaddr::DevAddr; use super::maccommand::MACCommandSet; -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct FHDR { pub devaddr: DevAddr, pub f_ctrl: FCtrl, @@ -82,7 +84,8 @@ impl FHDR { } } -#[derive(Serialize, Default, Debug, PartialEq, Eq, Clone)] +#[derive(Default, Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct FCtrl { pub adr: bool, pub adr_ack_req: bool, diff --git a/lrwn/src/lib.rs b/lrwn/src/lib.rs index cd330a54..3d6d6518 100644 --- a/lrwn/src/lib.rs +++ b/lrwn/src/lib.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "diesel")] #[macro_use] extern crate diesel; #[macro_use] @@ -25,12 +26,14 @@ mod dl_settings; mod error; mod eui64; mod fhdr; +#[cfg(feature = "crypto")] pub mod keys; mod maccommand; mod mhdr; mod netid; mod payload; mod phy_payload; +#[cfg(feature = "regions")] pub mod region; lazy_static! { diff --git a/lrwn/src/maccommand.rs b/lrwn/src/maccommand.rs index dfb6aac1..139aa611 100644 --- a/lrwn/src/maccommand.rs +++ b/lrwn/src/maccommand.rs @@ -3,12 +3,14 @@ use std::ops::{Deref, DerefMut}; use std::time::Duration; use anyhow::Result; +#[cfg(feature = "serde")] use serde::Serialize; use super::cflist::ChMask; use super::dl_settings::DLSettings; -#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy, Hash)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum CID { ResetInd, ResetConf, @@ -83,7 +85,8 @@ impl CID { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum MACCommand { ResetInd(ResetIndPayload), ResetConf(ResetConfPayload), @@ -170,7 +173,8 @@ impl MACCommand { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum Version { LoRaWAN1_1, } @@ -198,13 +202,15 @@ impl fmt::Display for Version { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum DwellTime { NoLimit, Limit400ms, } -#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum DeviceModeClass { ClassA, ClassC, @@ -242,7 +248,8 @@ impl fmt::Display for DeviceModeClass { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct MACCommandSet(Vec); impl Deref for MACCommandSet { @@ -780,7 +787,8 @@ impl MACCommandSet { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct ResetIndPayload { pub dev_lorawan_version: Version, } @@ -803,7 +811,8 @@ impl ResetIndPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct ResetConfPayload { pub serv_lorawan_version: Version, } @@ -826,7 +835,8 @@ impl ResetConfPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct LinkCheckAnsPayload { pub margin: u8, pub gw_cnt: u8, @@ -851,7 +861,8 @@ impl LinkCheckAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct LinkADRReqPayload { pub dr: u8, pub tx_power: u8, @@ -894,7 +905,8 @@ impl LinkADRReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct Redundancy { pub ch_mask_cntl: u8, pub nb_rep: u8, @@ -922,7 +934,8 @@ impl Redundancy { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct LinkADRAnsPayload { pub ch_mask_ack: bool, pub dr_ack: bool, @@ -961,7 +974,8 @@ impl LinkADRAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct DutyCycleReqPayload { pub max_duty_cycle: u8, } @@ -988,7 +1002,8 @@ impl DutyCycleReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RxParamSetupReqPayload { pub frequency: u32, pub dl_settings: DLSettings, @@ -1029,7 +1044,8 @@ impl RxParamSetupReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RxParamSetupAnsPayload { pub channel_ack: bool, pub rx2_dr_ack: bool, @@ -1066,7 +1082,8 @@ impl RxParamSetupAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct DevStatusAnsPayload { pub battery: u8, pub margin: i8, @@ -1110,7 +1127,8 @@ impl DevStatusAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct NewChannelReqPayload { pub ch_index: u8, pub freq: u32, @@ -1177,7 +1195,8 @@ impl NewChannelReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct NewChannelAnsPayload { pub channel_freq_ok: bool, pub dr_range_ok: bool, @@ -1209,7 +1228,8 @@ impl NewChannelAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RxTimingSetupReqPayload { pub delay: u8, } @@ -1234,7 +1254,8 @@ impl RxTimingSetupReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct TxParamSetupReqPayload { pub uplink_dwell_time: DwellTime, pub downlink_dwell_time: DwellTime, @@ -1285,7 +1306,8 @@ impl TxParamSetupReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct DlChannelReqPayload { pub ch_index: u8, pub freq: u32, @@ -1327,7 +1349,8 @@ impl DlChannelReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct DlChannelAnsPayload { pub uplink_freq_exists: bool, pub channel_freq_ok: bool, @@ -1361,7 +1384,8 @@ impl DlChannelAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RekeyConfPayload { pub serv_lorawan_version: Version, } @@ -1384,7 +1408,8 @@ impl RekeyConfPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RekeyIndPayload { pub dev_lorawan_version: Version, } @@ -1407,7 +1432,8 @@ impl RekeyIndPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct ADRParamSetupReqPayload { pub adr_param: ADRParam, } @@ -1430,7 +1456,8 @@ impl ADRParamSetupReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct ADRParam { pub limit_exp: u8, pub delay_exp: u8, @@ -1462,7 +1489,8 @@ impl ADRParam { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct DeviceTimeAnsPayload { pub time_since_gps_epoch: Duration, } @@ -1496,7 +1524,8 @@ impl DeviceTimeAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct ForceRejoinReqPayload { pub period: u8, pub max_retries: u8, @@ -1541,7 +1570,8 @@ impl ForceRejoinReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RejoinParamSetupReqPayload { pub max_time_n: u8, pub max_count_n: u8, @@ -1573,7 +1603,8 @@ impl RejoinParamSetupReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RejoinParamSetupAnsPayload { pub time_ok: bool, } @@ -1600,7 +1631,8 @@ impl RejoinParamSetupAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct PingSlotInfoReqPayload { pub periodicity: u8, } @@ -1627,7 +1659,8 @@ impl PingSlotInfoReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct PingSlotChannelReqPayload { pub freq: u32, pub dr: u8, @@ -1669,7 +1702,8 @@ impl PingSlotChannelReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct PingSlotChannelAnsPayload { pub dr_ok: bool, pub channel_freq_ok: bool, @@ -1704,7 +1738,8 @@ impl PingSlotChannelAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct BeaconFreqReqPayload { pub freq: u32, } @@ -1741,7 +1776,8 @@ impl BeaconFreqReqPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct BeaconFreqAnsPayload { beacon_freq_ok: bool, } @@ -1768,7 +1804,8 @@ impl BeaconFreqAnsPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct DeviceModeIndPayload { pub class: DeviceModeClass, } @@ -1791,7 +1828,8 @@ impl DeviceModeIndPayload { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct DeviceModeConfPayload { pub class: DeviceModeClass, } diff --git a/lrwn/src/mhdr.rs b/lrwn/src/mhdr.rs index de51d1fe..19f7c6cc 100644 --- a/lrwn/src/mhdr.rs +++ b/lrwn/src/mhdr.rs @@ -1,9 +1,11 @@ use std::fmt; use anyhow::Result; +#[cfg(feature = "serde")] use serde::Serialize; -#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum MType { JoinRequest, JoinAccept, @@ -21,12 +23,14 @@ impl fmt::Display for MType { } } -#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum Major { LoRaWANR1, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct MHDR { pub m_type: MType, pub major: Major, diff --git a/lrwn/src/netid.rs b/lrwn/src/netid.rs index f8ab8e44..eaecf608 100644 --- a/lrwn/src/netid.rs +++ b/lrwn/src/netid.rs @@ -2,8 +2,11 @@ use std::fmt; use std::str::FromStr; use anyhow::Result; -use serde::de::{self, Visitor}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "serde")] +use serde::{ + de::{self, Visitor}, + {Deserialize, Deserializer, Serialize, Serializer}, +}; use crate::devaddr::DevAddrPrefix; use crate::Error; @@ -132,6 +135,7 @@ impl FromStr for NetID { } } +#[cfg(feature = "serde")] impl Serialize for NetID { fn serialize(&self, serializer: S) -> Result where @@ -141,6 +145,7 @@ impl Serialize for NetID { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for NetID { fn deserialize(deserialize: D) -> Result where @@ -150,8 +155,10 @@ impl<'de> Deserialize<'de> for NetID { } } +#[cfg(feature = "serde")] struct NetIdVisitor; +#[cfg(feature = "serde")] impl<'de> Visitor<'de> for NetIdVisitor { type Value = NetID; diff --git a/lrwn/src/payload.rs b/lrwn/src/payload.rs index ae5474b5..e1a47208 100644 --- a/lrwn/src/payload.rs +++ b/lrwn/src/payload.rs @@ -1,4 +1,5 @@ use anyhow::Result; +#[cfg(feature = "serde")] use serde::{Serialize, Serializer}; use super::cflist::CFList; @@ -21,6 +22,7 @@ pub enum Payload { Raw(Vec), } +#[cfg(feature = "serde")] impl Serialize for Payload { fn serialize(&self, serializer: S) -> Result where @@ -37,7 +39,8 @@ impl Serialize for Payload { } } -#[derive(Serialize, PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum JoinType { Join, RejoinType0, @@ -85,7 +88,8 @@ impl Payload { } } -#[derive(Serialize, PartialEq, Eq, Debug, Copy, Clone)] +#[derive(PartialEq, Eq, Debug, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct JoinRequestPayload { pub join_eui: EUI64, pub dev_eui: EUI64, @@ -120,7 +124,8 @@ impl JoinRequestPayload { } } -#[derive(Serialize, PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct JoinAcceptPayload { pub join_nonce: u32, // the actual max value is (2^24 -1) pub home_netid: NetID, @@ -191,6 +196,7 @@ pub enum FRMPayload { MACCommandSet(MACCommandSet), } +#[cfg(feature = "serde")] impl Serialize for FRMPayload { fn serialize(&self, serializer: S) -> Result where @@ -212,7 +218,8 @@ impl FRMPayload { } } -#[derive(Serialize, PartialEq, Eq, Debug, Clone, Default)] +#[derive(PartialEq, Eq, Debug, Clone, Default)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct MACPayload { pub fhdr: FHDR, pub f_port: Option, @@ -287,7 +294,8 @@ impl MACPayload { } } -#[derive(Serialize, PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RejoinRequestType02Payload { pub rejoin_type: JoinType, pub netid: NetID, @@ -343,7 +351,8 @@ impl RejoinRequestType02Payload { } } -#[derive(Serialize, PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct RejoinRequestType1Payload { pub rejoin_type: JoinType, pub join_eui: EUI64, diff --git a/lrwn/src/phy_payload.rs b/lrwn/src/phy_payload.rs index 366492bd..8cc1a43b 100644 --- a/lrwn/src/phy_payload.rs +++ b/lrwn/src/phy_payload.rs @@ -1,17 +1,27 @@ -use aes::cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt}; -use aes::{Aes128, Block}; +#[cfg(feature = "crypto")] +use aes::{ + cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt}, + Aes128, Block, +}; use anyhow::Result; +#[cfg(feature = "crypto")] use cmac::{Cmac, Mac}; +#[cfg(feature = "serde")] use serde::Serialize; -use super::aes128::AES128Key; -use super::devaddr::DevAddr; -use super::eui64::EUI64; use super::maccommand::{MACCommand, MACCommandSet}; use super::mhdr::{MType, MHDR}; -use super::payload::{FRMPayload, JoinAcceptPayload, JoinType, Payload}; +use super::payload::{FRMPayload, Payload}; +#[cfg(feature = "crypto")] +use super::{ + aes128::AES128Key, + devaddr::DevAddr, + eui64::EUI64, + payload::{JoinAcceptPayload, JoinType}, +}; -#[derive(PartialEq, Eq, Clone, Copy, Serialize)] +#[derive(PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub enum MACVersion { LoRaWAN1_0, LoRaWAN1_1, @@ -310,7 +320,8 @@ pub enum MACVersion { /// let phy_decoded = PhyPayload::from_slice(&bytes).unwrap(); /// assert_eq!(phy, phy_decoded); /// ``` -#[derive(Debug, PartialEq, Eq, Clone, Serialize)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct PhyPayload { pub mhdr: MHDR, pub payload: Payload, @@ -374,6 +385,7 @@ impl PhyPayload { /// Calculate and set the MIC field for uplink data frames. /// The conf_f_cnt, tx_dr, tx_ch and s_nwk_s_int_key are only required for LoRaWAN 1.1 and can /// be left blank for LoRaWAN 1.0. + #[cfg(feature = "crypto")] pub fn set_uplink_data_mic( &mut self, mac_version: MACVersion, @@ -399,6 +411,7 @@ impl PhyPayload { /// frame-counter value, as only the 16 lsb are transmitted over the air. /// The conf_f_cnt, tx_dr, tx_ch and s_nwk_s_int_key are only required for LoRaWAN 1.1 and can /// be left blank for LoRaWAN 1.0. + #[cfg(feature = "crypto")] pub fn validate_uplink_data_mic( &self, mac_version: MACVersion, @@ -425,6 +438,7 @@ impl PhyPayload { /// Set the MIC for downlink data frames. /// The conf_f_cnt is only required for LoRaWAN 1.1 and can be left blank for LoRaWAN 1.0. + #[cfg(feature = "crypto")] pub fn set_downlink_data_mic( &mut self, mac_version: MACVersion, @@ -436,6 +450,7 @@ impl PhyPayload { Ok(()) } + #[cfg(feature = "crypto")] pub fn validate_downlink_data_mic( &mut self, mac_version: MACVersion, @@ -453,6 +468,7 @@ impl PhyPayload { /// Validate the cmacF part of the uplink data MIC (LoRaWAN 1.1 only). /// In order to validate the MIC, the f_cnt value must be first set to the full 32 bit /// frame-counter value, as only the 16 lsb are transmitted over the air. + #[cfg(feature = "crypto")] pub fn validate_uplink_data_micf(&self, f_nwk_s_int_key: &AES128Key) -> Result { // We are only interested in mic[2:] (cmacF bytes), therefore there is no // need to pass the correct confFCnt, txDR, txCh and sNwkSIntKey parameters. @@ -473,12 +489,14 @@ impl PhyPayload { } /// Set the join-request MIC. + #[cfg(feature = "crypto")] pub fn set_join_request_mic(&mut self, key: &AES128Key) -> Result<()> { self.mic = Some(self.calculate_upink_join_mic(key)?); Ok(()) } /// Validate the join-request MIC. + #[cfg(feature = "crypto")] pub fn validate_join_request_mic(&self, key: &AES128Key) -> Result { if let Some(v) = self.mic { let mic = self.calculate_upink_join_mic(key)?; @@ -489,6 +507,7 @@ impl PhyPayload { } /// Set the the downlink join-accept MIC. + #[cfg(feature = "crypto")] pub fn set_join_accept_mic( &mut self, join_req_type: JoinType, @@ -502,6 +521,7 @@ impl PhyPayload { } /// Validate the downlink join-accept MIC. + #[cfg(feature = "crypto")] pub fn validate_join_accept_mic( &self, join_req_type: JoinType, @@ -522,6 +542,7 @@ impl PhyPayload { /// the encrypted payload. /// For encrypting a join-request response, use the nwk_key, for rejoin-request 0, 1 and 3 /// response, use the js_enc_key. + #[cfg(feature = "crypto")] pub fn encrypt_join_accept_payload(&mut self, key: &AES128Key) -> Result<()> { use aes::cipher::KeyInit; @@ -566,6 +587,7 @@ impl PhyPayload { /// of the encrypted payload. /// For decrypting a join-request response, use the nwk_key, for rejoin-request 0, 1 and 3 /// response, use the js_enc_key. + #[cfg(feature = "crypto")] pub fn decrypt_join_accept_payload(&mut self, key: &AES128Key) -> Result<()> { use aes::cipher::KeyInit; @@ -608,6 +630,7 @@ impl PhyPayload { } /// Encrypt the f_opts with the given key. + #[cfg(feature = "crypto")] pub fn encrypt_f_opts(&mut self, nwk_s_enc_key: &AES128Key) -> Result<()> { if let Payload::MACPayload(pl) = &mut self.payload { let f_opts_bytes = pl.fhdr.f_opts.to_vec()?; @@ -638,6 +661,7 @@ impl PhyPayload { /// Decrypt the f_opts with the given key. /// This automatically calls decode_f_opts_to_mac_commands. + #[cfg(feature = "crypto")] pub fn decrypt_f_opts(&mut self, nwk_s_enc_key: &AES128Key) -> Result<()> { self.encrypt_f_opts(nwk_s_enc_key)?; self.decode_f_opts_to_mac_commands()?; @@ -674,6 +698,7 @@ impl PhyPayload { } /// Encrypt the frm_payload with the given key. + #[cfg(feature = "crypto")] pub fn encrypt_frm_payload(&mut self, key: &AES128Key) -> Result<()> { if let Payload::MACPayload(pl) = &mut self.payload { // nothing to do @@ -693,6 +718,7 @@ impl PhyPayload { } /// Decrypt the frm_payload with the given key. + #[cfg(feature = "crypto")] pub fn decrypt_frm_payload(&mut self, key: &AES128Key) -> Result<()> { if let Payload::MACPayload(pl) = &mut self.payload { // nothing to do @@ -718,6 +744,7 @@ impl PhyPayload { Err(anyhow!("payload must be of type MACPayload")) } + #[cfg(feature = "crypto")] fn calculate_uplink_data_mic( &self, mac_version: MACVersion, @@ -797,6 +824,7 @@ impl PhyPayload { Err(anyhow!("payload must be of type MACPayload")) } + #[cfg(feature = "crypto")] fn calculate_downlink_data_mic( &self, mac_version: MACVersion, @@ -844,6 +872,7 @@ impl PhyPayload { Err(anyhow!("payload must be of type MACPayload")) } + #[cfg(feature = "crypto")] fn calculate_upink_join_mic(&self, key: &AES128Key) -> Result<[u8; 4]> { // mic bytes let mut mic_bytes = Vec::new(); @@ -864,6 +893,7 @@ impl PhyPayload { Ok(mic) } + #[cfg(feature = "crypto")] fn calculate_downlink_join_mic( &self, join_req_type: JoinType, @@ -916,6 +946,7 @@ impl PhyPayload { /// Set the a_fcnt_down to false and use the n_fcnt_down as f_cnt. /// For downlink if f_port > 0: /// Set the a_fcnt_down to true and use the a_f_cnt_down as f_cnt. +#[cfg(feature = "crypto")] pub fn encrypt_f_opts( nwk_s_enc_key: &AES128Key, a_fcnt_down: bool, @@ -963,6 +994,7 @@ pub fn encrypt_f_opts( /// Encrypt (and decrypt) the frm_payload. /// Note that the same function is used for encryption and decryption. +#[cfg(feature = "crypto")] pub fn encrypt_frm_payload( key: &AES128Key, uplink: bool, diff --git a/lrwn/src/region/mod.rs b/lrwn/src/region/mod.rs index 1ed3939a..6ba30721 100644 --- a/lrwn/src/region/mod.rs +++ b/lrwn/src/region/mod.rs @@ -4,9 +4,13 @@ use std::str::FromStr; use std::time::Duration; use anyhow::{Context, Result}; -use diesel::backend::{self, Backend}; -use diesel::sql_types::Text; -use diesel::{deserialize, serialize}; +#[cfg(feature = "diesel")] +use diesel::{ + backend::{self, Backend}, + sql_types::Text, + {deserialize, serialize}, +}; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use crate::{ @@ -25,9 +29,11 @@ pub mod kr920; pub mod ru864; pub mod us915; -#[derive(Deserialize, Serialize, Copy, Clone, Debug, Eq, PartialEq, AsExpression, FromSqlRow)] #[allow(non_camel_case_types)] -#[diesel(sql_type = diesel::sql_types::Text)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] pub enum CommonName { EU868, US915, @@ -51,6 +57,7 @@ impl fmt::Display for CommonName { } } +#[cfg(feature = "diesel")] impl deserialize::FromSql for CommonName where DB: Backend, @@ -62,6 +69,7 @@ where } } +#[cfg(feature = "diesel")] impl serialize::ToSql for CommonName where str: serialize::ToSql, @@ -104,8 +112,9 @@ impl FromStr for CommonName { } #[allow(non_camel_case_types)] -#[derive(Clone, Copy, PartialEq, Eq, Hash, AsExpression, FromSqlRow)] -#[diesel(sql_type = diesel::sql_types::Text)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] pub enum Revision { Latest, A, @@ -159,6 +168,7 @@ impl FromStr for Revision { } } +#[cfg(feature = "diesel")] impl deserialize::FromSql for Revision where DB: Backend, @@ -170,6 +180,7 @@ where } } +#[cfg(feature = "diesel")] impl serialize::ToSql for Revision where str: serialize::ToSql, @@ -186,8 +197,9 @@ where } #[allow(non_camel_case_types)] -#[derive(Copy, Clone, PartialEq, Eq, Hash, AsExpression, FromSqlRow)] -#[diesel(sql_type = diesel::sql_types::Text)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] pub enum MacVersion { Latest, LORAWAN_1_0_0, @@ -241,6 +253,7 @@ impl FromStr for MacVersion { } } +#[cfg(feature = "diesel")] impl deserialize::FromSql for MacVersion where DB: Backend, @@ -252,6 +265,7 @@ where } } +#[cfg(feature = "diesel")] impl serialize::ToSql for MacVersion where str: serialize::ToSql,