Skip to content

Commit 730762f

Browse files
authored
block-buffer: add BlockSizes trait and use it in buffer bounds (#1455)
The trait was previously defined in `crypto-common`, but it will be removed (see RustCrypto/traits#2304) and we previously did not use it because of the circular dependency between repositories.
1 parent 359c374 commit 730762f

4 files changed

Lines changed: 42 additions & 39 deletions

File tree

block-buffer/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## 0.12.0 (2026-02-24)
8+
### Added
9+
- `BlockSizes` trait implemented for sizes bigger than `U0` and smaller than `U256` ([#1455])
10+
11+
### Changed
12+
- Block sizes used by `BlockBuffer` and `ReadBuffer` are now bound by `BlockSizes` ([#1455])
13+
14+
[#1455]: https://github.com/RustCrypto/utils/pull/1455
15+
716
## 0.11.0 (2025-11-07)
817
### Added
918
- `ReadBuffer` type ([#823])

block-buffer/src/lib.rs

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ mod sealed;
5353

5454
pub use read::ReadBuffer;
5555

56+
/// Trait implemented for supported block sizes, i.e. for types from `U1` to `U255`.
57+
pub trait BlockSizes: ArraySize + sealed::BlockSizes {}
58+
59+
impl<T: ArraySize + sealed::BlockSizes> BlockSizes for T {}
60+
5661
/// Trait for buffer kinds.
5762
pub trait BufferKind: sealed::Sealed {}
5863

@@ -86,32 +91,22 @@ impl fmt::Display for Error {
8691
}
8792

8893
/// Buffer for block processing of data.
89-
pub struct BlockBuffer<BS: ArraySize, K: BufferKind> {
94+
pub struct BlockBuffer<BS: BlockSizes, K: BufferKind> {
9095
buffer: MaybeUninit<Array<u8, BS>>,
9196
pos: K::Pos,
9297
}
9398

94-
impl<BS: ArraySize, K: BufferKind> BlockBuffer<BS, K> {
95-
/// This associated constant is used to assert block size correctness at compile time.
96-
const BLOCK_SIZE_ASSERT: bool = {
97-
assert!(BS::USIZE != 0, "Block size can not be equal to zero!");
98-
assert!(BS::USIZE <= 255, "Block size can not be bigger than 255!");
99-
true
100-
};
101-
}
102-
103-
impl<BS: ArraySize, K: BufferKind> Default for BlockBuffer<BS, K> {
99+
impl<BS: BlockSizes, K: BufferKind> Default for BlockBuffer<BS, K> {
104100
#[inline]
105101
fn default() -> Self {
106-
assert!(Self::BLOCK_SIZE_ASSERT);
107102
let mut buffer = MaybeUninit::uninit();
108103
let mut pos = Default::default();
109104
K::set_pos(&mut buffer, &mut pos, 0);
110105
Self { buffer, pos }
111106
}
112107
}
113108

114-
impl<BS: ArraySize, K: BufferKind> Clone for BlockBuffer<BS, K> {
109+
impl<BS: BlockSizes, K: BufferKind> Clone for BlockBuffer<BS, K> {
115110
#[inline]
116111
fn clone(&self) -> Self {
117112
// SAFETY: `BlockBuffer` does not implement `Drop` (i.e. it could be a `Copy` type),
@@ -120,7 +115,7 @@ impl<BS: ArraySize, K: BufferKind> Clone for BlockBuffer<BS, K> {
120115
}
121116
}
122117

123-
impl<BS: ArraySize, K: BufferKind> fmt::Debug for BlockBuffer<BS, K> {
118+
impl<BS: BlockSizes, K: BufferKind> fmt::Debug for BlockBuffer<BS, K> {
124119
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
125120
f.debug_struct(K::NAME)
126121
.field("pos", &self.get_pos())
@@ -130,7 +125,7 @@ impl<BS: ArraySize, K: BufferKind> fmt::Debug for BlockBuffer<BS, K> {
130125
}
131126
}
132127

133-
impl<BS: ArraySize, K: BufferKind> BlockBuffer<BS, K> {
128+
impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
134129
/// Create new buffer from slice.
135130
///
136131
/// # Panics
@@ -148,10 +143,6 @@ impl<BS: ArraySize, K: BufferKind> BlockBuffer<BS, K> {
148143
/// If slice length is not valid for used buffer kind.
149144
#[inline(always)]
150145
pub fn try_new(buf: &[u8]) -> Result<Self, Error> {
151-
const {
152-
assert!(Self::BLOCK_SIZE_ASSERT);
153-
}
154-
155146
if !K::invariant(buf.len(), BS::USIZE) {
156147
return Err(Error);
157148
}
@@ -318,7 +309,7 @@ pub type SerializedBufferSize<BS, K> = Sum<BS, <K as sealed::Sealed>::Overhead>;
318309
/// `BlockBuffer` serialized as a byte array.
319310
pub type SerializedBuffer<BS, K> = Array<u8, SerializedBufferSize<BS, K>>;
320311

321-
impl<BS: ArraySize, K: BufferKind> BlockBuffer<BS, K>
312+
impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K>
322313
where
323314
BS: core::ops::Add<K::Overhead>,
324315
Sum<BS, K::Overhead>: ArraySize,
@@ -337,7 +328,7 @@ where
337328
/// Deserialize buffer from a byte array.
338329
///
339330
/// # Errors
340-
/// If algorithm-specific invariant fails to hold
331+
/// If `buf` does not represent a valid serialization of `BlockBuffer`.
341332
pub fn deserialize(buf: &SerializedBuffer<BS, K>) -> Result<Self, Error> {
342333
let (pos, block) = buf.split_at(1);
343334
let pos = usize::from(pos[0]);
@@ -358,7 +349,7 @@ where
358349
}
359350
}
360351

361-
impl<BS: ArraySize> BlockBuffer<BS, Eager> {
352+
impl<BS: BlockSizes> BlockBuffer<BS, Eager> {
362353
/// Compress remaining data after padding it with `delim`, zeros and
363354
/// the `suffix` bytes. If there is not enough unused space, `compress`
364355
/// will be called twice.
@@ -413,15 +404,15 @@ impl<BS: ArraySize> BlockBuffer<BS, Eager> {
413404
}
414405

415406
#[cfg(feature = "zeroize")]
416-
impl<BS: ArraySize, K: BufferKind> Zeroize for BlockBuffer<BS, K> {
407+
impl<BS: BlockSizes, K: BufferKind> Zeroize for BlockBuffer<BS, K> {
417408
#[inline]
418409
fn zeroize(&mut self) {
419410
self.buffer.zeroize();
420411
self.pos.zeroize();
421412
}
422413
}
423414

424-
impl<BS: ArraySize, K: BufferKind> Drop for BlockBuffer<BS, K> {
415+
impl<BS: BlockSizes, K: BufferKind> Drop for BlockBuffer<BS, K> {
425416
#[inline]
426417
fn drop(&mut self) {
427418
#[cfg(feature = "zeroize")]
@@ -430,4 +421,4 @@ impl<BS: ArraySize, K: BufferKind> Drop for BlockBuffer<BS, K> {
430421
}
431422

432423
#[cfg(feature = "zeroize")]
433-
impl<BS: ArraySize, K: BufferKind> ZeroizeOnDrop for BlockBuffer<BS, K> {}
424+
impl<BS: BlockSizes, K: BufferKind> ZeroizeOnDrop for BlockBuffer<BS, K> {}

block-buffer/src/read.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,25 @@
1-
use super::{Array, ArraySize, Error};
1+
use super::{Array, BlockSizes, Error};
22
use core::fmt;
33

44
/// Buffer for reading block-generated data.
5-
pub struct ReadBuffer<BS: ArraySize> {
5+
pub struct ReadBuffer<BS: BlockSizes> {
66
/// The first byte of the block is used as cursor position.
77
/// `&buffer[usize::from(buffer[0])..]` is interpreted as unread bytes.
88
/// The cursor position is always bigger than zero and smaller than or equal to block size.
99
buffer: Array<u8, BS>,
1010
}
1111

12-
impl<BS: ArraySize> fmt::Debug for ReadBuffer<BS> {
12+
impl<BS: BlockSizes> fmt::Debug for ReadBuffer<BS> {
1313
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1414
f.debug_struct("ReadBuffer")
1515
.field("remaining_data", &self.remaining())
1616
.finish_non_exhaustive()
1717
}
1818
}
1919

20-
impl<BS: ArraySize> Default for ReadBuffer<BS> {
20+
impl<BS: BlockSizes> Default for ReadBuffer<BS> {
2121
#[inline]
2222
fn default() -> Self {
23-
assert!(
24-
BS::USIZE != 0 && BS::USIZE < 256,
25-
"buffer block size must be bigger than zero and smaller than 256"
26-
);
27-
2823
let buffer = Default::default();
2924
let mut res = Self { buffer };
3025
// SAFETY: `BS::USIZE` satisfies the `set_pos_unchecked` safety contract
@@ -33,15 +28,15 @@ impl<BS: ArraySize> Default for ReadBuffer<BS> {
3328
}
3429
}
3530

36-
impl<BS: ArraySize> Clone for ReadBuffer<BS> {
31+
impl<BS: BlockSizes> Clone for ReadBuffer<BS> {
3732
#[inline]
3833
fn clone(&self) -> Self {
3934
let buffer = self.buffer.clone();
4035
Self { buffer }
4136
}
4237
}
4338

44-
impl<BS: ArraySize> ReadBuffer<BS> {
39+
impl<BS: BlockSizes> ReadBuffer<BS> {
4540
/// Return current cursor position, i.e. how many bytes were read from the buffer.
4641
#[inline(always)]
4742
pub fn get_pos(&self) -> usize {
@@ -176,12 +171,12 @@ impl<BS: ArraySize> ReadBuffer<BS> {
176171
}
177172

178173
#[cfg(feature = "zeroize")]
179-
impl<BS: ArraySize> Drop for ReadBuffer<BS> {
174+
impl<BS: BlockSizes> Drop for ReadBuffer<BS> {
180175
fn drop(&mut self) {
181176
use zeroize::Zeroize;
182177
self.buffer.zeroize();
183178
}
184179
}
185180

186181
#[cfg(feature = "zeroize")]
187-
impl<BS: ArraySize> zeroize::ZeroizeOnDrop for ReadBuffer<BS> {}
182+
impl<BS: BlockSizes> zeroize::ZeroizeOnDrop for ReadBuffer<BS> {}

block-buffer/src/sealed.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use hybrid_array::sizes::{U0, U1};
1+
use hybrid_array::{
2+
sizes::{U0, U1, U256},
3+
typenum::{IsLess, NonZero, True, Unsigned},
4+
};
25

36
use super::{Array, ArraySize};
47
use core::{mem::MaybeUninit, ptr};
@@ -96,3 +99,8 @@ impl Sealed for super::Lazy {
9699
}
97100
}
98101
}
102+
103+
/// Sealed trait implemented for sizes from `U1` to `U255`.
104+
pub trait BlockSizes {}
105+
106+
impl<T: Unsigned> BlockSizes for T where Self: IsLess<U256, Output = True> + NonZero {}

0 commit comments

Comments
 (0)