From d55d764e10f57bf3dc938541d8796e983f977945 Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Wed, 29 Apr 2026 15:34:44 -0500 Subject: [PATCH] Move BytesSplit to a module --- src/bytes_split.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++ src/codec.rs | 64 +++-------------------------------- src/lib.rs | 4 +-- 3 files changed, 91 insertions(+), 61 deletions(-) create mode 100644 src/bytes_split.rs diff --git a/src/bytes_split.rs b/src/bytes_split.rs new file mode 100644 index 0000000..d4e40b4 --- /dev/null +++ b/src/bytes_split.rs @@ -0,0 +1,84 @@ +use bytes::{Buf, Bytes}; + +pub struct BytesSplit(Bytes, u8); + +impl BytesSplit { + pub fn new(inner: Bytes, split_at: u8) -> Self { + Self(inner, split_at) + } +} + +impl Iterator for BytesSplit { + type Item = Bytes; + + fn next(&mut self) -> Option { + if self.0.is_empty() { + return None; + } + + // find the index of the first delimiter + let Some(i) = self + .0 + .iter() + .enumerate() + .find_map(|(i, b)| (*b == self.1).then_some(i)) + else { + // we're on the last element + let last_elem = self.0.clone(); + self.0.clear(); + return Some(last_elem); + }; + + // extract the element + let elem = self.0.split_to(i); + // remove the comma + self.0.advance(1); + + Some(elem) + } +} + +#[cfg(test)] +mod tests { + #![allow(clippy::unwrap_used)] + + use super::*; + use bytes::Bytes; + + #[test] + fn splits_on_commas() { + let bytes = Bytes::from(b"foo,bar,baz".as_slice()); + let mut split = BytesSplit::new(bytes, b','); + + assert_eq!(split.next().unwrap().as_ref(), b"foo"); + assert_eq!(split.next().unwrap().as_ref(), b"bar"); + assert_eq!(split.next().unwrap().as_ref(), b"baz"); + assert_eq!(split.next(), None); + } + + #[test] + fn trailing_comma_returns_none() { + let bytes = Bytes::from(b"foo,".as_slice()); + let mut split = BytesSplit::new(bytes, b','); + + assert_eq!(split.next().unwrap().as_ref(), b"foo"); + assert_eq!(split.next(), None); + } + + #[test] + fn single_comma_returns_empty_then_none() { + let bytes = Bytes::from(b",".as_slice()); + let mut split = BytesSplit::new(bytes, b','); + + assert_eq!(split.next().unwrap().as_ref(), b""); + assert_eq!(split.next(), None); + } + + #[test] + fn empty_string_returns_none() { + let bytes = Bytes::from(b"".as_slice()); + let mut split = BytesSplit::new(bytes, b','); + + assert_eq!(split.next(), None); + } +} diff --git a/src/codec.rs b/src/codec.rs index ac45599..7901fc3 100644 --- a/src/codec.rs +++ b/src/codec.rs @@ -1,7 +1,10 @@ -use bytes::{Buf, BufMut, Bytes}; +use bytes::{BufMut, Bytes}; use tokio_util::codec::{AnyDelimiterCodec, AnyDelimiterCodecError, Decoder, Encoder}; -use crate::command::{Command, ParamSet, Response}; +use crate::{ + bytes_split::BytesSplit, + command::{Command, ParamSet, Response}, +}; #[derive(Clone, Debug)] pub struct Codec { @@ -116,60 +119,3 @@ impl Decoder for Codec { Ok(Some(RawResponse { cmd, raw_values })) } } - -struct BytesSplit(Bytes, u8); - -impl BytesSplit { - fn new(inner: Bytes, split_at: u8) -> Self { - Self(inner, split_at) - } -} - -impl Iterator for BytesSplit { - type Item = Bytes; - - fn next(&mut self) -> Option { - if self.0.is_empty() { - return None; - } - - // find the index of the first delimiter - let Some(i) = self - .0 - .iter() - .enumerate() - .find_map(|(i, b)| (*b == self.1).then_some(i)) - else { - // we're on the last element - let last_elem = self.0.clone(); - self.0.clear(); - return Some(last_elem); - }; - - // extract the element - let elem = self.0.split_to(i); - // remove the comma - self.0.advance(1); - - Some(elem) - } -} - -#[cfg(test)] -mod tests { - #![allow(clippy::unwrap_used)] - - use super::*; - use bytes::Bytes; - - #[test] - fn split_works() { - let bytes = Bytes::from(b"foo,bar,baz".as_slice()); - let mut split = BytesSplit::new(bytes, b','); - - assert_eq!(split.next().unwrap().as_ref(), b"foo"); - assert_eq!(split.next().unwrap().as_ref(), b"bar"); - assert_eq!(split.next().unwrap().as_ref(), b"baz"); - assert_eq!(split.next(), None); - } -} diff --git a/src/lib.rs b/src/lib.rs index 0fa1f0c..54350cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ +mod bytes_split; mod codec; -mod scanner; - mod command; +mod scanner; pub use crate::command::bc125at; pub use crate::command::{Command, Param, ParamSet, Response}; -- 2.51.2