Skip to content

Commit

Permalink
refactor: mock Statistics when feature not enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
threadexio committed May 6, 2024
1 parent ef02172 commit 43cb7bb
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 191 deletions.
3 changes: 2 additions & 1 deletion channels/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
extern crate alloc;

mod protocol;
mod statistics;
mod util;

pub mod error;
Expand All @@ -82,7 +83,7 @@ pub mod receiver;
pub mod sender;

#[cfg(feature = "statistics")]
pub use self::util::Statistics;
pub use self::statistics::Statistics;

pub use self::receiver::Receiver;
pub use self::sender::Sender;
Expand Down
3 changes: 2 additions & 1 deletion channels/src/protocol/deframer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use channels_packet::id::IdSequence;
use channels_packet::Flags;

use crate::receiver::Config;
use crate::util::{grow_vec_by_n, Statistics};
use crate::statistics::Statistics;
use crate::util::grow_vec_by_n;

#[derive(Clone, Default)]
struct RecvPcb {
Expand Down
11 changes: 2 additions & 9 deletions channels/src/protocol/recv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use alloc::vec::Vec;

use crate::error::RecvError;
use crate::io::{AsyncRead, Read};
use crate::util::StatIO;
use crate::statistics::StatIO;

use super::deframer::{DeframeError, DeframeStatus, Deframer};

Expand Down Expand Up @@ -80,17 +80,10 @@ where
{
use DeframeStatus::{NotReady, Ready};

#[cfg(not(feature = "statistics"))]
reader.statistics.inc_ops();

loop {
match deframer.deframe({
#[cfg(feature = "statistics")]
let statistics = &mut reader.statistics;
#[cfg(not(feature = "statistics"))]
let statistics = &mut Statistics::new();
statistics
}) {
match deframer.deframe(&mut reader.statistics) {
Ready(Ok(payload)) => break Ok(payload),
Ready(Err(e)) => break Err(e.into()),
NotReady(r) => {
Expand Down
4 changes: 1 addition & 3 deletions channels/src/protocol/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use channels_packet::{Flags, PacketLength, PayloadLength};
use crate::error::SendError;
use crate::io::{AsyncWrite, Write};
use crate::sender::Config;
use crate::util::StatIO;
use crate::statistics::StatIO;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SendPayloadError<Io> {
Expand Down Expand Up @@ -155,11 +155,9 @@ where
}
}

#[cfg(feature = "statistics")]
self.writer.statistics.inc_packets();
}

#[cfg(feature = "statistics")]
self.writer.statistics.inc_ops();

if self.config.flush_on_send() {
Expand Down
3 changes: 1 addition & 2 deletions channels/src/receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ use crate::error::RecvError;
use crate::io::{AsyncRead, Container, IntoRead, Read};
use crate::protocol::Deframer;
use crate::serdes::Deserializer;
use crate::util::StatIO;

#[allow(unused_imports)]
use crate::util::Statistics;
use crate::statistics::{StatIO, Statistics};

/// The receiving-half of the channel.
pub struct Receiver<T, R, D> {
Expand Down
3 changes: 1 addition & 2 deletions channels/src/sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ use crate::error::SendError;
use crate::io::{AsyncWrite, Container, IntoWrite, Write};
use crate::protocol::SendPcb;
use crate::serdes::Serializer;
use crate::util::StatIO;

#[allow(unused_imports)]
use crate::util::Statistics;
use crate::statistics::{StatIO, Statistics};

/// The sending-half of the channel.
pub struct Sender<T, W, S> {
Expand Down
206 changes: 206 additions & 0 deletions channels/src/statistics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
use core::fmt;
use core::pin::Pin;
use core::task::{ready, Context, Poll};

use crate::io::{
AsyncRead, AsyncWrite, Read, ReadBuf, Write, WriteBuf,
};

#[cfg(feature = "statistics")]
mod real {
use core::fmt;

/// IO statistic information.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Statistics {
total_bytes: u64,
packets: u64,
ops: u64,
}

#[allow(dead_code)]
impl Statistics {
pub(crate) const fn new() -> Self {
Self { total_bytes: 0, packets: 0, ops: 0 }
}

#[inline]
pub(crate) fn add_total_bytes(&mut self, n: u64) {
self.total_bytes += n;
}

#[inline]
pub(crate) fn inc_packets(&mut self) {
eprintln!("incrementing packet counter");
self.packets += 1;
}

#[inline]
pub(crate) fn inc_ops(&mut self) {
self.ops += 1;
}
}

#[allow(dead_code)]
impl Statistics {
/// Returns the number of bytes transferred through this reader/writer.
#[inline]
#[must_use]
pub fn total_bytes(&self) -> u64 {
self.total_bytes
}

/// Returns the number of packets transferred through this reader/writer.
#[inline]
#[must_use]
pub fn packets(&self) -> u64 {
self.packets
}

/// Returns the total number of `send`/`recv` operations.
#[inline]
#[must_use]
pub fn ops(&self) -> u64 {
self.ops
}
}

impl fmt::Debug for Statistics {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Statistics")
.field("total_bytes", &self.total_bytes)
.field("packets", &self.packets)
.field("ops", &self.ops)
.finish()
}
}
}

#[cfg(not(feature = "statistics"))]
mod mock {
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Statistics;

impl Statistics {
pub(crate) const fn new() -> Self {
Self
}

pub(crate) fn add_total_bytes(&mut self, _: u64) {}
pub(crate) fn inc_packets(&mut self) {}
pub(crate) fn inc_ops(&mut self) {}
}
}

#[cfg(feature = "statistics")]
pub use self::real::Statistics;

#[cfg(not(feature = "statistics"))]
pub use self::mock::Statistics;

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct StatIO<R> {
pub(crate) inner: R,
pub(crate) statistics: Statistics,
}

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

#[cfg(feature = "statistics")]
debug.field("statistics", &self.statistics);

debug.finish()
}
}

#[allow(unused_variables, clippy::unused_self)]
impl<R> StatIO<R> {
#[inline]
pub fn new(reader: R) -> Self {
Self { inner: reader, statistics: Statistics::new() }
}

#[inline]
fn on_read(&mut self, n: u64) {
self.statistics.add_total_bytes(n);
}

#[inline]
fn on_write(&mut self, n: u64) {
self.statistics.add_total_bytes(n);
}
}

impl<W: Write> Write for StatIO<W> {
type Error = W::Error;

fn write(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
self.inner.write(buf)?;

let dl = buf.len();
self.on_write(dl as u64);
Ok(())
}

fn flush(&mut self) -> Result<(), Self::Error> {
self.inner.flush()
}
}

impl<W: AsyncWrite> AsyncWrite for StatIO<W> {
type Error = W::Error;

fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context,
buf: &mut WriteBuf,
) -> Poll<Result<(), Self::Error>> {
let l0 = buf.consumed().len();
ready!(Pin::new(&mut self.inner).poll_write(cx, buf))?;
let l1 = buf.consumed().len();

let dl = l1 - l0;
self.on_write(dl as u64);
Poll::Ready(Ok(()))
}

fn poll_flush(
mut self: Pin<&mut Self>,
cx: &mut Context,
) -> Poll<Result<(), Self::Error>> {
Pin::new(&mut self.inner).poll_flush(cx)
}
}

impl<R: Read> Read for StatIO<R> {
type Error = R::Error;

fn read(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
self.inner.read(buf)?;

let dl = buf.len();
self.on_read(dl as u64);
Ok(())
}
}

impl<R: AsyncRead + Unpin> AsyncRead for StatIO<R> {
type Error = R::Error;

fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context,
buf: &mut ReadBuf,
) -> Poll<Result<(), Self::Error>> {
let l0 = buf.filled().len();
ready!(Pin::new(&mut self.inner).poll_read(cx, buf))?;
let l1 = buf.filled().len();

let dl = l1 - l0;
self.on_read(dl as u64);
Poll::Ready(Ok(()))
}
}
Loading

0 comments on commit 43cb7bb

Please sign in to comment.