Skip to content

Commit 417e368

Browse files
authored
Merge pull request #1787 from seijikun/mr-alignedbuffer-api
uefi: Improve AlignedBuffer API with more accessors and copy_from_iter()
2 parents ae1d072 + 22f7b7b commit 417e368

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

uefi/src/mem/aligned_buffer.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
use alloc::alloc::{Layout, LayoutError, alloc, dealloc};
44
use core::error::Error;
5-
use core::fmt;
65
use core::ptr::NonNull;
6+
use core::{fmt, slice};
77

88
/// Helper class to maintain the lifetime of a memory region allocated with a non-standard alignment.
99
/// Facilitates RAII to properly deallocate when lifetime of the object ends.
@@ -51,12 +51,34 @@ impl AlignedBuffer {
5151
self.ptr.as_ptr()
5252
}
5353

54+
/// Get the underlying memory region as immutable slice.
55+
#[must_use]
56+
pub const fn as_slice(&self) -> &[u8] {
57+
unsafe { slice::from_raw_parts(self.ptr(), self.size()) }
58+
}
59+
60+
/// Get the underlying memory region as mutable slice.
61+
#[must_use]
62+
pub const fn as_slice_mut(&mut self) -> &mut [u8] {
63+
unsafe { slice::from_raw_parts_mut(self.ptr_mut(), self.size()) }
64+
}
65+
5466
/// Get the size of the aligned memory region managed by this instance.
5567
#[must_use]
5668
pub const fn size(&self) -> usize {
5769
self.layout.size()
5870
}
5971

72+
/// Returns an iterator over the aligned buffer contents.
73+
pub fn iter(&self) -> impl Iterator<Item = &u8> {
74+
self.as_slice().iter()
75+
}
76+
77+
/// Returns a mutable iterator over the aligned buffer contents.
78+
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut u8> {
79+
self.as_slice_mut().iter_mut()
80+
}
81+
6082
/// Fill the aligned memory region with data from the given buffer.
6183
///
6284
/// The length of `src` must be the same as `self`.
@@ -67,6 +89,14 @@ impl AlignedBuffer {
6789
}
6890
}
6991

92+
/// Fill the aligned memory region with data from the given iterator.
93+
/// If the given iterator is shorter than the buffer, the remaining area will be left untouched.
94+
pub fn copy_from_iter(&mut self, src: impl Iterator<Item = u8>) {
95+
self.iter_mut()
96+
.zip(src)
97+
.for_each(|(dst, src_byte)| *dst = src_byte);
98+
}
99+
70100
/// Check the buffer's alignment against the `required_alignment`.
71101
pub fn check_alignment(&self, required_alignment: usize) -> Result<(), AlignmentError> {
72102
//TODO: use bfr.addr() when it's available
@@ -120,4 +150,28 @@ mod tests {
120150
}
121151
}
122152
}
153+
154+
#[test]
155+
fn test_copy_from_iter() {
156+
let src8: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
157+
{
158+
// src as large as dst
159+
let mut bfr = AlignedBuffer::from_size_align(8, 8).unwrap();
160+
bfr.copy_from_iter(src8.iter().cloned());
161+
assert_eq!(bfr.as_slice(), src8);
162+
}
163+
{
164+
// src larger than dst
165+
let mut bfr = AlignedBuffer::from_size_align(7, 8).unwrap();
166+
bfr.copy_from_iter(src8.iter().cloned());
167+
assert_eq!(bfr.as_slice(), [1, 2, 3, 4, 5, 6, 7]);
168+
}
169+
{
170+
// src smaller than dst
171+
let mut bfr = AlignedBuffer::from_size_align(9, 8).unwrap();
172+
bfr.iter_mut().for_each(|dst| *dst = 0); // fill with 0s
173+
bfr.copy_from_iter(src8.iter().cloned());
174+
assert_eq!(bfr.as_slice(), [1, 2, 3, 4, 5, 6, 7, 8, 0]);
175+
}
176+
}
123177
}

0 commit comments

Comments
 (0)