Skip to content

Commit a18c91e

Browse files
authored
Merge pull request #5 from JadKHaddad/feat/echo
Exposed internal functions and fields
2 parents d1bc9e7 + 1a9d54d commit a18c91e

File tree

11 files changed

+472
-298
lines changed

11 files changed

+472
-298
lines changed

framez/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
3737
all-features = true
3838
rustdoc-args = ["--cfg", "docsrs"]
3939

40+
[[example]]
41+
name = "echo"
42+
path = "examples/echo.rs"
43+
required-features = []
44+
4045
[[example]]
4146
name = "zerocopy"
4247
path = "examples/zerocopy.rs"

framez/examples/echo.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//! This example shows how to reuse the read and write buffers without splitting the `Framed` instance.
2+
//!
3+
//! ```not_rust
4+
//! cargo run --example echo
5+
//! ```
6+
7+
use core::error::Error;
8+
9+
use embedded_io_adapters::tokio_1::FromTokio;
10+
use framez::{Framed, codec::lines::StrLines, next, send};
11+
12+
#[tokio::main]
13+
async fn main() -> Result<(), Box<dyn Error>> {
14+
tracing_subscriber::fmt()
15+
.with_env_filter("server=info,client=info")
16+
.init();
17+
18+
let (server, client) = tokio::io::duplex(16);
19+
20+
let read_buf = &mut [0u8; 1024];
21+
let write_buf = &mut [0u8; 1024];
22+
let mut server = Framed::new(StrLines::new(), FromTokio::new(server), read_buf, write_buf);
23+
24+
let server = async move {
25+
while let Some(item) = next!(server).transpose()? {
26+
tracing::info!(target: "server", item, "received frame");
27+
28+
// echo the item back
29+
send!(server, item)?;
30+
31+
if item == "Close" {
32+
tracing::info!(target: "server", "closing connection");
33+
34+
break;
35+
}
36+
}
37+
38+
Ok::<(), Box<dyn Error>>(())
39+
};
40+
41+
let read_buf = &mut [0u8; 1024];
42+
let write_buf = &mut [0u8; 1024];
43+
let mut client = Framed::new(StrLines::new(), FromTokio::new(client), read_buf, write_buf);
44+
45+
let client = async move {
46+
let items = ["Hello, world!", "How are you?", "Goodbye!", "Close"];
47+
48+
for item in items {
49+
tracing::info!(target: "client", item, "sending frame");
50+
51+
client.send(item).await?;
52+
}
53+
54+
while let Some(item) = next!(client).transpose()? {
55+
tracing::info!(target: "client", item, "received frame");
56+
}
57+
58+
Ok::<(), Box<dyn Error>>(())
59+
};
60+
61+
let (server_result, client_result) = tokio::join!(server, client);
62+
63+
server_result?;
64+
client_result?;
65+
66+
Ok(())
67+
}

framez/src/framed.rs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ use crate::{
1313
#[derive(Debug)]
1414
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1515
pub struct Framed<'buf, C, RW> {
16-
core: FramedCore<'buf, C, RW, ReadWriteState<'buf>>,
16+
/// The core framed implementation.
17+
///
18+
/// This field is made public to be used in the [`functions`](crate::functions) module for library authors.
19+
/// If you are using this crate as a user, you should probably not care about this field.
20+
pub core: FramedCore<'buf, C, RW>,
1721
}
1822

1923
impl<'buf, C, RW> Framed<'buf, C, RW> {
20-
/// Creates a new [`Framed`] with the given `coded` and `reader/writer`.
24+
/// Creates a new [`Framed`] with the given `codec` and `reader/writer`.
2125
#[inline]
2226
pub const fn new(
2327
codec: C,
@@ -74,7 +78,7 @@ impl<'buf, C, RW> Framed<'buf, C, RW> {
7478

7579
/// Returns the number of bytes that can be framed.
7680
#[inline]
77-
pub fn framable(&self) -> usize {
81+
pub const fn framable(&self) -> usize {
7882
self.core.framable()
7983
}
8084

@@ -208,15 +212,23 @@ impl<'buf, C, RW> Framed<'buf, C, RW> {
208212
#[derive(Debug)]
209213
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
210214
pub struct FramedRead<'buf, C, R> {
211-
core: FramedCore<'buf, C, R, ReadState<'buf>>,
215+
/// The core framed implementation.
216+
///
217+
/// This field is made public to be used in the [`functions`](crate::functions) module for library authors.
218+
/// If you are using this crate as a user, you should probably not care about this field.
219+
pub core: FramedCore<'buf, C, R>,
212220
}
213221

214222
impl<'buf, C, R> FramedRead<'buf, C, R> {
215223
/// Creates a new [`FramedRead`] with the given `decoder` and `reader`.
216224
#[inline]
217225
pub const fn new(codec: C, reader: R, buffer: &'buf mut [u8]) -> Self {
218226
Self {
219-
core: FramedCore::new(codec, reader, ReadState::new(buffer)),
227+
core: FramedCore::new(
228+
codec,
229+
reader,
230+
ReadWriteState::new(ReadState::new(buffer), WriteState::empty()),
231+
),
220232
}
221233
}
222234

@@ -247,17 +259,29 @@ impl<'buf, C, R> FramedRead<'buf, C, R> {
247259
/// Consumes the [`FramedRead`] and returns the `codec` and `reader` and state.
248260
#[inline]
249261
pub fn into_parts(self) -> (C, R, ReadState<'buf>) {
250-
self.core.into_parts()
262+
let (codec, reader, state) = self.core.into_parts();
263+
264+
(codec, reader, state.read)
251265
}
252266

253267
#[inline]
254268
/// Creates a new [`FramedRead`] from its parts.
255269
pub const fn from_parts(codec: C, read: R, state: ReadState<'buf>) -> Self {
256270
Self {
257-
core: FramedCore::from_parts(codec, read, state),
271+
core: FramedCore::from_parts(
272+
codec,
273+
read,
274+
ReadWriteState::new(state, WriteState::empty()),
275+
),
258276
}
259277
}
260278

279+
/// Returns the number of bytes that can be framed.
280+
#[inline]
281+
pub const fn framable(&self) -> usize {
282+
self.core.framable()
283+
}
284+
261285
/// See [`Framed::maybe_next`].
262286
pub async fn maybe_next<'this>(
263287
&'this mut self,
@@ -300,15 +324,23 @@ impl<'buf, C, R> FramedRead<'buf, C, R> {
300324
#[derive(Debug)]
301325
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
302326
pub struct FramedWrite<'buf, C, W> {
303-
core: FramedCore<'buf, C, W, WriteState<'buf>>,
327+
/// The core framed implementation.
328+
///
329+
/// This field is made public to be used in the [`functions`](crate::functions) module for library authors.
330+
/// If you are using this crate as a user, you should probably not care about this field.
331+
pub core: FramedCore<'buf, C, W>,
304332
}
305333

306334
impl<'buf, C, W> FramedWrite<'buf, C, W> {
307335
/// Creates a new [`FramedWrite`] with the given `encoder` and `writer`.
308336
#[inline]
309337
pub const fn new(codec: C, writer: W, buffer: &'buf mut [u8]) -> Self {
310338
Self {
311-
core: FramedCore::new(codec, writer, WriteState::new(buffer)),
339+
core: FramedCore::new(
340+
codec,
341+
writer,
342+
ReadWriteState::new(ReadState::empty(), WriteState::new(buffer)),
343+
),
312344
}
313345
}
314346

@@ -339,14 +371,20 @@ impl<'buf, C, W> FramedWrite<'buf, C, W> {
339371
/// Consumes the [`FramedWrite`] and returns the `codec` and `writer` and state.
340372
#[inline]
341373
pub fn into_parts(self) -> (C, W, WriteState<'buf>) {
342-
self.core.into_parts()
374+
let (codec, writer, state) = self.core.into_parts();
375+
376+
(codec, writer, state.write)
343377
}
344378

345379
#[inline]
346380
/// Creates a new [`FramedWrite`] from its parts.
347381
pub const fn from_parts(codec: C, write: W, state: WriteState<'buf>) -> Self {
348382
Self {
349-
core: FramedCore::from_parts(codec, write, state),
383+
core: FramedCore::from_parts(
384+
codec,
385+
write,
386+
ReadWriteState::new(ReadState::empty(), state),
387+
),
350388
}
351389
}
352390

0 commit comments

Comments
 (0)