Skip to content

Commit

Permalink
feat(bytestring): split_at method
Browse files Browse the repository at this point in the history
  • Loading branch information
robjtede committed Nov 23, 2024
1 parent 01a104e commit 3bf3b5c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
1 change: 1 addition & 0 deletions bytestring/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Add `ByteString::split_at()` method.
- Minimum supported Rust version (MSRV) is now 1.70.

## 1.3.1
Expand Down
2 changes: 1 addition & 1 deletion bytestring/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = [
"Nikolay Kim <[email protected]>",
"Rob Ede <[email protected]>",
]
keywords = ["string", "bytes", "utf8", "web", "actix"]
keywords = ["string", "bytes", "utf8", "web", "bytestring"]
categories = ["no-std", "web-programming"]
homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-net"
Expand Down
55 changes: 53 additions & 2 deletions bytestring/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use core::{borrow::Borrow, fmt, hash, ops, str};

use bytes::Bytes;

/// An immutable UTF-8 encoded string with [`Bytes`] as a storage.
/// An immutable UTF-8 encoded string using [`Bytes`] as storage.
#[derive(Clone, Default, Eq, PartialOrd, Ord)]
pub struct ByteString(Bytes);

Expand Down Expand Up @@ -53,7 +53,29 @@ impl ByteString {
Self(src)
}

/// Returns a new byte string that is equivalent to the given `subset`.
/// Divides one bytestring into two at an index, returning both parts.
///
/// # Panics
///
/// Panics if `mid` is not on a UTF-8 code point boundary, or if it is past the end of the last
/// code point of the bytestring.
pub fn split_at(&self, mid: usize) -> (ByteString, ByteString) {
let this: &str = self.as_ref();
let _valid_midpoint_check = this.split_at(mid);

let mut bytes = self.0.clone();
let first = bytes.split_to(mid);
let last = bytes;

unsafe {
(
ByteString::from_bytes_unchecked(first),
ByteString::from_bytes_unchecked(last),
)
}
}

/// Returns a new `ByteString` that is equivalent to the given `subset`.
///
/// When processing a `ByteString` buffer with other tools, one often gets a `&str` which is in
/// fact a slice of the original `ByteString`; i.e., a subset of it. This function turns that
Expand Down Expand Up @@ -465,4 +487,33 @@ mod test {
// being a logical subset of the string
ByteString::from_static("foo bar").slice_ref("foo");
}

#[test]
fn split_at() {
let buf = ByteString::from_static("foo bar");

let (first, last) = buf.split_at(0);
assert_eq!(ByteString::from_static(""), first);
assert_eq!(ByteString::from_static("foo bar"), last);

let (first, last) = buf.split_at(4);
assert_eq!(ByteString::from_static("foo "), first);
assert_eq!(ByteString::from_static("bar"), last);

let (first, last) = buf.split_at(7);
assert_eq!(ByteString::from_static("foo bar"), first);
assert_eq!(ByteString::from_static(""), last);
}

#[test]
#[should_panic]
fn split_at_invalid_code_point() {
ByteString::from_static("µ").split_at(1);
}

#[test]
#[should_panic]
fn split_at_outside_string() {
ByteString::from_static("foo").split_at(9);
}
}

0 comments on commit 3bf3b5c

Please sign in to comment.