Skip to content

Commit f54e65e

Browse files
committed
add get_array to Buf
1 parent 141cbc2 commit f54e65e

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ name = "bytes"
66
# - Create "v1.x.y" git tag.
77
version = "1.10.1"
88
edition = "2018"
9-
rust-version = "1.39"
9+
rust-version = "1.51"
1010
license = "MIT"
1111
authors = [
1212
"Carl Lerche <me@carllerche.com>",

src/buf/buf_impl.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,30 @@ pub trait Buf {
296296
.unwrap_or_else(|error| panic_advance(&error));
297297
}
298298

299+
/// Gets a const known number of bytes from `self`
300+
///
301+
/// The current position is advanced by `N`.
302+
///
303+
/// # Examples
304+
///
305+
/// ```
306+
/// use bytes::Buf;
307+
///
308+
/// let mut buf = &b"hello world"[..];
309+
/// assert_eq!(*b"hello", buf.get_array::<5>());
310+
/// ```
311+
///
312+
/// # Panics
313+
///
314+
/// This function panics if there is not enough remaining data in `self`.
315+
fn get_array<const N: usize>(&mut self) -> [u8; N]
316+
where
317+
Self: Sized,
318+
{
319+
self.try_get_array()
320+
.unwrap_or_else(|error| panic_advance(&error))
321+
}
322+
299323
/// Gets an unsigned 8 bit integer from `self`.
300324
///
301325
/// The current position is advanced by 1.
@@ -1178,6 +1202,61 @@ pub trait Buf {
11781202
Ok(())
11791203
}
11801204

1205+
/// Gets a const known number of bytes from `self`
1206+
///
1207+
/// The current position is advanced by `N`.
1208+
///
1209+
/// Returns `Err(TryGetError)` when there are not enough
1210+
/// remaining bytes to read the value.
1211+
///
1212+
/// # Examples
1213+
///
1214+
/// ```
1215+
/// use bytes::Buf;
1216+
///
1217+
/// let mut buf = &b"hello world"[..];
1218+
/// assert_eq!(Ok(*b"hello"), buf.try_get_array::<5>());
1219+
/// assert_eq!(6, buf.remaining());
1220+
/// ```
1221+
/// ```
1222+
/// use bytes::{Buf, TryGetError};
1223+
///
1224+
/// let mut buf = &b"hel"[..];
1225+
/// assert_eq!(Err(TryGetError{requested: 5, available: 3}), buf.try_get_array::<5>());
1226+
/// assert_eq!(3, buf.remaining());
1227+
/// ```
1228+
///
1229+
fn try_get_array<const N: usize>(&mut self) -> Result<[u8; N], TryGetError>
1230+
where
1231+
Self: Sized,
1232+
{
1233+
if self.remaining() < N {
1234+
return Err(TryGetError {
1235+
requested: N,
1236+
available: self.remaining(),
1237+
});
1238+
}
1239+
1240+
// try to convert directly from the bytes
1241+
// this Option<ret> trick is to avoid keeping a borrow on self
1242+
// when advance() is called (mut borrow) and to call bytes() only once
1243+
let ret = self
1244+
.chunk()
1245+
.get(..N)
1246+
.map(|src| unsafe { *(src as *const _ as *const [_; N]) });
1247+
1248+
if let Some(ret) = ret {
1249+
// if the direct conversion was possible, advance and return
1250+
self.advance(N);
1251+
return Ok(ret);
1252+
} else {
1253+
// if not we copy the bytes in a temp buffer then convert
1254+
let mut buf = [0; N];
1255+
self.copy_to_slice(&mut buf); // (do the advance)
1256+
return Ok(buf);
1257+
}
1258+
}
1259+
11811260
/// Gets an unsigned 8 bit integer from `self`.
11821261
///
11831262
/// The current position is advanced by 1.

0 commit comments

Comments
 (0)