@@ -312,3 +312,86 @@ func normalPrint(_ input: (base: UInt32, isBigEndian: Bool), expected: String)
312
312
)
313
313
#expect( String ( describing: collection) == expected)
314
314
}
315
+
316
+ @Test ( " Mutate contiguous storage " )
317
+ func mutateContiguousStorage( ) async throws {
318
+ // No usage with elements aren't raw octets.
319
+ var nonOctets = EmbeddedIntegerCollection (
320
+ embedding: UInt16 . self, within: 0x1234_5678_9ABC_DEF0 as UInt64 ,
321
+ iteratingFrom: . mostSignificantFirst
322
+ )
323
+ let nonOctetCount = nonOctets. withContiguousMutableStorageIfAvailable (
324
+ flipAndCount ( _: )
325
+ )
326
+ #expect( nonOctetCount == nil )
327
+
328
+ // Octet elements
329
+ var bigOctets = EmbeddedIntegerCollection (
330
+ embedding: UInt8 . self, within: 0x0123_4567 as UInt32 ,
331
+ iteratingFrom: . mostSignificantFirst
332
+ )
333
+ #expect( bigOctets. word == 0x0123_4567 )
334
+ #expect( bigOctets. elementsEqual ( [ 0x01 , 0x23 , 0x45 , 0x67 ] ) )
335
+
336
+ let bigOctetCount = bigOctets. withContiguousMutableStorageIfAvailable (
337
+ flipAndCount ( _: )
338
+ )
339
+ #expect( bigOctetCount == 4 )
340
+ #expect( bigOctets. word == 0xFEDC_BA98 )
341
+ #expect( bigOctets. elementsEqual ( [ 0xFE , 0xDC , 0xBA , 0x98 ] ) )
342
+
343
+ var littleOctets = EmbeddedIntegerCollection (
344
+ embedding: UInt8 . self, within: 0x0123_4567 as UInt32 ,
345
+ iteratingFrom: . leastSignificantFirst
346
+ )
347
+ #expect( littleOctets. word == 0x0123_4567 )
348
+ #expect( littleOctets. elementsEqual ( [ 0x67 , 0x45 , 0x23 , 0x01 ] ) )
349
+
350
+ let littleOctetCount = littleOctets. withContiguousMutableStorageIfAvailable (
351
+ flipAndCount ( _: )
352
+ )
353
+ #expect( littleOctetCount == 4 )
354
+ #expect( littleOctets. word == 0xFEDC_BA98 )
355
+ #expect( littleOctets. elementsEqual ( [ 0x98 , 0xBA , 0xDC , 0xFE ] ) )
356
+ }
357
+
358
+ /// Return the given collection's length after mutating each element.
359
+ private func flipAndCount< T: MutableCollection > ( _ collection: inout T ) -> Int
360
+ where T. Element: BinaryInteger {
361
+ for i in collection. indices {
362
+ collection [ i] = ~ collection[ i]
363
+ }
364
+ return collection. count
365
+ }
366
+
367
+ @Test (
368
+ " Inspect contiguous storage " ,
369
+ arguments: [ 0 , 0x0123_4567 , 0x89AB_CDEF ] , [ false , true ]
370
+ )
371
+ func inspectContiguousStorage( wrapped: UInt32 , isBigEndian: Bool ) async throws {
372
+ let collection = EmbeddedIntegerCollection (
373
+ embedding: UInt8 . self,
374
+ within: wrapped,
375
+ iteratingFrom: isBigEndian ? . mostSignificantFirst : . leastSignificantFirst
376
+ )
377
+ let bitsCount = try #require(
378
+ collection. withContiguousStorageIfAvailable {
379
+ return $0. map ( \. nonzeroBitCount) . reduce ( 0 , + )
380
+ }
381
+ )
382
+ #expect( bitsCount == collection. word. nonzeroBitCount)
383
+ }
384
+
385
+ @Test ( " Inspecting non-octet contiguous storage " )
386
+ func nonOctetInspectContiguousStorage( ) async throws {
387
+ let collection = EmbeddedIntegerCollection (
388
+ embedding: UInt16 . self,
389
+ within: 0x0123_4567 as UInt32 ,
390
+ iteratingFrom: . leastSignificantFirst
391
+ )
392
+ #expect(
393
+ collection. withContiguousStorageIfAvailable {
394
+ return $0. map ( \. nonzeroBitCount) . reduce ( 0 , + )
395
+ } == nil
396
+ )
397
+ }
0 commit comments