From db09289cf1e95335cae7112153b545a899f314a7 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Tue, 16 Jan 2024 09:49:37 -0800 Subject: [PATCH 1/3] chore: factor out bbq into its own crate --- Cargo.lock | 15 +++++++ source/bbq/Cargo.toml | 27 ++++++++++++ .../src/comms/bbq.rs => bbq/src/lib.rs} | 41 +++++++++++++------ source/forth3/src/lib.rs | 10 +++++ source/kernel/Cargo.toml | 4 ++ source/kernel/src/comms/mod.rs | 2 +- source/kernel/src/fmt.rs | 15 ------- source/kernel/src/forth/mod.rs | 3 +- source/kernel/src/lib.rs | 1 - 9 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 source/bbq/Cargo.toml rename source/{kernel/src/comms/bbq.rs => bbq/src/lib.rs} (91%) delete mode 100644 source/kernel/src/fmt.rs diff --git a/Cargo.lock b/Cargo.lock index 5fe88a4a..da47841e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5035,6 +5035,7 @@ dependencies = [ "maitake", "mnemos-abi", "mnemos-alloc", + "mnemos-bbq", "mnemos-trace-proto", "mycelium-bitfield 0.1.3 (git+https://github.com/hawkw/mycelium.git?rev=101a4abaa19afdd131b334a16d92c9fb4909c064)", "mycelium-util 0.1.0 (git+https://github.com/hawkw/mycelium.git?rev=101a4abaa19afdd131b334a16d92c9fb4909c064)", @@ -5073,6 +5074,16 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "mnemos-bbq" +version = "0.1.0" +dependencies = [ + "maitake", + "mnemos-abi", + "mnemos-alloc", + "tracing 0.1.37", +] + [[package]] name = "mnemos-beepy" version = "0.1.0" @@ -7520,6 +7531,10 @@ dependencies = [ "typenum", ] +[[package]] +name = "skippy" +version = "0.1.0" + [[package]] name = "slab" version = "0.4.8" diff --git a/source/bbq/Cargo.toml b/source/bbq/Cargo.toml new file mode 100644 index 00000000..2a176ed2 --- /dev/null +++ b/source/bbq/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "mnemos-bbq" +version = "0.1.0" +edition.workspace = true +repository.workspace = true +homepage.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies.mnemos-abi] +version = "0.1.0" +path = "../abi" + +[dependencies.maitake] +version = "0.1.0" +default-features = false +features = ["alloc"] + +[dependencies.mnemos-alloc] +version = "0.1.0" +path = "../alloc" + +[dependencies.tracing] +version = "0.1.35" +features = ["attributes"] +default-features = false diff --git a/source/kernel/src/comms/bbq.rs b/source/bbq/src/lib.rs similarity index 91% rename from source/kernel/src/comms/bbq.rs rename to source/bbq/src/lib.rs index d3124497..5de0295e 100644 --- a/source/kernel/src/comms/bbq.rs +++ b/source/bbq/src/lib.rs @@ -4,9 +4,12 @@ //! This extends the underlying bbqueue type exposed by the ABI crate, allowing //! for async kernel-to-kernel (including driver services) usage. -use core::ops::{Deref, DerefMut}; +#![no_std] +use core::{ + fmt, + ops::{Deref, DerefMut}, +}; -use crate::fmt; use abi::bbqueue_ipc::{BBBuffer, Consumer as InnerConsumer, Producer as InnerProducer}; use abi::bbqueue_ipc::{GrantR as InnerGrantR, GrantW as InnerGrantW}; use maitake::sync::Mutex; @@ -251,7 +254,7 @@ impl MpscProducer { name = "MpscProducer::send_grant_max", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub async fn send_grant_max(&self, max: usize) -> GrantW { let producer = self.storage.producer.lock().await; @@ -263,7 +266,7 @@ impl MpscProducer { name = "MpscProducer::send_grant_exact", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub async fn send_grant_exact(&self, size: usize) -> GrantW { let producer = self.storage.producer.lock().await; @@ -277,7 +280,7 @@ impl SpscProducer { name = "SpscProducer::send_grant_max", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub async fn send_grant_max(&self, max: usize) -> GrantW { producer_send_grant_max(max, &self.producer, &self.storage).await @@ -287,7 +290,7 @@ impl SpscProducer { name = "SpscProducer::send_grant_exact", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub async fn send_grant_exact(&self, size: usize) -> GrantW { producer_send_grant_exact(size, &self.producer, &self.storage).await @@ -299,7 +302,7 @@ impl Consumer { name = "Consumer::read_grant", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub async fn read_grant(&self) -> GrantR { loop { @@ -330,7 +333,7 @@ impl SpscProducer { name = "SpscProducer::send_grant_exact_sync", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub fn send_grant_exact_sync(&self, size: usize) -> Option { self.producer.grant_exact(size).ok().map(|wgr| GrantW { @@ -343,7 +346,7 @@ impl SpscProducer { name = "SpscProducer::send_grant_max_sync", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub fn send_grant_max_sync(&self, max: usize) -> Option { self.producer @@ -361,7 +364,7 @@ impl MpscProducer { name = "MpscProducer::send_grant_exact_sync", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub fn send_grant_exact_sync(&self, size: usize) -> Option { let producer = self.storage.producer.try_lock()?; @@ -376,7 +379,7 @@ impl MpscProducer { name = "MpscProducer::send_grant_max_sync", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub fn send_grant_max_sync(&self, max: usize) -> Option { let producer = self.storage.producer.try_lock()?; @@ -393,7 +396,7 @@ impl Consumer { name = "Consumer::read_grant_sync", level = "trace", skip(self), - fields(queue = ?fmt::ptr(self.storage.deref())), + fields(queue = ?fmt_ptr(self.storage.deref())), )] pub fn read_grant_sync(&self) -> Option { self.consumer.read().ok().map(|rgr| GrantR { @@ -402,3 +405,17 @@ impl Consumer { }) } } + +#[inline] +fn fmt_ptr(ptr: P) -> DebugPtr

{ + DebugPtr(ptr) +} + +#[derive(Copy, Clone)] +pub(crate) struct DebugPtr(P); + +impl fmt::Debug for DebugPtr

{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:p}", self.0) + } +} diff --git a/source/forth3/src/lib.rs b/source/forth3/src/lib.rs index b00d34fb..5ad2821b 100644 --- a/source/forth3/src/lib.rs +++ b/source/forth3/src/lib.rs @@ -287,6 +287,16 @@ pub mod test { assert_send::>(); } + #[test] + fn builtins() { + all_runtest( + r#" + > builtins + < + "#, + ); + } + #[test] fn forth() { let mut lbforth = LBForth::from_params( diff --git a/source/kernel/Cargo.toml b/source/kernel/Cargo.toml index 239b9881..397933f6 100644 --- a/source/kernel/Cargo.toml +++ b/source/kernel/Cargo.toml @@ -92,6 +92,10 @@ version = "0.7.10" version = "0.1.0" path = "../abi" +[dependencies.mnemos-bbq] +version = "0.1.0" +path = "../bbq" + [dependencies.serde] version = "1.0.136" default-features = false diff --git a/source/kernel/src/comms/mod.rs b/source/kernel/src/comms/mod.rs index e38cfe84..10e73108 100644 --- a/source/kernel/src/comms/mod.rs +++ b/source/kernel/src/comms/mod.rs @@ -1,5 +1,5 @@ //! Kernel Communications Interfaces -pub mod bbq; +pub use mnemos_bbq as bbq; pub mod kchannel; pub mod oneshot; diff --git a/source/kernel/src/fmt.rs b/source/kernel/src/fmt.rs deleted file mode 100644 index 429a011a..00000000 --- a/source/kernel/src/fmt.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub(crate) use core::fmt::*; - -#[inline] -pub(crate) fn ptr(ptr: P) -> DebugPtr

{ - DebugPtr(ptr) -} - -#[derive(Copy, Clone)] -pub(crate) struct DebugPtr(P); - -impl Debug for DebugPtr

{ - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - write!(f, "{:p}", self.0) - } -} diff --git a/source/kernel/src/forth/mod.rs b/source/kernel/src/forth/mod.rs index 319c192d..d1263832 100644 --- a/source/kernel/src/forth/mod.rs +++ b/source/kernel/src/forth/mod.rs @@ -149,10 +149,11 @@ impl Forth { .input_mut() .fill(input) .expect("eliza: why would this fail?"); - read.release(len); } Err(_e) => todo!("eliza: what to do if the input is not utf8?"), }; + + read.release(len); } } } diff --git a/source/kernel/src/lib.rs b/source/kernel/src/lib.rs index 3ef5aa79..6f37026c 100644 --- a/source/kernel/src/lib.rs +++ b/source/kernel/src/lib.rs @@ -76,7 +76,6 @@ extern crate alloc; pub mod comms; pub mod daemons; -pub(crate) mod fmt; pub mod forth; pub mod isr; pub mod registry; From 5e224c67fb58f517021b77ceffbac6e17cbe1f56 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Tue, 16 Jan 2024 11:17:55 -0800 Subject: [PATCH 2/3] chore: update nightly to 2024-01-15 Now we can use `async fn` in traits. --- flake.lock | 18 +++++++++--------- flake.nix | 3 ++- rust-toolchain.toml | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/flake.lock b/flake.lock index a24bfd75..45831970 100644 --- a/flake.lock +++ b/flake.lock @@ -27,11 +27,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1692799911, - "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", "owner": "numtide", "repo": "flake-utils", - "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", "type": "github" }, "original": { @@ -60,11 +60,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1692734709, - "narHash": "sha256-SCFnyHCyYjwEmgUsHDDuU0TsbVMKeU1vwkR+r7uS2Rg=", + "lastModified": 1705133751, + "narHash": "sha256-rCIsyE80jgiOU78gCWN3A0wE0tR2GI5nH6MlS+HaaSQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b85ed9dcbf187b909ef7964774f8847d554fab3b", + "rev": "9b19f5e77dd906cb52dade0b7bd280339d2a1f3d", "type": "github" }, "original": { @@ -132,11 +132,11 @@ ] }, "locked": { - "lastModified": 1693015707, - "narHash": "sha256-SFr93DYn502sVT9nB5U8/cKg1INyEk/jCeq8tHioz7Y=", + "lastModified": 1705371439, + "narHash": "sha256-P1kulUXpYWkcrjiX3sV4j8ACJZh9XXSaaD+jDLBDLKo=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "e90223633068a44f0fb62374e0fa360ccc987292", + "rev": "b21f3c0d5bf0f0179f5f0140e8e0cd099618bd04", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index e3fa4e9a..bbc2492e 100644 --- a/flake.nix +++ b/flake.nix @@ -35,7 +35,8 @@ # use the Rust toolchain specified in the project's rust-toolchain.toml rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; - in { + in + { devShell = with pkgs; mkShell rec { name = "mnemos-dev"; diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 74ee909f..740411cc 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "nightly-2023-08-08" +channel = "nightly-2024-01-15" profile = "minimal" components = [ "clippy", From 1194a8ed277399ca26db449f94c5829c8124ba6a Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Tue, 16 Jan 2024 11:19:14 -0800 Subject: [PATCH 3/3] feat(bbq): add `async fn write_fmt` to bbq --- Cargo.lock | 30 +++--- source/bbq/Cargo.toml | 3 + source/bbq/src/async_fmt.rs | 180 ++++++++++++++++++++++++++++++++++++ source/bbq/src/lib.rs | 34 ++++++- 4 files changed, 229 insertions(+), 18 deletions(-) create mode 100644 source/bbq/src/async_fmt.rs diff --git a/Cargo.lock b/Cargo.lock index da47841e..87ea1290 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4316,7 +4316,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.3", + "socket2 0.5.5", "widestring", "windows-sys 0.48.0", "winreg", @@ -4513,9 +4513,9 @@ checksum = "441225017b106b9f902e97947a6d31e44ebcf274b91bdbfb51e5c477fcd468e5" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libgit2-sys" @@ -5002,9 +5002,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", @@ -5081,6 +5081,7 @@ dependencies = [ "maitake", "mnemos-abi", "mnemos-alloc", + "tokio", "tracing 0.1.37", ] @@ -7531,10 +7532,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "skippy" -version = "0.1.0" - [[package]] name = "slab" version = "0.4.8" @@ -7605,9 +7602,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -8081,11 +8078,10 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ - "autocfg 1.1.0", "backtrace", "bytes", "libc", @@ -8094,7 +8090,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.4.9", + "socket2 0.5.5", "tokio-macros", "tracing 0.1.37", "windows-sys 0.48.0", @@ -8112,9 +8108,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", diff --git a/source/bbq/Cargo.toml b/source/bbq/Cargo.toml index 2a176ed2..aa184c57 100644 --- a/source/bbq/Cargo.toml +++ b/source/bbq/Cargo.toml @@ -25,3 +25,6 @@ path = "../alloc" version = "0.1.35" features = ["attributes"] default-features = false + +[dev-dependencies] +tokio = { version = "1.35", features = ["rt", "macros", "time"] } diff --git a/source/bbq/src/async_fmt.rs b/source/bbq/src/async_fmt.rs new file mode 100644 index 00000000..2e9582c0 --- /dev/null +++ b/source/bbq/src/async_fmt.rs @@ -0,0 +1,180 @@ +use super::{BidiHandle, GrantW, MpscProducer, SpscProducer}; +use core::fmt::{self, Write}; + +// TODO(eliza): should this be a public API? +pub(crate) trait Producer { + async fn send_grant(&self, max: usize) -> GrantW; +} + +impl Producer for MpscProducer { + async fn send_grant(&self, max: usize) -> GrantW { + self.send_grant_max(max).await + } +} + +impl Producer for SpscProducer { + async fn send_grant(&self, max: usize) -> GrantW { + self.send_grant_max(max).await + } +} + +impl Producer for BidiHandle { + async fn send_grant(&self, max: usize) -> GrantW { + self.producer().send_grant_max(max).await + } +} + +pub(crate) async fn fmt_to_bbq(producer: &impl Producer, fmt: impl fmt::Debug) { + struct ByteCtr { + cnt: usize, + } + + impl fmt::Write for ByteCtr { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.cnt += s.as_bytes().len(); + Ok(()) + } + } + + struct WriteWgr<'a> { + skip: usize, + written: usize, + buf: &'a mut [u8], + } + + impl fmt::Write for WriteWgr<'_> { + fn write_str(&mut self, s: &str) -> fmt::Result { + let mut bytes = test_dbg!(s).as_bytes(); + let rem_skip = test_dbg!(self.skip).saturating_sub(test_dbg!(self.written)); + if test_dbg!(rem_skip) > 0 { + let len = test_dbg!(bytes.len()); + bytes = if len > rem_skip { + self.written += rem_skip; + &bytes[rem_skip..] + } else { + self.written += len; + &[] + }; + } + + if !test_dbg!(bytes.is_empty()) { + let rem_write = self.written - self.skip; + let buf = &mut self.buf[test_dbg!(rem_write)..]; + let buflen = buf.len(); + if buflen == 0 { + // bail + return Err(fmt::Error); + } + let wrlen = core::cmp::min(buflen, bytes.len()); + buf[..wrlen].copy_from_slice(&bytes[..wrlen]); + self.written += wrlen; + } + + Ok(()) + } + } + + let mut cnt = ByteCtr { cnt: 0 }; + write!(cnt, "{fmt:?}").expect("writing to byte counter should never fail"); + let total_len = cnt.cnt; + let mut written = 0; + + while written < total_len { + let rem = total_len - written; + let mut wgr = producer.send_grant(test_dbg!(rem)).await; + let written_now = { + let mut writer = WriteWgr { + skip: written, + written: 0, + buf: &mut wgr[..], + }; + let _ = write!(&mut writer, "{fmt:?}"); + test_dbg!(writer.written) - test_dbg!(writer.skip) + }; + written += test_dbg!(written_now); + + wgr.commit(written_now); + } +} + +#[cfg(test)] +mod tests { + use super::*; + const STR: &str = "\ + There was a man named Mord whose surname was Fiddle; he was the \ + son of Sigvat the Red, and he dwelt at the \"Vale\" in the \ + Rangrivervales. He was a mighty chief, and a great taker up of \ + suits, and so great a lawyer that no judgments were thought \ + lawful unless he had a hand in them. He had an only daughter, \ + named Unna. She was a fair, courteous and gifted woman, \ + and that was thought the best match in all the Rangrivervales.\ + "; + #[tokio::test] + async fn it_works() { + let (tx, rx) = crate::new_spsc_channel(16).await; + let writer = tokio::spawn(async move { + fmt_to_bbq(&tx, &STR).await; + }); + + let reader = tokio::spawn(async move { + let len = STR.as_bytes().len(); + let recvd = recv(rx, len).await; + assert_eq!(recvd, format!("{STR:?}")); + }); + + tokio::time::timeout(tokio::time::Duration::from_secs(60), async move { + tokio::try_join!(reader, writer).expect("neither task should panic") + }) + .await + .expect("reader and writer should complete within 60 seconds"); + } + + #[tokio::test] + async fn debug_also_works() { + #[derive(Debug)] + #[allow(dead_code)] + struct MyCoolStruct<'a> { + a: &'a str, + my_vec: Vec<&'a str>, + c: &'a str, + } + + let my_struct = MyCoolStruct { + a: "hello world", + my_vec: STR.split('.').collect(), + c: "goodbye world", + }; + + let output = format!("{my_struct:?}"); + + let (tx, rx) = crate::new_spsc_channel(16).await; + let writer = tokio::spawn(async move { + fmt_to_bbq(&tx, my_struct).await; + }); + + let reader = tokio::spawn(async move { + let len = output.as_bytes().len(); + let recvd = recv(rx, len).await; + assert_eq!(recvd, output); + }); + + tokio::time::timeout(tokio::time::Duration::from_secs(60), async move { + tokio::try_join!(reader, writer).expect("neither task should panic") + }) + .await + .expect("reader and writer should complete within 60 seconds"); + } + + async fn recv(rx: crate::Consumer, len: usize) -> String { + let mut buf = String::with_capacity(len); + while buf.len() < len { + let rgr = rx.read_grant().await; + let len = rgr.len(); + let recv = std::str::from_utf8(&rgr[..len]).expect("must be UTF8"); + println!("recv: {recv:?}"); + buf.push_str(recv); + rgr.release(len); + } + buf + } +} diff --git a/source/bbq/src/lib.rs b/source/bbq/src/lib.rs index 5de0295e..92e8abb2 100644 --- a/source/bbq/src/lib.rs +++ b/source/bbq/src/lib.rs @@ -4,12 +4,29 @@ //! This extends the underlying bbqueue type exposed by the ABI crate, allowing //! for async kernel-to-kernel (including driver services) usage. -#![no_std] +#![cfg_attr(not(test), no_std)] + +#[cfg(not(test))] +macro_rules! test_dbg { + ($e:expr) => { + $e + }; +} + +#[cfg(test)] +macro_rules! test_dbg { + ($e:expr) => { + std::dbg!($e) + }; +} + use core::{ fmt, ops::{Deref, DerefMut}, }; +mod async_fmt; + use abi::bbqueue_ipc::{BBBuffer, Consumer as InnerConsumer, Producer as InnerProducer}; use abi::bbqueue_ipc::{GrantR as InnerGrantR, GrantW as InnerGrantW}; use maitake::sync::Mutex; @@ -45,6 +62,11 @@ impl BidiHandle { pub fn split(self) -> (SpscProducer, Consumer) { (self.producer, self.consumer) } + + pub async fn write_fmt(&self, fmt: impl fmt::Debug) -> fmt::Result { + async_fmt::fmt_to_bbq(self, fmt).await; + Ok(()) + } } pub async fn new_bidi_channel(capacity_a: usize, capacity_b: usize) -> (BidiHandle, BidiHandle) { @@ -273,6 +295,11 @@ impl MpscProducer { let producer = producer.as_ref().unwrap(); producer_send_grant_exact(size, producer, &self.storage).await } + + pub async fn write_fmt(&self, fmt: impl fmt::Debug) -> fmt::Result { + async_fmt::fmt_to_bbq(self, fmt).await; + Ok(()) + } } impl SpscProducer { @@ -295,6 +322,11 @@ impl SpscProducer { pub async fn send_grant_exact(&self, size: usize) -> GrantW { producer_send_grant_exact(size, &self.producer, &self.storage).await } + + pub async fn write_fmt(&self, fmt: impl fmt::Debug) -> fmt::Result { + async_fmt::fmt_to_bbq(self, fmt).await; + Ok(()) + } } impl Consumer {