@@ -37,34 +37,68 @@ pub enum CopySide {
3737 Destination ,
3838}
3939
40- /// Error encountered while attempting a data transfer .
40+ /// Error encountered while checking offsets against a buffer .
4141#[ derive( Clone , Debug , Error ) ]
4242#[ non_exhaustive]
43- pub enum TransferError {
44- #[ error( "Source and destination cannot be the same buffer" ) ]
45- SameSourceDestinationBuffer ,
46- #[ error( transparent) ]
47- MissingBufferUsage ( #[ from] MissingBufferUsageError ) ,
48- #[ error( transparent) ]
49- MissingTextureUsage ( #[ from] MissingTextureUsageError ) ,
50- #[ error( "Start offset ({offset}) is out-of-bounds for buffer of size {buffer_size}" ) ]
51- BufferStartOffsetOverrun {
43+ pub enum BufferOverrunError {
44+ #[ error( "start offset ({offset}) is out-of-bounds for buffer of size {buffer_size}" ) ]
45+ StartOffset {
5246 offset : BufferAddress ,
5347 buffer_size : BufferAddress ,
54- side : CopySide ,
5548 } ,
5649 #[ error(
57- "End offset (start at {} + size of {}) is out-of-bounds for buffer of size {}" ,
50+ "end offset (start at {} + size of {}) is out-of-bounds for buffer of size {}" ,
5851 offset,
5952 size,
6053 buffer_size
6154 ) ]
62- BufferEndOffsetOverrun {
55+ EndOffset {
6356 offset : BufferAddress ,
6457 size : BufferAddress ,
6558 buffer_size : BufferAddress ,
66- side : CopySide ,
6759 } ,
60+ }
61+
62+ impl BufferOverrunError {
63+ /// Returns the end offset if everything is validated.
64+ ///
65+ /// TODO: more
66+ pub ( crate ) fn check (
67+ offset : BufferAddress ,
68+ size : BufferAddress ,
69+ buffer_size : BufferAddress ,
70+ ) -> Result < BufferAddress , Self > {
71+ if offset >= buffer_size {
72+ return Err ( Self :: StartOffset {
73+ offset,
74+ buffer_size,
75+ } ) ;
76+ }
77+ // NOTE: Should never underflow because of our earlier check.
78+ if size > buffer_size - offset {
79+ return Err ( Self :: EndOffset {
80+ offset,
81+ size,
82+ buffer_size,
83+ } ) ;
84+ }
85+ // NOTE: Should never overflow because of our earlier check.
86+ Ok ( offset + size)
87+ }
88+ }
89+
90+ /// Error encountered while attempting a data transfer.
91+ #[ derive( Clone , Debug , Error ) ]
92+ #[ non_exhaustive]
93+ pub enum TransferError {
94+ #[ error( "Source and destination cannot be the same buffer" ) ]
95+ SameSourceDestinationBuffer ,
96+ #[ error( transparent) ]
97+ MissingBufferUsage ( #[ from] MissingBufferUsageError ) ,
98+ #[ error( transparent) ]
99+ MissingTextureUsage ( #[ from] MissingTextureUsageError ) ,
100+ #[ error( "Transfer {_0}" ) ]
101+ BufferOverrun ( BufferOverrunError ) ,
68102 #[ error( "Copy of {dimension:?} {start_offset}..{end_offset} would end up overrunning the bounds of the {side:?} texture of {dimension:?} size {texture_size}" ) ]
69103 TextureOverrun {
70104 start_offset : u32 ,
@@ -244,6 +278,12 @@ impl From<BufferTextureCopyInfoError> for TransferError {
244278 }
245279}
246280
281+ impl BufferOverrunError {
282+ fn to_transfer_error ( & self , side : CopySide ) -> TransferError {
283+ todo ! ( )
284+ }
285+ }
286+
247287pub ( crate ) fn extract_texture_selector < T > (
248288 copy_texture : & wgt:: TexelCopyTextureInfo < T > ,
249289 copy_size : & Extent3d ,
@@ -352,22 +392,9 @@ pub(crate) fn validate_linear_texture_data(
352392 return Err ( TransferError :: UnspecifiedRowsPerImage ) ;
353393 } ;
354394
355- if offset > buffer_size {
356- return Err ( TransferError :: BufferStartOffsetOverrun {
357- start_offset : offset,
358- buffer_size : bytes_in_copy,
359- side : buffer_side,
360- } ) ;
361- }
362- // NOTE: Should never underflow because of our earlier check.
363- if bytes_in_copy > buffer_size - offset {
364- return Err ( TransferError :: BufferEndOffsetOverrun {
365- offset,
366- size : bytes_in_copy,
367- buffer_size,
368- side : buffer_side,
369- } ) ;
370- }
395+ // Avoid underflow in the subtraction by checking bytes_in_copy against buffer_size first.
396+ let _ = BufferOverrunError :: check ( offset, bytes_in_copy, buffer_size)
397+ . map_err ( |e| e. to_transfer_error ( buffer_side) ) ?;
371398
372399 let is_contiguous = ( row_stride_bytes == row_bytes_dense || !requires_multiple_rows)
373400 && ( image_stride_bytes == image_bytes_dense || !requires_multiple_images) ;
0 commit comments