From b59dee95a274b75d083f1948471a2e5f03f6215b Mon Sep 17 00:00:00 2001 From: Sven Friedrich Date: Thu, 13 Jun 2024 13:40:55 +0200 Subject: [PATCH 1/5] chore: flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'devshell': 'github:numtide/devshell/83cb93d6d063ad290beee669f4badf9914cc16ec' (2024-01-15) → 'github:numtide/devshell/1ebbe68d57457c8cae98145410b164b5477761f4' (2024-06-03) • Updated input 'fenix': 'github:nix-community/fenix/46a368edf5f1cc16573157797e5acead834d5b2c' (2024-01-30) → 'github:nix-community/fenix/ab655c627777ab5f9964652fe23bbb1dfbd687a8' (2024-06-08) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/d13951f25c4cb880bff09a3c02a796ecc51f69ac' (2024-01-29) → 'github:rust-lang/rust-analyzer/48bbdd6a74f3176987d5c809894ac33957000d19' (2024-06-05) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/6723fa4e4f1a30d42a633bef5eb01caeb281adc3' (2024-01-08) → 'github:nixos/nixpkgs/57d6973abba7ea108bac64ae7629e7431e0199b6' (2024-06-12) • Updated input 'utils': 'github:numtide/flake-utils/1ef2e671c3b0c19053962c07dbda38332dcebf26' (2024-01-15) → 'github:numtide/flake-utils/b1d9ab70662946ef0850d488da1c9019f3a9752a' (2024-03-11) --- flake.lock | 38 ++++++++++++++++++++------------------ flake.nix | 1 + 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/flake.lock b/flake.lock index c269704..74fd1c2 100644 --- a/flake.lock +++ b/flake.lock @@ -6,11 +6,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1705332421, - "narHash": "sha256-USpGLPme1IuqG78JNqSaRabilwkCyHmVWY0M9vYyqEA=", + "lastModified": 1717408969, + "narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=", "owner": "numtide", "repo": "devshell", - "rev": "83cb93d6d063ad290beee669f4badf9914cc16ec", + "rev": "1ebbe68d57457c8cae98145410b164b5477761f4", "type": "github" }, "original": { @@ -27,11 +27,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1706595721, - "narHash": "sha256-nf5/lPawM20WO1gHAlsUwDEJ4v+InC3BYYV1EBsBJZk=", + "lastModified": 1717827974, + "narHash": "sha256-ixopuTeTouxqTxfMuzs6IaRttbT8JqRW5C9Q/57WxQw=", "owner": "nix-community", "repo": "fenix", - "rev": "46a368edf5f1cc16573157797e5acead834d5b2c", + "rev": "ab655c627777ab5f9964652fe23bbb1dfbd687a8", "type": "github" }, "original": { @@ -76,16 +76,18 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1704732714, - "narHash": "sha256-ABqK/HggMYA/jMUXgYyqVAcQ8QjeMyr1jcXfTpSHmps=", - "owner": "NixOS", + "lastModified": 1718160348, + "narHash": "sha256-9YrUjdztqi4Gz8n3mBuqvCkMo4ojrA6nASwyIKWMpus=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "6723fa4e4f1a30d42a633bef5eb01caeb281adc3", + "rev": "57d6973abba7ea108bac64ae7629e7431e0199b6", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" } }, "root": { @@ -99,11 +101,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1706540258, - "narHash": "sha256-6RTztJE21l0hfWHp0qMWBurWnoFmUxYEDCvaGTnQYcA=", + "lastModified": 1717583671, + "narHash": "sha256-+lRAmz92CNUxorqWusgJbL9VE1eKCnQQojglRemzwkw=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "d13951f25c4cb880bff09a3c02a796ecc51f69ac", + "rev": "48bbdd6a74f3176987d5c809894ac33957000d19", "type": "github" }, "original": { @@ -148,11 +150,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index fc99446..7a1261c 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,6 @@ { inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; utils.url = "github:numtide/flake-utils"; devshell.url = "github:numtide/devshell"; fenix.url = "github:nix-community/fenix"; From 6698cf4fc91dc9dd412bc0d58cdd940696d83455 Mon Sep 17 00:00:00 2001 From: Sven Friedrich Date: Wed, 3 Apr 2024 11:55:48 +0200 Subject: [PATCH 2/5] feat!: remove const generic from channel Removes const generics from all channel types. Ditches nightly feature which was used with the const generics. Renames functions for more clarity. --- Cargo.toml | 3 +-- src/error.rs | 33 ++++++++------------------------- src/lib.rs | 3 --- src/queuing.rs | 46 ++++++++++++++++------------------------------ src/sampling.rs | 44 +++++++++++++++++--------------------------- 5 files changed, 42 insertions(+), 87 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0fb10b1..e23d2aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,5 @@ license = "MIT OR Apache-2.0" [dependencies] serde = { version = "1.0", features = ["derive"], default-features = false } postcard = { version = "1.0", default-features = false } -arrayvec = { version = "0.7", default-features = false } -a653rs = "0.5" +a653rs = "0.6" diff --git a/src/error.rs b/src/error.rs index aa75d8e..9cff111 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,43 +1,26 @@ use a653rs::prelude::*; -use arrayvec::ArrayVec; #[derive(Debug, Clone)] -pub enum QueuingRecvError -where - [u8; MSG_SIZE as usize]:, -{ +pub enum QueuingRecvBufError<'a> { Apex(a653rs::prelude::Error), - Postcard(postcard::Error, ArrayVec), + Postcard(postcard::Error, &'a [u8]), } -impl From for QueuingRecvError -where - [u8; MSG_SIZE as usize]:, -{ +impl From for QueuingRecvBufError<'_> { fn from(e: a653rs::prelude::Error) -> Self { - QueuingRecvError::Apex(e) + QueuingRecvBufError::Apex(e) } } #[derive(Debug, Clone)] -pub enum SamplingRecvError -where - [u8; MSG_SIZE as usize]:, -{ +pub enum SamplingRecvBufError<'a> { Apex(a653rs::prelude::Error), - Postcard( - postcard::Error, - Validity, - ArrayVec, - ), + Postcard(postcard::Error, Validity, &'a [u8]), } -impl From for SamplingRecvError -where - [u8; MSG_SIZE as usize]:, -{ +impl From for SamplingRecvBufError<'_> { fn from(e: a653rs::prelude::Error) -> Self { - SamplingRecvError::Apex(e) + SamplingRecvBufError::Apex(e) } } diff --git a/src/lib.rs b/src/lib.rs index 90da82e..cd6cbae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,4 @@ #![no_std] -// #![deny(missing_docs)] -#![allow(incomplete_features)] -#![feature(generic_const_exprs)] #![deny(rustdoc::broken_intra_doc_links)] pub mod error; diff --git a/src/queuing.rs b/src/queuing.rs index d0274e1..95fabf2 100644 --- a/src/queuing.rs +++ b/src/queuing.rs @@ -1,5 +1,4 @@ use a653rs::prelude::*; -use arrayvec::ArrayVec; use postcard::de_flavors::Slice as DeSlice; use postcard::ser_flavors::Slice as SerSlice; use serde::{Deserialize, Serialize}; @@ -7,60 +6,47 @@ use serde::{Deserialize, Serialize}; use crate::error::*; pub trait QueuingPortSenderExt { - fn send_type(&self, p: T, timeout: SystemTime) -> Result<(), SendError> + fn send_type_buf(&self, p: T, timeout: SystemTime, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize; } -pub trait QueuingPortReceiverExt { - fn recv_type( - &self, +pub trait QueuingPortReceiverExt { + fn recv_type_buf<'a, T>( + &'a self, timeout: SystemTime, - ) -> Result<(T, QueueOverflow), QueuingRecvError> + buf: &'a mut [u8], + ) -> Result<(T, QueueOverflow), QueuingRecvBufError<'a>> where - T: for<'a> Deserialize<'a>, - [u8; MSG_SIZE as usize]:; + T: for<'b> Deserialize<'b>; } -impl - QueuingPortSenderExt for QueuingPortSender -where - [u8; MSG_SIZE as usize]:, -{ - fn send_type(&self, p: T, timeout: SystemTime) -> Result<(), SendError> +impl QueuingPortSenderExt for QueuingPortSender { + fn send_type_buf(&self, p: T, timeout: SystemTime, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize, { - let buf = &mut [0u8; MSG_SIZE as usize]; let buf = postcard::serialize_with_flavor::(&p, SerSlice::new(buf))?; self.send(buf, timeout).map_err(SendError::from) } } -impl - QueuingPortReceiverExt for QueuingPortReceiver -where - [u8; MSG_SIZE as usize]:, -{ - fn recv_type( +impl QueuingPortReceiverExt for QueuingPortReceiver { + fn recv_type_buf<'a, T>( &self, timeout: SystemTime, - ) -> Result<(T, QueueOverflow), QueuingRecvError> + buf: &'a mut [u8], + ) -> Result<(T, QueueOverflow), QueuingRecvBufError<'a>> where - T: for<'a> Deserialize<'a>, + T: for<'b> Deserialize<'b>, { - let mut msg_buf = [0u8; MSG_SIZE as usize]; - let (msg, overflow) = self.receive(&mut msg_buf, timeout)?; + let (msg, overflow) = self.receive(buf, timeout)?; let msg_slice = DeSlice::new(msg); let mut deserializer = postcard::Deserializer::from_flavor(msg_slice); match T::deserialize(&mut deserializer) { Ok(t) => Ok((t, overflow)), - Err(e) => { - let mut msg = ArrayVec::from(msg_buf); - msg.truncate(msg.len()); - Err(QueuingRecvError::Postcard(e, msg)) - } + Err(e) => Err(QueuingRecvBufError::Postcard(e, msg)), } } } diff --git a/src/sampling.rs b/src/sampling.rs index e0aa1d9..0dd0f7f 100644 --- a/src/sampling.rs +++ b/src/sampling.rs @@ -1,5 +1,4 @@ use a653rs::prelude::*; -use arrayvec::ArrayVec; use postcard::de_flavors::Slice as DeSlice; use postcard::ser_flavors::Slice as SerSlice; use serde::{Deserialize, Serialize}; @@ -7,54 +6,45 @@ use serde::{Deserialize, Serialize}; use crate::error::*; pub trait SamplingPortSourceExt { - fn send_type(&self, p: T) -> Result<(), SendError> + fn send_type_buf(&self, p: T, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize; } -pub trait SamplingPortDestinationExt { - fn recv_type(&self) -> Result<(Validity, T), SamplingRecvError> +pub trait SamplingPortDestinationExt { + fn recv_type_buf<'a, T>( + &self, + buf: &'a mut [u8], + ) -> Result<(Validity, T), SamplingRecvBufError<'a>> where - T: for<'a> Deserialize<'a>, - [u8; MSG_SIZE as usize]:; + T: for<'b> Deserialize<'b>; } -impl SamplingPortSourceExt - for SamplingPortSource -where - [u8; MSG_SIZE as usize]:, -{ - fn send_type(&self, p: T) -> Result<(), SendError> +impl SamplingPortSourceExt for SamplingPortSource { + fn send_type_buf(&self, p: T, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize, { - let buf = &mut [0u8; MSG_SIZE as usize]; let buf = postcard::serialize_with_flavor::(&p, SerSlice::new(buf))?; self.send(buf).map_err(SendError::from) } } -impl SamplingPortDestinationExt - for SamplingPortDestination -where - [u8; MSG_SIZE as usize]:, -{ - fn recv_type(&self) -> Result<(Validity, T), SamplingRecvError> +impl SamplingPortDestinationExt for SamplingPortDestination { + fn recv_type_buf<'a, T>( + &self, + buf: &'a mut [u8], + ) -> Result<(Validity, T), SamplingRecvBufError<'a>> where - T: for<'a> Deserialize<'a>, + T: for<'b> Deserialize<'b>, { - let mut msg_buf = [0u8; MSG_SIZE as usize]; - let (val, msg) = self.receive(&mut msg_buf)?; + let (val, msg) = self.receive(buf)?; let msg_slice = DeSlice::new(msg); let mut deserializer = postcard::Deserializer::from_flavor(msg_slice); match T::deserialize(&mut deserializer) { Ok(t) => Ok((val, t)), - Err(e) => { - let mut msg = ArrayVec::from(msg_buf); - msg.truncate(msg.len()); - Err(SamplingRecvError::Postcard(e, val, msg)) - } + Err(e) => Err(SamplingRecvBufError::Postcard(e, val, msg)), } } } From e8953b7d4e5645784c6ec716da1bbe6d79264af2 Mon Sep 17 00:00:00 2001 From: Sven Friedrich Date: Wed, 3 Apr 2024 15:04:31 +0200 Subject: [PATCH 3/5] feat: add alloc feature --- .github/workflows/nix.yml | 1 + Cargo.toml | 10 ++++++++++ flake.nix | 19 ++++++++++++++---- src/error.rs | 34 +++++++++++++++++++++++++++++++ src/queuing.rs | 42 +++++++++++++++++++++++++++++++++++++++ src/sampling.rs | 42 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 144 insertions(+), 4 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index c894053..c4b341d 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -27,6 +27,7 @@ jobs: command: - verify-no_std - verify-doc + - verify-features steps: - uses: actions/checkout@v2 - name: Install Nix diff --git a/Cargo.toml b/Cargo.toml index e23d2aa..c719f0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,18 @@ license = "MIT OR Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = [] +alloc = ["postcard/alloc"] + [dependencies] serde = { version = "1.0", features = ["derive"], default-features = false } postcard = { version = "1.0", default-features = false } a653rs = "0.6" + +[package.metadata.cargo-all-features] +skip_optional_dependencies = true + +[package.metadata."docs.rs"] +all-features = true diff --git a/flake.nix b/flake.nix index 7a1261c..2ca3e6f 100644 --- a/flake.nix +++ b/flake.nix @@ -17,11 +17,11 @@ }; rust-toolchain = with fenix.packages.${system}; combine [ - latest.rustc - latest.cargo - latest.clippy + stable.rustc + stable.cargo + stable.clippy latest.rustfmt - targets.thumbv6m-none-eabi.latest.rust-std + targets.thumbv6m-none-eabi.stable.rust-std ]; in rec { @@ -35,6 +35,7 @@ cargo-outdated cargo-audit cargo-udeps + cargo-all-features cargo-watch nixpkgs-fmt ]; @@ -83,6 +84,16 @@ "Verify that the documentation builds without problems"; category = "test"; } + { + name = "verify-features"; + command = '' + cd $PRJ_ROOT + cargo check-all-features $@ + ''; + help = + "Verify that all feature combinations build"; + category = "test"; + } ]; }); checks = { diff --git a/src/error.rs b/src/error.rs index 9cff111..3403af8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,25 @@ +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +#[cfg(feature = "alloc")] +extern crate alloc; + use a653rs::prelude::*; +#[cfg(feature = "alloc")] +#[derive(Debug, Clone)] +pub enum QueuingRecvError { + Apex(a653rs::prelude::Error), + Postcard(postcard::Error, Vec), +} + +#[cfg(feature = "alloc")] +impl From for QueuingRecvError { + fn from(e: a653rs::prelude::Error) -> Self { + QueuingRecvError::Apex(e) + } +} + #[derive(Debug, Clone)] pub enum QueuingRecvBufError<'a> { Apex(a653rs::prelude::Error), @@ -12,6 +32,20 @@ impl From for QueuingRecvBufError<'_> { } } +#[cfg(feature = "alloc")] +#[derive(Debug, Clone)] +pub enum SamplingRecvError { + Apex(a653rs::prelude::Error), + Postcard(postcard::Error, Validity, Vec), +} + +#[cfg(feature = "alloc")] +impl From for SamplingRecvError { + fn from(e: a653rs::prelude::Error) -> Self { + SamplingRecvError::Apex(e) + } +} + #[derive(Debug, Clone)] pub enum SamplingRecvBufError<'a> { Apex(a653rs::prelude::Error), diff --git a/src/queuing.rs b/src/queuing.rs index 95fabf2..0d8e9ac 100644 --- a/src/queuing.rs +++ b/src/queuing.rs @@ -1,3 +1,9 @@ +#[cfg(feature = "alloc")] +use alloc::vec; + +#[cfg(feature = "alloc")] +extern crate alloc; + use a653rs::prelude::*; use postcard::de_flavors::Slice as DeSlice; use postcard::ser_flavors::Slice as SerSlice; @@ -6,12 +12,22 @@ use serde::{Deserialize, Serialize}; use crate::error::*; pub trait QueuingPortSenderExt { + #[cfg(feature = "alloc")] + fn send_type(&self, p: T, timeout: SystemTime) -> Result<(), SendError> + where + T: Serialize; + fn send_type_buf(&self, p: T, timeout: SystemTime, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize; } pub trait QueuingPortReceiverExt { + #[cfg(feature = "alloc")] + fn recv_type(&self, timeout: SystemTime) -> Result<(T, QueueOverflow), QueuingRecvError> + where + T: for<'a> Deserialize<'a>; + fn recv_type_buf<'a, T>( &'a self, timeout: SystemTime, @@ -22,6 +38,15 @@ pub trait QueuingPortReceiverExt { } impl QueuingPortSenderExt for QueuingPortSender { + #[cfg(feature = "alloc")] + fn send_type(&self, p: T, timeout: SystemTime) -> Result<(), SendError> + where + T: Serialize, + { + let msg = postcard::to_allocvec(&p)?; + self.send(&msg, timeout).map_err(SendError::from) + } + fn send_type_buf(&self, p: T, timeout: SystemTime, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize, @@ -33,6 +58,23 @@ impl QueuingPortSenderExt for QueuingPortSender { } impl QueuingPortReceiverExt for QueuingPortReceiver { + #[cfg(feature = "alloc")] + fn recv_type(&self, timeout: SystemTime) -> Result<(T, QueueOverflow), QueuingRecvError> + where + T: for<'a> Deserialize<'a>, + { + let mut buf = vec![0; self.size()]; + let (msg, overflow) = self.receive(&mut buf, timeout)?; + match postcard::from_bytes(msg) { + Ok(t) => Ok((t, overflow)), + Err(e) => { + let msg_len = msg.len(); + buf.truncate(msg_len); + Err(QueuingRecvError::Postcard(e, buf)) + } + } + } + fn recv_type_buf<'a, T>( &self, timeout: SystemTime, diff --git a/src/sampling.rs b/src/sampling.rs index 0dd0f7f..694e882 100644 --- a/src/sampling.rs +++ b/src/sampling.rs @@ -1,3 +1,9 @@ +#[cfg(feature = "alloc")] +use alloc::vec; + +#[cfg(feature = "alloc")] +extern crate alloc; + use a653rs::prelude::*; use postcard::de_flavors::Slice as DeSlice; use postcard::ser_flavors::Slice as SerSlice; @@ -6,12 +12,22 @@ use serde::{Deserialize, Serialize}; use crate::error::*; pub trait SamplingPortSourceExt { + #[cfg(feature = "alloc")] + fn send_type(&self, p: T) -> Result<(), SendError> + where + T: Serialize; + fn send_type_buf(&self, p: T, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize; } pub trait SamplingPortDestinationExt { + #[cfg(feature = "alloc")] + fn recv_type(&self) -> Result<(Validity, T), SamplingRecvError> + where + T: for<'a> Deserialize<'a>; + fn recv_type_buf<'a, T>( &self, buf: &'a mut [u8], @@ -21,6 +37,15 @@ pub trait SamplingPortDestinationExt { } impl SamplingPortSourceExt for SamplingPortSource { + #[cfg(feature = "alloc")] + fn send_type(&self, p: T) -> Result<(), SendError> + where + T: Serialize, + { + let msg = postcard::to_allocvec(&p)?; + self.send(&msg).map_err(SendError::from) + } + fn send_type_buf(&self, p: T, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize, @@ -32,6 +57,23 @@ impl SamplingPortSourceExt for SamplingPortSource { } impl SamplingPortDestinationExt for SamplingPortDestination { + #[cfg(feature = "alloc")] + fn recv_type<'a, T>(&self) -> Result<(Validity, T), SamplingRecvError> + where + T: for<'b> Deserialize<'b>, + { + let mut buf = vec![0; self.size() as usize]; + let (val, msg) = self.receive(&mut buf)?; + match postcard::from_bytes(msg) { + Ok(t) => Ok((val, t)), + Err(e) => { + let msg_len = msg.len(); + buf.truncate(msg_len); + Err(SamplingRecvError::Postcard(e, val, buf)) + } + } + } + fn recv_type_buf<'a, T>( &self, buf: &'a mut [u8], From f0986a1ef3b7c319f994acbb446b5533174e80c5 Mon Sep 17 00:00:00 2001 From: Sven Friedrich Date: Thu, 13 Jun 2024 13:32:21 +0200 Subject: [PATCH 4/5] test: add tests --- .github/workflows/nix.yml | 1 + Cargo.toml | 11 ++- flake.nix | 10 +++ src/queuing.rs | 142 ++++++++++++++++++++++++++++++++++++++ src/sampling.rs | 104 ++++++++++++++++++++++++++++ tests/mock.rs | 108 +++++++++++++++++++++++++++++ tests/mock_test.rs | 125 +++++++++++++++++++++++++++++++++ 7 files changed, 499 insertions(+), 2 deletions(-) create mode 100644 tests/mock.rs create mode 100644 tests/mock_test.rs diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index c4b341d..def3cbc 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -28,6 +28,7 @@ jobs: - verify-no_std - verify-doc - verify-features + - verify-tests steps: - uses: actions/checkout@v2 - name: Install Nix diff --git a/Cargo.toml b/Cargo.toml index c719f0c..97fadc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,13 +12,20 @@ default = [] alloc = ["postcard/alloc"] [dependencies] -serde = { version = "1.0", features = ["derive"], default-features = false } +serde.workspace = true postcard = { version = "1.0", default-features = false } +a653rs.workspace = true -a653rs = "0.6" +[dev-dependencies] +a653rs = { workspace = true, features = ["bindings"] } +serde = { workspace = true, features = ["alloc"] } [package.metadata.cargo-all-features] skip_optional_dependencies = true [package.metadata."docs.rs"] all-features = true + +[workspace.dependencies] +a653rs = "0.6" +serde = { version = "1.0", default-features = false} diff --git a/flake.nix b/flake.nix index 2ca3e6f..200fccf 100644 --- a/flake.nix +++ b/flake.nix @@ -94,6 +94,16 @@ "Verify that all feature combinations build"; category = "test"; } + { + name = "verify-tests"; + command = '' + cd $PRJ_ROOT + cargo test-all-features $@ + ''; + help = + "Verify that all tests run for all feature combinations"; + category = "test"; + } ]; }); checks = { diff --git a/src/queuing.rs b/src/queuing.rs index 0d8e9ac..1134804 100644 --- a/src/queuing.rs +++ b/src/queuing.rs @@ -92,3 +92,145 @@ impl QueuingPortReceiverExt for QueuingPortReceiver } } } + +#[cfg(test)] +#[path = "../tests"] +mod tests { + use core::str::FromStr; + use std::string::String; + + use a653rs::bindings::QueuingDiscipline; + use a653rs::prelude::{Name, SystemTime}; + use mock::MockHyp; + + use crate::prelude::{QueuingPortReceiverExt, QueuingPortSenderExt}; + + extern crate std; + + #[allow(clippy::duplicate_mod)] + mod mock; + + #[test] + fn queuing_type_buf() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_queuing_port_sender( + Name::from_str("").unwrap(), + 500, + 0, + QueuingDiscipline::Fifo, + ) + .unwrap(); + let dest_port = ctx + .create_queuing_port_receiver( + Name::from_str("").unwrap(), + 500, + 0, + QueuingDiscipline::Fifo, + ) + .unwrap(); + + let msg = String::from("Test"); + let mut buf = [0; 500]; + + src_port + .send_type_buf(msg.clone(), SystemTime::Infinite, &mut buf) + .unwrap(); + let (rec, _): (String, _) = dest_port + .recv_type_buf(SystemTime::Infinite, &mut buf) + .unwrap(); + + assert_eq!(msg, rec) + }) + } + + #[test] + fn const_queuing_type_buf() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_const_queuing_port_sender::<500, 0>( + Name::from_str("").unwrap(), + QueuingDiscipline::Fifo, + ) + .unwrap(); + let dest_port = ctx + .create_const_queuing_port_receiver::<500, 0>( + Name::from_str("").unwrap(), + QueuingDiscipline::Fifo, + ) + .unwrap(); + + let msg = String::from("Test"); + let mut buf = [0; 500]; + + src_port + .send_type_buf(msg.clone(), SystemTime::Infinite, &mut buf) + .unwrap(); + let (rec, _): (String, _) = dest_port + .recv_type_buf(SystemTime::Infinite, &mut buf) + .unwrap(); + + assert_eq!(msg, rec) + }) + } + + #[cfg(feature = "alloc")] + #[test] + fn queuing_type() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_queuing_port_sender( + Name::from_str("").unwrap(), + 500, + 0, + QueuingDiscipline::Fifo, + ) + .unwrap(); + let dest_port = ctx + .create_queuing_port_receiver( + Name::from_str("").unwrap(), + 500, + 0, + QueuingDiscipline::Fifo, + ) + .unwrap(); + + let msg = String::from("Test"); + + src_port + .send_type(msg.clone(), SystemTime::Infinite) + .unwrap(); + let (rec, _): (String, _) = dest_port.recv_type(SystemTime::Infinite).unwrap(); + + assert_eq!(msg, rec) + }) + } + + #[cfg(feature = "alloc")] + #[test] + fn const_queuing_type() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_const_queuing_port_sender::<500, 0>( + Name::from_str("").unwrap(), + QueuingDiscipline::Fifo, + ) + .unwrap(); + let dest_port = ctx + .create_const_queuing_port_receiver::<500, 0>( + Name::from_str("").unwrap(), + QueuingDiscipline::Fifo, + ) + .unwrap(); + + let msg = String::from("Test"); + + src_port + .send_type(msg.clone(), SystemTime::Infinite) + .unwrap(); + let (rec, _): (String, _) = dest_port.recv_type(SystemTime::Infinite).unwrap(); + + assert_eq!(msg, rec) + }) + } +} diff --git a/src/sampling.rs b/src/sampling.rs index 694e882..40a777e 100644 --- a/src/sampling.rs +++ b/src/sampling.rs @@ -90,3 +90,107 @@ impl SamplingPortDestinationExt for SamplingPortDestin } } } + +#[cfg(test)] +#[path = "../tests"] +mod tests { + use core::str::FromStr; + use core::time::Duration; + use std::string::String; + + use a653rs::prelude::Name; + use mock::MockHyp; + + use crate::prelude::{SamplingPortDestinationExt, SamplingPortSourceExt}; + + extern crate std; + + #[allow(clippy::duplicate_mod)] + mod mock; + + #[test] + fn sampling_type_buf() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_sampling_port_source(Name::from_str("").unwrap(), 500) + .unwrap(); + let dest_port = ctx + .create_sampling_port_destination(Name::from_str("").unwrap(), 500, Duration::ZERO) + .unwrap(); + + let msg = String::from("Test"); + let mut buf = [0; 500]; + + src_port.send_type_buf(msg.clone(), &mut buf).unwrap(); + let (_, rec): (_, String) = dest_port.recv_type_buf(&mut buf).unwrap(); + + assert_eq!(msg, rec) + }) + } + + #[test] + fn const_sampling_type_buf() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_const_sampling_port_source::<500>(Name::from_str("").unwrap()) + .unwrap(); + let dest_port = ctx + .create_const_sampling_port_destination::<500>( + Name::from_str("").unwrap(), + Duration::ZERO, + ) + .unwrap(); + + let msg = String::from("Test"); + let mut buf = [0; 500]; + + src_port.send_type_buf(msg.clone(), &mut buf).unwrap(); + let (_, rec): (_, String) = dest_port.recv_type_buf(&mut buf).unwrap(); + + assert_eq!(msg, rec) + }) + } + + #[cfg(feature = "alloc")] + #[test] + fn sampling_type() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_sampling_port_source(Name::from_str("").unwrap(), 500) + .unwrap(); + let dest_port = ctx + .create_sampling_port_destination(Name::from_str("").unwrap(), 500, Duration::ZERO) + .unwrap(); + + let msg = String::from("Test"); + + src_port.send_type(msg.clone()).unwrap(); + let (_, rec): (_, String) = dest_port.recv_type().unwrap(); + + assert_eq!(msg, rec) + }) + } + + #[cfg(feature = "alloc")] + #[test] + fn const_sampling_type() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_const_sampling_port_source::<500>(Name::from_str("").unwrap()) + .unwrap(); + let dest_port = ctx + .create_const_sampling_port_destination::<500>( + Name::from_str("").unwrap(), + Duration::ZERO, + ) + .unwrap(); + + let msg = String::from("Test"); + + src_port.send_type(msg.clone()).unwrap(); + let (_, rec): (_, String) = dest_port.recv_type().unwrap(); + + assert_eq!(msg, rec) + }) + } +} diff --git a/tests/mock.rs b/tests/mock.rs new file mode 100644 index 0000000..14a2818 --- /dev/null +++ b/tests/mock.rs @@ -0,0 +1,108 @@ +use core::mem::MaybeUninit; +use std::sync::Mutex; +use std::vec::Vec; + +use a653rs::bindings::{ApexQueuingPortP4, ApexSamplingPortP4, Validity}; +use a653rs::prelude::StartContext; + +extern crate std; + +static mut SAMPLING_PORTS: Vec = Vec::new(); +static mut QUEUING_PORTS: Vec> = Vec::new(); +static SYNC: Mutex<()> = Mutex::new(()); + +pub struct MockHyp; + +impl MockHyp { + pub fn run_test(t: fn(StartContext)) { + let ctx = unsafe { MaybeUninit::zeroed().assume_init() }; + let lock = SYNC.lock(); + unsafe { + SAMPLING_PORTS.clear(); + QUEUING_PORTS.clear(); + } + t(ctx); + drop(lock); + } +} + +impl ApexSamplingPortP4 for MockHyp { + fn create_sampling_port( + _sampling_port_name: a653rs::bindings::SamplingPortName, + _max_message_size: a653rs::prelude::MessageSize, + _port_direction: a653rs::bindings::PortDirection, + _refresh_period: a653rs::bindings::ApexSystemTime, + ) -> Result { + Ok(0) + } + + fn write_sampling_message( + _sampling_port_id: a653rs::prelude::SamplingPortId, + message: &[a653rs::prelude::ApexByte], + ) -> Result<(), a653rs::bindings::ErrorReturnCode> { + unsafe { SAMPLING_PORTS = message.to_vec() }; + Ok(()) + } + + unsafe fn read_sampling_message( + _sampling_port_id: a653rs::prelude::SamplingPortId, + out: &mut [a653rs::prelude::ApexByte], + ) -> Result< + (a653rs::prelude::Validity, a653rs::prelude::MessageSize), + a653rs::bindings::ErrorReturnCode, + > { + let msg = unsafe { SAMPLING_PORTS.clone() }; + let len = out.len().min(msg.len()); + out[..len].copy_from_slice(&msg.as_slice()[..len]); + + Ok((Validity::Valid, len as u32)) + } +} + +impl ApexQueuingPortP4 for MockHyp { + fn create_queuing_port( + _queuing_port_name: a653rs::bindings::QueuingPortName, + _max_message_size: a653rs::prelude::MessageSize, + _max_nb_message: a653rs::prelude::MessageRange, + _port_direction: a653rs::bindings::PortDirection, + _queuing_discipline: a653rs::prelude::QueuingDiscipline, + ) -> Result { + Ok(0) + } + + fn send_queuing_message( + _queuing_port_id: a653rs::prelude::QueuingPortId, + message: &[a653rs::prelude::ApexByte], + _time_out: a653rs::bindings::ApexSystemTime, + ) -> Result<(), a653rs::bindings::ErrorReturnCode> { + unsafe { QUEUING_PORTS.push(message.to_vec()) }; + Ok(()) + } + + unsafe fn receive_queuing_message( + _queuing_port_id: a653rs::prelude::QueuingPortId, + _time_out: a653rs::bindings::ApexSystemTime, + out: &mut [a653rs::prelude::ApexByte], + ) -> Result< + (a653rs::prelude::MessageSize, a653rs::prelude::QueueOverflow), + a653rs::bindings::ErrorReturnCode, + > { + let msg = unsafe { QUEUING_PORTS.remove(0) }; + let len = out.len().min(msg.len()); + out[..len].copy_from_slice(&msg.as_slice()[..len]); + + Ok((len as u32, false)) + } + + fn get_queuing_port_status( + _queuing_port_id: a653rs::prelude::QueuingPortId, + ) -> Result { + unimplemented!() + } + + fn clear_queuing_port( + _queuing_port_id: a653rs::prelude::QueuingPortId, + ) -> Result<(), a653rs::bindings::ErrorReturnCode> { + unimplemented!() + } +} diff --git a/tests/mock_test.rs b/tests/mock_test.rs new file mode 100644 index 0000000..78a62cf --- /dev/null +++ b/tests/mock_test.rs @@ -0,0 +1,125 @@ +use core::str::FromStr; +use core::time::Duration; + +use a653rs::bindings::QueuingDiscipline; +use a653rs::prelude::{Name, SystemTime}; +use mock::MockHyp; + +mod mock; + +#[test] +fn mock_sampling_port() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_sampling_port_source(Name::from_str("").unwrap(), 4) + .unwrap(); + let dest_port = ctx + .create_sampling_port_destination(Name::from_str("").unwrap(), 4, Duration::ZERO) + .unwrap(); + + let msg = [0, 1, 2, 3]; + let mut buf = [0; 4]; + src_port.send(&msg).unwrap(); + dest_port.receive(&mut buf).unwrap(); + + assert_eq!(msg, buf) + }) +} + +#[test] +fn mock_const_sampling_port() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_const_sampling_port_source::<4>(Name::from_str("").unwrap()) + .unwrap(); + let dest_port = ctx + .create_const_sampling_port_destination::<4>( + Name::from_str("").unwrap(), + Duration::ZERO, + ) + .unwrap(); + + let msg = [0, 1, 2, 3]; + let mut buf = [0; 4]; + src_port.send(&msg).unwrap(); + dest_port.receive(&mut buf).unwrap(); + + assert_eq!(msg, buf) + }) +} + +#[test] +fn mock_queuing_port() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_queuing_port_sender(Name::from_str("").unwrap(), 4, 0, QueuingDiscipline::Fifo) + .unwrap(); + let dest_port = ctx + .create_queuing_port_receiver( + Name::from_str("").unwrap(), + 4, + 0, + QueuingDiscipline::Fifo, + ) + .unwrap(); + + let msg = [0, 1, 2, 3]; + let mut buf = [0; 4]; + src_port.send(&msg, SystemTime::Infinite).unwrap(); + dest_port.receive(&mut buf, SystemTime::Infinite).unwrap(); + + assert_eq!(msg, buf) + }) +} + +#[test] +fn mock_const_queuing_port() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_const_queuing_port_sender::<4, 0>( + Name::from_str("").unwrap(), + QueuingDiscipline::Fifo, + ) + .unwrap(); + let dest_port = ctx + .create_const_queuing_port_receiver::<4, 0>( + Name::from_str("").unwrap(), + QueuingDiscipline::Fifo, + ) + .unwrap(); + + let msg = [0, 1, 2, 3]; + let mut buf = [0; 4]; + src_port.send(&msg, SystemTime::Infinite).unwrap(); + dest_port.receive(&mut buf, SystemTime::Infinite).unwrap(); + + assert_eq!(msg, buf) + }) +} + +#[test] +fn mock_queuing_port_msgs() { + MockHyp::run_test(|mut ctx| { + let src_port = ctx + .create_queuing_port_sender(Name::from_str("").unwrap(), 4, 0, QueuingDiscipline::Fifo) + .unwrap(); + let dest_port = ctx + .create_queuing_port_receiver( + Name::from_str("").unwrap(), + 4, + 0, + QueuingDiscipline::Fifo, + ) + .unwrap(); + + let msg = [0, 1, 2, 3]; + let msg2 = [3, 2, 1, 0]; + let mut buf = [0; 4]; + src_port.send(&msg, SystemTime::Infinite).unwrap(); + src_port.send(&msg2, SystemTime::Infinite).unwrap(); + dest_port.receive(&mut buf, SystemTime::Infinite).unwrap(); + assert_eq!(msg, buf); + dest_port.receive(&mut buf, SystemTime::Infinite).unwrap(); + assert_eq!(msg2, buf) + }) +} From c43b9c4aa21b3e84c14d2b743bdb6bc7c04c3266 Mon Sep 17 00:00:00 2001 From: Sven Friedrich Date: Thu, 13 Jun 2024 14:41:03 +0200 Subject: [PATCH 5/5] docs: add docs --- src/error.rs | 14 +++++++ src/prelude.rs | 2 + src/queuing.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++++ src/sampling.rs | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/mock.rs | 2 + 5 files changed, 217 insertions(+) diff --git a/src/error.rs b/src/error.rs index 3403af8..f034def 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,3 +1,5 @@ +//! Error Types + #[cfg(feature = "alloc")] use alloc::vec::Vec; @@ -10,6 +12,9 @@ use a653rs::prelude::*; #[derive(Debug, Clone)] pub enum QueuingRecvError { Apex(a653rs::prelude::Error), + /// Postcard deserialization error + /// + /// Also returns the data which failed to deserialize Postcard(postcard::Error, Vec), } @@ -23,6 +28,9 @@ impl From for QueuingRecvError { #[derive(Debug, Clone)] pub enum QueuingRecvBufError<'a> { Apex(a653rs::prelude::Error), + /// Postcard deserialization error + /// + /// Also returns the data which failed to deserialize Postcard(postcard::Error, &'a [u8]), } @@ -36,6 +44,9 @@ impl From for QueuingRecvBufError<'_> { #[derive(Debug, Clone)] pub enum SamplingRecvError { Apex(a653rs::prelude::Error), + /// Postcard deserialization error + /// + /// Also returns the data which failed to deserialize and its [`Validity`] Postcard(postcard::Error, Validity, Vec), } @@ -49,6 +60,9 @@ impl From for SamplingRecvError { #[derive(Debug, Clone)] pub enum SamplingRecvBufError<'a> { Apex(a653rs::prelude::Error), + /// Postcard deserialization error + /// + /// Also returns the data which failed to deserialize and its [`Validity`] Postcard(postcard::Error, Validity, &'a [u8]), } diff --git a/src/prelude.rs b/src/prelude.rs index 15e9efa..c8bd2cc 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,3 +1,5 @@ +//! Convenience prelude for simple import + pub use crate::error::*; pub use crate::queuing::*; pub use crate::sampling::*; diff --git a/src/queuing.rs b/src/queuing.rs index 1134804..e54c826 100644 --- a/src/queuing.rs +++ b/src/queuing.rs @@ -1,3 +1,5 @@ +//! Queuing port extension traits + #[cfg(feature = "alloc")] use alloc::vec; @@ -11,23 +13,119 @@ use serde::{Deserialize, Serialize}; use crate::error::*; +/// Postcard extension trait for queuing port sender pub trait QueuingPortSenderExt { + /// Send a type using an a653rs [`QueuingPortSender`] + /// + /// # Example + /// ```rust + /// use a653rs_postcard::prelude::*; + /// # use a653rs::prelude::*; + /// # use std::str::FromStr; + /// # use std::time::Duration; + /// # use mock::MockHyp as Hypervisor; + /// # #[path = "../tests/mock.rs"] + /// # mod mock; + /// # Hypervisor::run_test(|mut ctx| { + /// # let port = ctx + /// # .create_queuing_port_sender(Name::from_str("").unwrap(), 500, 10, QueuingDiscipline::Fifo) + /// # .unwrap(); + /// + /// let port: QueuingPortSender = port; + /// port.send_type(String::from("Typed Data"), SystemTime::Infinite).unwrap(); + /// # }) + /// ``` #[cfg(feature = "alloc")] fn send_type(&self, p: T, timeout: SystemTime) -> Result<(), SendError> where T: Serialize; + /// Send a type using an a653rs [`QueuingPortSender`] + /// + /// Requires a buffer `buf` for serialization. + /// + /// # Example + /// ```rust + /// use a653rs_postcard::prelude::*; + /// # use a653rs::prelude::*; + /// # use std::str::FromStr; + /// # use std::time::Duration; + /// # use mock::MockHyp as Hypervisor; + /// # #[path = "../tests/mock.rs"] + /// # mod mock; + /// # Hypervisor::run_test(|mut ctx| { + /// # let port = ctx + /// # .create_queuing_port_sender(Name::from_str("").unwrap(), 500, 10, QueuingDiscipline::Fifo) + /// # .unwrap(); + /// + /// let port: QueuingPortSender = port; + /// let mut buf = [0; 500]; + /// port.send_type_buf(String::from("Typed Data"), SystemTime::Infinite, &mut buf).unwrap(); + /// # }) + /// ``` fn send_type_buf(&self, p: T, timeout: SystemTime, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize; } +/// Postcard extension trait for queuing ports receiver pub trait QueuingPortReceiverExt { + /// Receive a type using an a653rs [`QueuingPortReceiver`] + /// + /// # Example + /// ```rust + /// use a653rs_postcard::prelude::*; + /// # use a653rs::prelude::*; + /// # use std::str::FromStr; + /// # use std::time::Duration; + /// # use mock::MockHyp as Hypervisor; + /// # #[path = "../tests/mock.rs"] + /// # mod mock; + /// # Hypervisor::run_test(|mut ctx| { + /// # let src_port = ctx + /// # .create_queuing_port_sender(Name::from_str("").unwrap(), 500, 10, QueuingDiscipline::Fifo) + /// # .unwrap(); + /// # let port = ctx + /// # .create_queuing_port_receiver(Name::from_str("").unwrap(), 500, 10, QueuingDiscipline::Fifo) + /// # .unwrap(); + /// + /// let port: QueuingPortReceiver = port; + /// # src_port.send_type(String::default(), SystemTime::Infinite).unwrap(); + /// port.recv_type::(SystemTime::Infinite).unwrap(); + /// # }) + /// ``` #[cfg(feature = "alloc")] fn recv_type(&self, timeout: SystemTime) -> Result<(T, QueueOverflow), QueuingRecvError> where T: for<'a> Deserialize<'a>; + /// Receive a type using an a653rs [`QueuingPortReceiver`] + /// + /// Requires a buffer `buf` for receiving and deserializing the data. + /// + /// # Example + /// ```rust + /// use a653rs_postcard::prelude::*; + /// # use a653rs::prelude::*; + /// # use std::str::FromStr; + /// # use std::time::Duration; + /// # use mock::MockHyp as Hypervisor; + /// # #[path = "../tests/mock.rs"] + /// # mod mock; + /// # Hypervisor::run_test(|mut ctx| { + /// # let src_port = ctx + /// # .create_queuing_port_sender(Name::from_str("").unwrap(), 500, 10, QueuingDiscipline::Fifo) + /// # .unwrap(); + /// # let port = ctx + /// # .create_queuing_port_receiver(Name::from_str("").unwrap(), 500, 10, QueuingDiscipline::Fifo) + /// # .unwrap(); + /// + /// let port: QueuingPortReceiver = port; + /// let mut buf = [0; 500]; + /// # src_port.send_type_buf(String::default(), SystemTime::Infinite, &mut buf).unwrap(); + /// port.recv_type_buf::(SystemTime::Infinite, &mut buf).unwrap(); + /// # }) + /// ``` fn recv_type_buf<'a, T>( &'a self, timeout: SystemTime, diff --git a/src/sampling.rs b/src/sampling.rs index 40a777e..6118d5f 100644 --- a/src/sampling.rs +++ b/src/sampling.rs @@ -1,3 +1,5 @@ +//! Sampling port extension traits + #[cfg(feature = "alloc")] use alloc::vec; @@ -11,23 +13,119 @@ use serde::{Deserialize, Serialize}; use crate::error::*; +/// Postcard extension trait for sampling port sources pub trait SamplingPortSourceExt { + // Send a type using an a653rs [`SamplingPortSource`] + /// + /// # Example + /// ```rust + /// use a653rs_postcard::prelude::*; + /// # use a653rs::prelude::*; + /// # use std::str::FromStr; + /// # use std::time::Duration; + /// # use mock::MockHyp as Hypervisor; + /// # #[path = "../tests/mock.rs"] + /// # mod mock; + /// # Hypervisor::run_test(|mut ctx| { + /// # let port = ctx + /// # .create_sampling_port_source(Name::from_str("").unwrap(), 500) + /// # .unwrap(); + /// + /// let port: SamplingPortSource = port; + /// port.send_type(String::from("Typed Data")).unwrap(); + /// # }) + /// ``` #[cfg(feature = "alloc")] fn send_type(&self, p: T) -> Result<(), SendError> where T: Serialize; + // Send a type using an a653rs [`SamplingPortSource`] + /// + /// Requires a buffer `buf` for serialization. + /// + /// # Example + /// ```rust + /// use a653rs_postcard::prelude::*; + /// # use a653rs::prelude::*; + /// # use std::str::FromStr; + /// # use std::time::Duration; + /// # use mock::MockHyp as Hypervisor; + /// # #[path = "../tests/mock.rs"] + /// # mod mock; + /// # Hypervisor::run_test(|mut ctx| { + /// # let port = ctx + /// # .create_sampling_port_source(Name::from_str("").unwrap(), 500) + /// # .unwrap(); + /// + /// let port: SamplingPortSource = port; + /// let mut buf = [0; 500]; + /// port.send_type_buf(String::from("Typed Data"), &mut buf).unwrap(); + /// # }) + /// ``` fn send_type_buf(&self, p: T, buf: &mut [u8]) -> Result<(), SendError> where T: Serialize; } +/// Postcard extension trait for sampling port destinations pub trait SamplingPortDestinationExt { + /// Receive a type using an a653rs [`SamplingPortDestination`] + /// + /// # Example + /// ```rust + /// use a653rs_postcard::prelude::*; + /// # use a653rs::prelude::*; + /// # use std::str::FromStr; + /// # use std::time::Duration; + /// # use mock::MockHyp as Hypervisor; + /// # #[path = "../tests/mock.rs"] + /// # mod mock; + /// # Hypervisor::run_test(|mut ctx| { + /// # let src_port = ctx + /// # .create_sampling_port_source(Name::from_str("").unwrap(), 500) + /// # .unwrap(); + /// # let port = ctx + /// # .create_sampling_port_destination(Name::from_str("Port").unwrap(), 500, Duration::ZERO) + /// # .unwrap(); + /// + /// let port: SamplingPortDestination = port; + /// # src_port.send_type(String::default()).unwrap(); + /// let (validity, received_type) = port.recv_type::().unwrap(); + /// # }) + /// ``` #[cfg(feature = "alloc")] fn recv_type(&self) -> Result<(Validity, T), SamplingRecvError> where T: for<'a> Deserialize<'a>; + /// Receive a type using an a653rs [`SamplingPortDestination`] + /// + /// Requires a buffer `buf` for receiving and deserializing the data. + /// + /// # Example + /// ```rust + /// use a653rs_postcard::prelude::*; + /// # use a653rs::prelude::*; + /// # use std::str::FromStr; + /// # use std::time::Duration; + /// # use mock::MockHyp as Hypervisor; + /// # #[path = "../tests/mock.rs"] + /// # mod mock; + /// # Hypervisor::run_test(|mut ctx| { + /// # let src_port = ctx + /// # .create_sampling_port_source(Name::from_str("").unwrap(), 500) + /// # .unwrap(); + /// # let port = ctx + /// # .create_sampling_port_destination(Name::from_str("Port").unwrap(), 500, Duration::ZERO) + /// # .unwrap(); + /// + /// let port: SamplingPortDestination = port; + /// let mut buf = [0; 500]; + /// # src_port.send_type_buf(String::default(), &mut buf).unwrap(); + /// let (validity, received_type) = port.recv_type_buf::(&mut buf).unwrap(); + /// # }) + /// ``` fn recv_type_buf<'a, T>( &self, buf: &'a mut [u8], @@ -37,6 +135,9 @@ pub trait SamplingPortDestinationExt { } impl SamplingPortSourceExt for SamplingPortSource { + /// Receive a type using an a653rs [`SamplingPortDestination`] + /// + /// Requires a buffer `buf` for receiving and deserializing the data. #[cfg(feature = "alloc")] fn send_type(&self, p: T) -> Result<(), SendError> where diff --git a/tests/mock.rs b/tests/mock.rs index 14a2818..fc46211 100644 --- a/tests/mock.rs +++ b/tests/mock.rs @@ -14,6 +14,8 @@ static SYNC: Mutex<()> = Mutex::new(()); pub struct MockHyp; impl MockHyp { + /// Prevents multiple tests from running concurrently + /// Also clears all ports before starting with the next one pub fn run_test(t: fn(StartContext)) { let ctx = unsafe { MaybeUninit::zeroed().assume_init() }; let lock = SYNC.lock();