Skip to content

Commit

Permalink
refactor: extract config to separate structs
Browse files Browse the repository at this point in the history
  • Loading branch information
threadexio committed Mar 26, 2024
1 parent d77c4e3 commit 327f386
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 52 deletions.
14 changes: 2 additions & 12 deletions channels/src/protocol.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use core::num::NonZeroUsize;

use channels_packet::{
Flags, Header, IdGenerator, PacketLength, PayloadLength,
};
Expand All @@ -8,18 +6,10 @@ use crate::error::VerifyError;
use crate::io::{
AsyncRead, AsyncWrite, Buf, Contiguous, Cursor, Read, Write,
};
use crate::receiver::Config as RecvConfig;
use crate::sender::Config as SendConfig;
use crate::util::StatIO;

#[derive(Clone)]
pub struct SendConfig {
pub flush_on_send: bool,
}

#[derive(Clone)]
pub struct RecvConfig {
pub size_estimate: Option<NonZeroUsize>,
}

#[derive(Clone)]
pub struct Pcb {
id_gen: IdGenerator,
Expand Down
83 changes: 60 additions & 23 deletions channels/src/receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use core::num::NonZeroUsize;

use crate::error::RecvError;
use crate::io::{AsyncRead, IntoReader, Read, Reader};
use crate::protocol::{Pcb, RecvConfig};
use crate::protocol::Pcb;
use crate::serdes::Deserializer;
use crate::util::StatIO;

Expand All @@ -19,7 +19,7 @@ pub struct Receiver<T, R, D> {
reader: StatIO<R>,
deserializer: D,
pcb: Pcb,
config: RecvConfig,
config: Config,
}

impl<T> Receiver<T, (), ()> {
Expand Down Expand Up @@ -327,7 +327,7 @@ pub struct Builder<T, R, D> {
_marker: PhantomData<T>,
reader: R,
deserializer: D,
config: RecvConfig,
config: Option<Config>,
}

impl<T> Builder<T, (), ()> {
Expand All @@ -350,7 +350,7 @@ impl<T> Builder<T, (), ()> {
_marker: PhantomData,
reader: (),
deserializer: (),
config: RecvConfig { size_estimate: None },
config: None,
}
}
}
Expand Down Expand Up @@ -419,20 +419,24 @@ impl<T, R> Builder<T, R, ()> {
}

impl<T, R, D> Builder<T, R, D> {
/// Set the expected size for each received type.
/// Set the [`Config`] for this receiver.
///
/// This options exists purely to avoid reallocations when receiving types
/// that span multiple packets.
/// # Example
///
/// ```no_run
/// use core::num::NonZeroUsize;
///
/// # Panics
/// use channels::receiver::{Config, Receiver};
///
/// If `size_estimate` is 0.
/// let config = Config::default()
/// .size_estimate(NonZeroUsize::new(42).unwrap());
///
/// let rx = Receiver::<i32, _, _>::builder()
/// .config(config);
/// ```
#[must_use]
pub fn size_estimate(mut self, size_estimate: usize) -> Self {
self.config.size_estimate = Some(
NonZeroUsize::new(size_estimate)
.expect("size_estimate cannot be zero"),
);
pub fn config(mut self, config: Config) -> Self {
self.config = Some(config);
self
}

Expand All @@ -452,20 +456,53 @@ impl<T, R, D> Builder<T, R, D> {
reader: StatIO::new(self.reader),
deserializer: self.deserializer,
pcb: Pcb::new(),
config: self.config,
config: self.config.unwrap_or_default(),
}
}
}

impl fmt::Debug for RecvConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut debug = f.debug_struct("Config");
/// Configuration for [`Receiver`].
///
/// [`Receiver`]: crate::Receiver
#[derive(Clone, Default)]
pub struct Config {
pub(crate) size_estimate: Option<NonZeroUsize>,
}

if let Some(x) = self.size_estimate {
debug.field("size_estimate", &x.get());
}
impl Config {
/// Size estimate for incoming data.
///
/// Inform the receiving code to preallocate a buffer of this size when
/// receiving. Setting this field correctly can help avoid reallocations
/// when receiving data that is split up into multiple packets. For most
/// cases, when data fits inside a single packet, this field has _no_ effect
/// and can simply be left as the default.
///
/// When setting this field, if you don't know the exact size of your data,
/// it is best to overestimate it. Setting a value even one byte less than
/// what the actual size of the data is will still lead to a reallocation
/// and more copying. However if the data fits inside one packet, as is with
/// most cases, setting this field incorrectly can still have a minor impact
/// on performance.
///
/// In general, this field should probably be left alone unless you can
/// prove that the processing time for received packets far exceeds the
/// transmission time of the medium used.
///
///
/// **Default:** `None`
#[must_use]
pub fn size_estimate(mut self, estimate: NonZeroUsize) -> Self {
self.size_estimate = Some(estimate);
self
}
}

debug.finish()
impl fmt::Debug for Config {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Config")
.field("size_estimate", &self.size_estimate)
.finish()
}
}

Expand All @@ -485,7 +522,7 @@ where

impl<T, R, D> fmt::Debug for Receiver<T, R, D>
where
StatIO<R>: fmt::Debug,
R: fmt::Debug,
D: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
65 changes: 48 additions & 17 deletions channels/src/sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use core::marker::PhantomData;

use crate::error::SendError;
use crate::io::{AsyncWrite, IntoWriter, Write, Writer};
use crate::protocol::{Pcb, SendConfig};
use crate::protocol::Pcb;
use crate::serdes::Serializer;
use crate::util::StatIO;

Expand All @@ -19,7 +19,7 @@ pub struct Sender<T, W, S> {
writer: StatIO<W>,
serializer: S,
pcb: Pcb,
config: SendConfig,
config: Config,
}

impl<T> Sender<T, (), ()> {
Expand Down Expand Up @@ -273,7 +273,7 @@ pub struct Builder<T, W, S> {
_marker: PhantomData<T>,
writer: W,
serializer: S,
config: SendConfig,
config: Option<Config>,
}

impl<T> Builder<T, (), ()> {
Expand All @@ -296,7 +296,7 @@ impl<T> Builder<T, (), ()> {
_marker: PhantomData,
serializer: (),
writer: (),
config: SendConfig { flush_on_send: true },
config: None,
}
}
}
Expand Down Expand Up @@ -362,17 +362,22 @@ impl<T, W> Builder<T, W, ()> {
}

impl<T, W, S> Builder<T, W, S> {
/// Flush the writer after every [`Sender::send()`] and
/// [`Sender::send_blocking()`] call.
/// Set the [`Config`] for this sender.
///
/// **Default value**: `true`.
/// # Example
///
/// ```no_run
/// use channels::sender::{Config, Sender};
///
/// If this option is disabled, then flushing the writer (if needed) must be
/// done manually through the provided references given by [`Sender::get()`]
/// and [`Sender::get_mut()`].
/// let config = Config::default()
/// .flush_on_send(false);
///
/// let tx = Sender::<i32, _, _>::builder()
/// .config(config);
/// ```
#[must_use]
pub fn flush_on_send(mut self, yes: bool) -> Self {
self.config.flush_on_send = yes;
pub fn config(mut self, config: Config) -> Self {
self.config = Some(config);
self
}

Expand All @@ -392,16 +397,42 @@ impl<T, W, S> Builder<T, W, S> {
writer: StatIO::new(self.writer),
serializer: self.serializer,
pcb: Pcb::new(),
config: self.config,
config: self.config.unwrap_or_default(),
}
}
}

impl fmt::Debug for SendConfig {
/// Configuration for [`Sender`].
#[derive(Clone)]
pub struct Config {
pub(crate) flush_on_send: bool,
}

impl Default for Config {
fn default() -> Self {
Self { flush_on_send: true }
}
}

impl Config {
/// Flush the underlying writer after every [`send()`] or [`send_blocking()`].
///
/// **Default:** `true`
///
/// [`send()`]: Sender::send()
/// [`send_blocking()`]: Sender::send_blocking()
#[must_use]
pub fn flush_on_send(mut self, yes: bool) -> Self {
self.flush_on_send = yes;
self
}
}

impl fmt::Debug for Config {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut debug = f.debug_struct("Config");
debug.field("flush_on_send", &self.flush_on_send);
debug.finish()
f.debug_struct("Config")
.field("flush_on_send", &self.flush_on_send)
.finish()
}
}

Expand Down

0 comments on commit 327f386

Please sign in to comment.