Skip to content

Commit 51e91af

Browse files
committed
[update] write_slice to return a result.
1 parent 3a8ffb9 commit 51e91af

File tree

1 file changed

+40
-17
lines changed

1 file changed

+40
-17
lines changed

crates/lambda-rs/src/render/buffer.rs

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,19 @@ impl Buffer {
170170
/// Example
171171
/// ```rust,ignore
172172
/// let transforms: Vec<InstanceTransform> = compute_transforms();
173-
/// instance_buffer.write_slice(render_context.gpu(), 0, &transforms);
173+
/// instance_buffer
174+
/// .write_slice(render_context.gpu(), 0, &transforms)
175+
/// .unwrap();
174176
/// ```
175-
pub fn write_slice<T: Copy>(&self, gpu: &Gpu, offset: u64, data: &[T]) {
176-
let bytes = slice_as_bytes(data);
177+
pub fn write_slice<T: Copy>(
178+
&self,
179+
gpu: &Gpu,
180+
offset: u64,
181+
data: &[T],
182+
) -> Result<(), &'static str> {
183+
let bytes = slice_as_bytes(data)?;
177184
self.write_bytes(gpu, offset, bytes);
185+
return Ok(());
178186
}
179187
}
180188

@@ -188,21 +196,23 @@ fn value_as_bytes<T: Copy>(data: &T) -> &[u8] {
188196
return bytes;
189197
}
190198

191-
fn slice_as_bytes<T: Copy>(data: &[T]) -> &[u8] {
192-
let element_size = std::mem::size_of::<T>();
193-
let Some(byte_len) = element_size.checked_mul(data.len()) else {
194-
debug_assert!(
195-
false,
196-
"Buffer::write_slice byte length overflow: element_size={}, len={}",
197-
element_size,
198-
data.len()
199-
);
200-
return &[];
199+
fn checked_byte_len(
200+
element_size: usize,
201+
element_count: usize,
202+
) -> Result<usize, &'static str> {
203+
let Some(byte_len) = element_size.checked_mul(element_count) else {
204+
return Err("Buffer byte length overflow.");
201205
};
206+
return Ok(byte_len);
207+
}
208+
209+
fn slice_as_bytes<T: Copy>(data: &[T]) -> Result<&[u8], &'static str> {
210+
let element_size = std::mem::size_of::<T>();
211+
let byte_len = checked_byte_len(element_size, data.len())?;
202212

203213
let bytes =
204214
unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u8, byte_len) };
205-
return bytes;
215+
return Ok(bytes);
206216
}
207217

208218
/// Strongly‑typed uniform buffer wrapper for ergonomics and safety.
@@ -398,7 +408,7 @@ impl BufferBuilder {
398408
data_len: usize,
399409
) -> Result<usize, &'static str> {
400410
let buffer_length = if self.buffer_length == 0 {
401-
element_size * data_len
411+
checked_byte_len(element_size, data_len)?
402412
} else {
403413
self.buffer_length
404414
};
@@ -428,6 +438,13 @@ mod tests {
428438
assert_eq!(builder.label.as_deref(), Some("buffer-test"));
429439
}
430440

441+
#[test]
442+
fn resolve_length_rejects_overflow() {
443+
let builder = BufferBuilder::new();
444+
let result = builder.resolve_length(usize::MAX, 2);
445+
assert!(result.is_err());
446+
}
447+
431448
#[test]
432449
fn value_as_bytes_matches_native_bytes() {
433450
let value: u32 = 0x1122_3344;
@@ -442,12 +459,18 @@ mod tests {
442459
for value in values {
443460
expected.extend_from_slice(&value.to_ne_bytes());
444461
}
445-
assert_eq!(slice_as_bytes(&values), expected.as_slice());
462+
assert_eq!(slice_as_bytes(&values).unwrap(), expected.as_slice());
446463
}
447464

448465
#[test]
449466
fn slice_as_bytes_empty_is_empty() {
450467
let values: [u32; 0] = [];
451-
assert_eq!(slice_as_bytes(&values), &[]);
468+
assert_eq!(slice_as_bytes(&values).unwrap(), &[]);
469+
}
470+
471+
#[test]
472+
fn checked_byte_len_rejects_overflow() {
473+
let result = checked_byte_len(usize::MAX, 2);
474+
assert!(result.is_err());
452475
}
453476
}

0 commit comments

Comments
 (0)