@@ -103,6 +103,56 @@ impl<const SIZE: usize> ArrayMemoryRegion<SIZE> {
103103 self . data . set_len ( data_len) ;
104104 self . data . as_mut_ptr ( ) . copy_from ( data_ptr, data_len) ;
105105 }
106+
107+ /// Try to build a [ArrayMemoryRegion] from an [IntoIterator<Item = u8>]
108+ pub fn try_from_iter < I : IntoIterator < Item = u8 > > (
109+ iter : I ,
110+ ) -> Result < Self , MemoryRegionFormIterError > {
111+ use MemoryRegionFormIterError :: * ;
112+ let mut iter = iter. into_iter ( ) ;
113+
114+ match iter. next ( ) {
115+ Some ( MEMORY_REGION_IDENTIFIER ) => { }
116+ Some ( id) => return Err ( InvalidIdentifier ( id) ) ,
117+ None => return Err ( NotEnoughItems ) ,
118+ }
119+
120+ let start_address = u64:: from_le_bytes ( [
121+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
122+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
123+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
124+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
125+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
126+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
127+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
128+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
129+ ] ) ;
130+
131+ let length = u64:: from_le_bytes ( [
132+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
133+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
134+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
135+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
136+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
137+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
138+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
139+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
140+ ] ) ;
141+
142+ if length > SIZE as u64 {
143+ return Err ( LengthTooBig ( length) ) ;
144+ }
145+
146+ // This call panics if length > SIZE
147+ // and `iter` does indeed contain more than SIZE items,
148+ // but we've just covered that case
149+ let data = ArrayVec :: from_iter ( iter. take ( length as usize ) ) ;
150+
151+ Ok ( Self {
152+ start_address,
153+ data,
154+ } )
155+ }
106156}
107157
108158#[ cfg( feature = "std" ) ]
@@ -134,42 +184,7 @@ impl<'a, const SIZE: usize> FromIterator<&'a u8> for ArrayMemoryRegion<SIZE> {
134184
135185impl < const SIZE : usize > FromIterator < u8 > for ArrayMemoryRegion < SIZE > {
136186 fn from_iter < T : IntoIterator < Item = u8 > > ( iter : T ) -> Self {
137- let mut iter = iter. into_iter ( ) ;
138-
139- assert_eq ! (
140- iter. next( ) . unwrap( ) ,
141- MEMORY_REGION_IDENTIFIER ,
142- "The given iterator is not for a memory region"
143- ) ;
144-
145- let start_address = u64:: from_le_bytes ( [
146- iter. next ( ) . unwrap ( ) ,
147- iter. next ( ) . unwrap ( ) ,
148- iter. next ( ) . unwrap ( ) ,
149- iter. next ( ) . unwrap ( ) ,
150- iter. next ( ) . unwrap ( ) ,
151- iter. next ( ) . unwrap ( ) ,
152- iter. next ( ) . unwrap ( ) ,
153- iter. next ( ) . unwrap ( ) ,
154- ] ) ;
155-
156- let length = u64:: from_le_bytes ( [
157- iter. next ( ) . unwrap ( ) ,
158- iter. next ( ) . unwrap ( ) ,
159- iter. next ( ) . unwrap ( ) ,
160- iter. next ( ) . unwrap ( ) ,
161- iter. next ( ) . unwrap ( ) ,
162- iter. next ( ) . unwrap ( ) ,
163- iter. next ( ) . unwrap ( ) ,
164- iter. next ( ) . unwrap ( ) ,
165- ] ) ;
166-
167- let data = ArrayVec :: from_iter ( iter. take ( length as usize ) ) ;
168-
169- Self {
170- start_address,
171- data,
172- }
187+ Self :: try_from_iter ( iter) . unwrap ( )
173188 }
174189}
175190
@@ -234,6 +249,49 @@ impl VecMemoryRegion {
234249
235250 self . data . as_mut_ptr ( ) . copy_from ( data_ptr, data_len) ;
236251 }
252+
253+ /// Try to build a [VecMemoryRegion] from an [IntoIterator<Item = u8>]
254+ pub fn try_from_iter < I : IntoIterator < Item = u8 > > (
255+ iter : I ,
256+ ) -> Result < Self , MemoryRegionFormIterError > {
257+ use MemoryRegionFormIterError :: * ;
258+ let mut iter = iter. into_iter ( ) ;
259+
260+ match iter. next ( ) {
261+ Some ( MEMORY_REGION_IDENTIFIER ) => { }
262+ Some ( id) => return Err ( InvalidIdentifier ( id) ) ,
263+ None => return Err ( NotEnoughItems ) ,
264+ }
265+
266+ let start_address = u64:: from_le_bytes ( [
267+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
268+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
269+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
270+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
271+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
272+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
273+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
274+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
275+ ] ) ;
276+
277+ let length = u64:: from_le_bytes ( [
278+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
279+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
280+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
281+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
282+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
283+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
284+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
285+ iter. next ( ) . ok_or ( NotEnoughItems ) ?,
286+ ] ) ;
287+
288+ let data = Vec :: from_iter ( iter. take ( length as usize ) ) ;
289+
290+ Ok ( Self {
291+ start_address,
292+ data,
293+ } )
294+ }
237295}
238296
239297#[ cfg( feature = "std" ) ]
@@ -267,42 +325,7 @@ impl<'a> FromIterator<&'a u8> for VecMemoryRegion {
267325#[ cfg( feature = "std" ) ]
268326impl FromIterator < u8 > for VecMemoryRegion {
269327 fn from_iter < T : IntoIterator < Item = u8 > > ( iter : T ) -> Self {
270- let mut iter = iter. into_iter ( ) ;
271-
272- assert_eq ! (
273- iter. next( ) . unwrap( ) ,
274- MEMORY_REGION_IDENTIFIER ,
275- "The given iterator is not for a memory region"
276- ) ;
277-
278- let start_address = u64:: from_le_bytes ( [
279- iter. next ( ) . unwrap ( ) ,
280- iter. next ( ) . unwrap ( ) ,
281- iter. next ( ) . unwrap ( ) ,
282- iter. next ( ) . unwrap ( ) ,
283- iter. next ( ) . unwrap ( ) ,
284- iter. next ( ) . unwrap ( ) ,
285- iter. next ( ) . unwrap ( ) ,
286- iter. next ( ) . unwrap ( ) ,
287- ] ) ;
288-
289- let length = u64:: from_le_bytes ( [
290- iter. next ( ) . unwrap ( ) ,
291- iter. next ( ) . unwrap ( ) ,
292- iter. next ( ) . unwrap ( ) ,
293- iter. next ( ) . unwrap ( ) ,
294- iter. next ( ) . unwrap ( ) ,
295- iter. next ( ) . unwrap ( ) ,
296- iter. next ( ) . unwrap ( ) ,
297- iter. next ( ) . unwrap ( ) ,
298- ] ) ;
299-
300- let data = Vec :: from_iter ( iter. take ( length as usize ) ) ;
301-
302- Self {
303- start_address,
304- data,
305- }
328+ Self :: try_from_iter ( iter) . unwrap ( )
306329 }
307330}
308331
@@ -433,6 +456,32 @@ impl<'a> Iterator for MemoryRegionIterator<'a> {
433456
434457impl < ' a > ExactSizeIterator for MemoryRegionIterator < ' a > { }
435458
459+ #[ derive( Debug ) ]
460+ /// Specifies what went wrong building a [MemoryRegion] from an iterator
461+ pub enum MemoryRegionFormIterError {
462+ /// The given iterator is not for a memory region.
463+ /// First item from iterator yielded invalid identifier. Expected [MEMORY_REGION_IDENTIFIER]
464+ InvalidIdentifier ( u8 ) ,
465+ /// Iterator specified length too big for declared region
466+ LengthTooBig ( u64 ) ,
467+ /// Iterator did not yield enough items to build memory region
468+ NotEnoughItems ,
469+ }
470+
471+ impl core:: fmt:: Display for MemoryRegionFormIterError {
472+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
473+ use MemoryRegionFormIterError :: * ;
474+ match self {
475+ InvalidIdentifier ( id) => write ! ( f, "Iterator is not for a memory region. Started with {id}, expected {MEMORY_REGION_IDENTIFIER}" ) ,
476+ LengthTooBig ( len) => write ! ( f, "Iterator specified length too big for declared region: {len}" ) ,
477+ NotEnoughItems => write ! ( f, "Iterator did not yield enough items to build memory region" ) ,
478+ }
479+ }
480+ }
481+
482+ #[ cfg( feature = "std" ) ]
483+ impl std:: error:: Error for MemoryRegionFormIterError { }
484+
436485#[ cfg( test) ]
437486mod tests {
438487 use super :: * ;
0 commit comments