1use wasm_dbms_api::prelude::{
7 DataSize, Encode, MSize, MemoryError, MemoryResult, Page, PageOffset,
8};
9
10use crate::memory_access::MemoryAccess;
11use crate::provider::MemoryProvider;
12
13pub const SCHEMA_PAGE: Page = 0;
15pub const UNCLAIMED_PAGES_PAGE: Page = 1;
17pub const RESERVED_PAGES: u64 = 2;
19
20pub struct MemoryManager<P>
23where
24 P: MemoryProvider,
25{
26 provider: P,
27}
28
29impl<P> MemoryManager<P>
30where
31 P: MemoryProvider,
32{
33 pub fn init(provider: P) -> Self {
40 let mut manager = MemoryManager { provider };
41
42 let current_pages = manager.provider.pages();
44 if current_pages >= RESERVED_PAGES {
45 return manager;
46 }
47
48 let missing = RESERVED_PAGES - current_pages;
50 if let Err(err) = manager.provider.grow(missing) {
51 panic!("Failed to grow memory during initialization: {err}");
52 }
53
54 manager
55 }
56
57 pub const fn schema_page(&self) -> Page {
59 SCHEMA_PAGE
60 }
61
62 pub const fn unclaimed_pages_page(&self) -> Page {
64 UNCLAIMED_PAGES_PAGE
65 }
66
67 #[cfg(test)]
72 pub(crate) fn into_provider(self) -> P {
73 self.provider
74 }
75
76 pub fn last_page(&self) -> Option<Page> {
78 match self.provider.pages() {
79 0 => None,
80 n => Some(n as Page - 1),
81 }
82 }
83
84 pub fn pages_count(&self) -> u64 {
86 self.provider.pages()
87 }
88
89 fn absolute_offset(&self, page: Page, offset: PageOffset) -> u64 {
92 (page as u64)
93 .checked_mul(P::PAGE_SIZE)
94 .and_then(|page_offset| page_offset.checked_add(offset as u64))
95 .expect("Overflow when calculating absolute offset")
96 }
97
98 fn check_unallocated_page(
100 &self,
101 page: Page,
102 offset: PageOffset,
103 data_size: MSize,
104 ) -> MemoryResult<()> {
105 if self.last_page().is_none_or(|last_page| page > last_page) {
106 return Err(MemoryError::SegmentationFault {
107 page,
108 offset,
109 data_size: data_size as u64,
110 page_size: P::PAGE_SIZE,
111 });
112 }
113 Ok(())
114 }
115
116 fn check_alignment<E>(&self, offset: PageOffset) -> MemoryResult<()>
119 where
120 E: Encode,
121 {
122 let alignment = E::ALIGNMENT as PageOffset;
123 if alignment != 0 && !offset.is_multiple_of(alignment) {
124 return Err(MemoryError::OffsetNotAligned { offset, alignment });
125 }
126 Ok(())
127 }
128}
129
130impl<P> MemoryAccess for MemoryManager<P>
131where
132 P: MemoryProvider,
133{
134 fn page_size(&self) -> u64 {
135 P::PAGE_SIZE
136 }
137
138 fn grow_one_page(&mut self) -> MemoryResult<Page> {
139 self.provider.grow(1)?;
140
141 self.provider.write(
143 self.absolute_offset(self.last_page().unwrap_or(0), 0),
144 &vec![0u8; P::PAGE_SIZE as usize],
145 )?;
146
147 match self.last_page() {
148 Some(page) => Ok(page),
149 None => Err(MemoryError::FailedToAllocatePage),
150 }
151 }
152
153 fn zero_page(&mut self, page: Page) -> MemoryResult<()> {
154 if self.last_page().is_none_or(|last_page| page > last_page) {
155 return Err(MemoryError::SegmentationFault {
156 page,
157 offset: 0,
158 data_size: P::PAGE_SIZE,
159 page_size: P::PAGE_SIZE,
160 });
161 }
162
163 let absolute_offset = self.absolute_offset(page, 0);
164 let buffer = vec![0u8; P::PAGE_SIZE as usize];
165 self.provider.write(absolute_offset, &buffer)
166 }
167
168 fn read_at<D>(&mut self, page: Page, offset: PageOffset) -> MemoryResult<D>
169 where
170 D: Encode,
171 {
172 self.check_alignment::<D>(offset)?;
173
174 let mut buf = vec![
175 0u8;
176 match D::SIZE {
177 DataSize::Fixed(size) => size as usize,
178 DataSize::Dynamic => (P::PAGE_SIZE as usize).saturating_sub(offset as usize),
179 }
180 ];
181
182 let read = self.read_at_raw(page, offset, &mut buf)?;
183 if read < buf.len() {
186 return Err(MemoryError::SegmentationFault {
187 page,
188 offset,
189 data_size: buf.len() as u64,
190 page_size: P::PAGE_SIZE,
191 });
192 }
193
194 D::decode(std::borrow::Cow::Owned(buf))
195 }
196
197 fn write_at<E>(&mut self, page: Page, offset: PageOffset, data: &E) -> MemoryResult<()>
198 where
199 E: Encode,
200 {
201 self.check_unallocated_page(page, offset, data.size())?;
202 self.check_alignment::<E>(offset)?;
203
204 let encoded = data.encode();
205 let padded_len = align_up::<E>(encoded.len());
209
210 if offset as u64 + padded_len as u64 > P::PAGE_SIZE {
211 return Err(MemoryError::SegmentationFault {
212 page,
213 offset,
214 data_size: padded_len as u64,
215 page_size: P::PAGE_SIZE,
216 });
217 }
218
219 let absolute_offset = self.absolute_offset(page, offset);
220 self.provider.write(absolute_offset, encoded.as_ref())?;
221
222 let padding = padded_len - encoded.len();
224 if padding > 0 {
225 let padding_offset = absolute_offset + encoded.len() as u64;
226 let padding_buffer = vec![0u8; padding];
227 self.provider
228 .write(padding_offset, padding_buffer.as_ref())?;
229 }
230
231 Ok(())
232 }
233
234 fn write_at_raw(&mut self, page: Page, offset: PageOffset, buf: &[u8]) -> MemoryResult<()> {
235 self.check_unallocated_page(page, offset, buf.len() as MSize)?;
236
237 if offset as u64 + buf.len() as u64 > P::PAGE_SIZE {
238 return Err(MemoryError::SegmentationFault {
239 page,
240 offset,
241 data_size: buf.len() as u64,
242 page_size: P::PAGE_SIZE,
243 });
244 }
245
246 let absolute_offset = self.absolute_offset(page, offset);
247 self.provider.write(absolute_offset, buf)
248 }
249
250 fn zero<E>(&mut self, page: Page, offset: PageOffset, data: &E) -> MemoryResult<()>
251 where
252 E: Encode,
253 {
254 self.check_unallocated_page(page, offset, data.size())?;
255 self.check_alignment::<E>(offset)?;
256
257 let length = align_up::<E>(data.size() as usize);
258
259 if offset as u64 + (length as u64) > P::PAGE_SIZE {
260 return Err(MemoryError::SegmentationFault {
261 page,
262 offset,
263 data_size: data.size() as u64,
264 page_size: P::PAGE_SIZE,
265 });
266 }
267
268 let absolute_offset = self.absolute_offset(page, offset);
269 let buffer = vec![0u8; length];
270 self.provider.write(absolute_offset, buffer.as_ref())
271 }
272
273 fn zero_raw(&mut self, page: Page, offset: PageOffset, len: PageOffset) -> MemoryResult<()> {
274 if self.last_page().is_none_or(|last_page| page > last_page) {
275 return Err(MemoryError::SegmentationFault {
276 page,
277 offset,
278 data_size: len as u64,
279 page_size: P::PAGE_SIZE,
280 });
281 }
282
283 if offset as u64 + len as u64 > P::PAGE_SIZE {
284 return Err(MemoryError::SegmentationFault {
285 page,
286 offset,
287 data_size: len as u64,
288 page_size: P::PAGE_SIZE,
289 });
290 }
291
292 let absolute_offset = self.absolute_offset(page, offset);
293 let buffer = vec![0u8; len as usize];
294 self.provider.write(absolute_offset, buffer.as_ref())
295 }
296
297 fn read_at_raw(
298 &mut self,
299 page: Page,
300 offset: PageOffset,
301 buf: &mut [u8],
302 ) -> MemoryResult<usize> {
303 if self.last_page().is_none_or(|last_page| page > last_page) {
304 return Err(MemoryError::SegmentationFault {
305 page,
306 offset,
307 data_size: buf.len() as u64,
308 page_size: P::PAGE_SIZE,
309 });
310 }
311
312 let read_len = ((P::PAGE_SIZE - offset as u64) as usize).min(buf.len());
313
314 let absolute_offset = self.absolute_offset(page, offset);
315 self.provider
316 .read(absolute_offset, buf[..read_len].as_mut())?;
317
318 Ok(read_len)
319 }
320}
321
322#[inline]
325pub const fn align_up<E>(offset: usize) -> usize
326where
327 E: Encode,
328{
329 let alignment = E::ALIGNMENT as usize;
330 offset.div_ceil(alignment) * alignment
331}
332
333#[cfg(test)]
334mod tests {
335 use std::borrow::Cow;
336
337 use wasm_dbms_api::prelude::{
338 DEFAULT_ALIGNMENT, DataSize, MSize, MemoryError, MemoryResult, PageOffset, Text,
339 };
340
341 use super::*;
342 use crate::provider::HeapMemoryProvider;
343
344 const SCRATCH_PAGE: Page = SCHEMA_PAGE;
346
347 fn make_mm() -> MemoryManager<HeapMemoryProvider> {
348 MemoryManager::init(HeapMemoryProvider::default())
349 }
350
351 #[test]
352 fn test_fixed_read_rejects_a_value_truncated_at_the_page_end() {
353 let mut mm = make_mm();
354 let page = mm.claim_page().expect("claim");
355 mm.write_at_raw(page, 65_532, &[1, 2, 3, 4])
356 .expect("write tail");
357
358 let value: MemoryResult<crate::RecordAddress> = mm.read_at(page, 65_532);
360 assert!(matches!(value, Err(MemoryError::SegmentationFault { .. })));
361 }
362
363 #[test]
364 fn test_should_init_memory_manager() {
365 let mm = make_mm();
366 assert_eq!(mm.last_page(), Some(1));
367 }
368
369 #[test]
370 fn test_should_get_last_page() {
371 let mm = make_mm();
372 let last_page = mm.last_page();
373 assert_eq!(last_page, Some(1)); }
375
376 #[test]
377 fn test_reserved_layout_is_schema_then_unclaimed_pages() {
378 let mm = make_mm();
379 assert_eq!(RESERVED_PAGES, 2);
380 assert_eq!(mm.schema_page(), 0);
381 assert_eq!(mm.unclaimed_pages_page(), 1);
382 }
383
384 #[test]
385 fn test_should_get_memory_page_size() {
386 let mm = make_mm();
387 let page_size = mm.page_size();
388 assert_eq!(page_size, HeapMemoryProvider::PAGE_SIZE);
389 }
390
391 #[test]
392 fn test_should_write_and_read_fixed_data_size() {
393 let mut mm = make_mm();
394 let data_to_write = FixedSizeData { a: 42, b: 1337 };
395 mm.write_at(SCRATCH_PAGE, 0, &data_to_write)
396 .expect("Failed to write data to scratch page");
397
398 let out: FixedSizeData = mm
399 .read_at(SCRATCH_PAGE, 0)
400 .expect("Failed to read data from scratch page");
401
402 assert_eq!(out, data_to_write);
403 }
404
405 #[test]
406 fn test_write_should_zero_padding() {
407 let mut mm = make_mm();
408 let data_to_write = Text("very_long_string".to_string());
409 mm.write_at(SCRATCH_PAGE, 0, &data_to_write)
410 .expect("Failed to write data to scratch page");
411
412 let mut buffer = vec![0; 32];
413 mm.read_at_raw(SCRATCH_PAGE, 0, &mut buffer)
414 .expect("Failed to read data from scratch page");
415
416 let non_zero_count = buffer.iter().filter(|&&b| b != 0).count();
417 assert_eq!(non_zero_count, data_to_write.size() as usize - 1);
418
419 let data_to_write_short = Text("short".to_string());
420 mm.write_at(SCRATCH_PAGE, 0, &data_to_write_short)
421 .expect("Failed to write data to scratch page");
422
423 let mut buffer = vec![0; 32];
424 mm.read_at_raw(SCRATCH_PAGE, 0, &mut buffer)
425 .expect("Failed to read data from scratch page");
426
427 let non_zero_count = buffer.iter().filter(|&&b| b != 0).count();
428 assert_eq!(non_zero_count, data_to_write_short.size() as usize - 1);
429 }
430
431 #[test]
432 fn test_should_zero_data() {
433 let mut mm = make_mm();
434 let data_to_write = FixedSizeData { a: 100, b: 200 };
435 mm.write_at(SCRATCH_PAGE, 48, &data_to_write)
436 .expect("Failed to write data to scratch page");
437
438 mm.zero(SCRATCH_PAGE, 48, &data_to_write)
439 .expect("Failed to zero data on scratch page");
440
441 let mut buffer = vec![0; 50];
442 mm.read_at_raw(SCRATCH_PAGE, 48, &mut buffer)
443 .expect("Failed to read data from scratch page");
444
445 assert!(buffer.iter().all(|&b| b == 0));
446 }
447
448 #[test]
449 fn test_should_zero_with_alignment() {
450 let mut mm = make_mm();
451 let data_to_write = FixedSizeData { a: 100, b: 200 };
452 mm.write_at(SCRATCH_PAGE, 0, &data_to_write)
453 .expect("Failed to write data to scratch page");
454 let data_to_write = FixedSizeData { a: 100, b: 200 };
455 mm.write_at(SCRATCH_PAGE, 6, &data_to_write)
456 .expect("Failed to write data to scratch page");
457
458 let data_with_alignment = DataWithAlignment { a: 100, b: 200 };
459 mm.zero(SCRATCH_PAGE, 0, &data_with_alignment)
460 .expect("Failed to zero data on scratch page");
461
462 let mut buffer = vec![0; 32];
463 mm.read_at_raw(SCRATCH_PAGE, 0, &mut buffer)
464 .expect("Failed to read data from scratch page");
465 assert!(
466 buffer.iter().all(|&b| b == 0),
467 "First 32 bytes are not zeroed"
468 );
469 }
470
471 #[test]
472 fn test_should_check_whether_write_is_aligned() {
473 let mut mm = make_mm();
474 let data_to_write = FixedSizeData { a: 100, b: 200 };
475 let res = mm.write_at(SCRATCH_PAGE, 2, &data_to_write);
476 assert!(matches!(res, Err(MemoryError::OffsetNotAligned { .. })));
477 }
478
479 #[test]
480 fn test_should_check_whether_read_is_aligned() {
481 let mut mm = make_mm();
482 let result: MemoryResult<FixedSizeData> = mm.read_at(SCRATCH_PAGE, 3);
483 assert!(matches!(result, Err(MemoryError::OffsetNotAligned { .. })));
484 }
485
486 #[test]
487 fn test_should_check_whether_zero_is_aligned() {
488 let mut mm = make_mm();
489 let data_to_zero = FixedSizeData { a: 1, b: 2 };
490 let result = mm.zero(SCRATCH_PAGE, 5, &data_to_zero);
491 assert!(matches!(result, Err(MemoryError::OffsetNotAligned { .. })));
492 }
493
494 #[test]
495 fn test_should_not_zero_unallocated_page() {
496 let mut mm = make_mm();
497 let data_to_zero = FixedSizeData { a: 1, b: 2 };
498 let result = mm.zero(10, 0, &data_to_zero);
499 assert!(matches!(result, Err(MemoryError::SegmentationFault { .. })));
500 }
501
502 #[test]
503 fn test_should_not_zero_out_of_bounds() {
504 let mut mm = make_mm();
505 let data_to_zero = FixedSizeData { a: 1, b: 2 };
506 let result = mm.zero(
507 SCRATCH_PAGE,
508 (HeapMemoryProvider::PAGE_SIZE - 4) as PageOffset,
509 &data_to_zero,
510 );
511 assert!(matches!(result, Err(MemoryError::SegmentationFault { .. })));
512 }
513
514 #[test]
515 fn test_should_read_raw() {
516 let mut mm = make_mm();
517 let data_to_write = vec![1u8, 2, 3, 4, 5];
518 mm.write_at_raw(SCRATCH_PAGE, 20, &data_to_write)
519 .expect("Failed to write raw data to scratch page");
520
521 let mut buf = vec![0u8; 5];
522 mm.read_at_raw(SCRATCH_PAGE, 20, &mut buf)
523 .expect("Failed to read raw data from scratch page");
524
525 assert_eq!(buf, data_to_write);
526 }
527
528 #[test]
529 fn test_should_fail_out_of_bounds_access() {
530 let mut mm = make_mm();
531 let data_to_write = FixedSizeData { a: 1, b: 2 };
532 let result = mm.write_at(
533 SCRATCH_PAGE,
534 (HeapMemoryProvider::PAGE_SIZE - 4) as PageOffset,
535 &data_to_write,
536 );
537 assert!(matches!(result, Err(MemoryError::SegmentationFault { .. })));
538
539 let result: MemoryResult<FixedSizeData> = mm.read_at(10, 0);
540 assert!(matches!(result, Err(MemoryError::SegmentationFault { .. })));
541 let result = mm.write_at(10, 0, &data_to_write);
542 assert!(matches!(result, Err(MemoryError::SegmentationFault { .. })));
543 }
544
545 #[test]
546 fn test_rejected_padded_write_does_not_touch_the_next_page() {
547 let mut mm = make_mm();
548 let first = mm.claim_page().expect("claim first");
549 let next = mm.claim_page().expect("claim next");
550 mm.write_at_raw(next, 0, &[0xAA; 4])
551 .expect("seed next page");
552
553 let result = mm.write_at(first, 65_530, &TenAlignedData([3; 6]));
555 assert!(matches!(result, Err(MemoryError::SegmentationFault { .. })));
556
557 let mut buf = [0u8; 4];
558 mm.read_at_raw(next, 0, &mut buf).expect("read next page");
559 assert_eq!(buf, [0xAA; 4]);
560 }
561
562 #[test]
563 fn test_should_claim_new_page_by_growing() {
564 let mut mm = make_mm();
565 let initial_last_page = mm.last_page().unwrap();
566 let new_page = mm.claim_page().expect("Failed to claim new page");
567 assert_eq!(new_page, initial_last_page + 1);
568 let updated_last_page = mm.last_page().unwrap();
569 assert_eq!(updated_last_page, new_page);
570 }
571
572 #[test]
573 fn test_unclaim_then_claim_returns_same_page() {
574 let mut mm = make_mm();
575 let first = mm.claim_page().expect("claim");
576 mm.write_at_raw(first, 0, &[0xAB, 0xCD, 0xEF, 0x42])
578 .expect("write");
579
580 mm.unclaim_page(first).expect("unclaim");
581
582 let reused = mm.claim_page().expect("claim again");
584 assert_eq!(reused, first);
585
586 let mut buf = [0u8; 4];
588 mm.read_at_raw(reused, 0, &mut buf).expect("read");
589 assert_eq!(buf, [0u8; 4]);
590 }
591
592 #[test]
593 fn test_claim_after_exhausting_unclaimed_grows_memory() {
594 let mut mm = make_mm();
595 let page_a = mm.claim_page().expect("claim a");
596 let page_b = mm.claim_page().expect("claim b");
597
598 mm.unclaim_page(page_a).expect("unclaim a");
599 mm.unclaim_page(page_b).expect("unclaim b");
600
601 let _ = mm.claim_page().expect("reuse 1");
603 let _ = mm.claim_page().expect("reuse 2");
604 let high_water_before = mm.last_page().unwrap();
605 let grown = mm.claim_page().expect("grow");
606 assert_eq!(grown, high_water_before + 1);
607 }
608
609 #[test]
610 fn test_unclaim_persists_across_reload() {
611 let mut provider = HeapMemoryProvider::default();
612 {
613 let mut mm = MemoryManager::init(provider);
614 let first = mm.claim_page().expect("claim");
615 mm.unclaim_page(first).expect("unclaim");
616 provider = mm.into_provider();
617 }
618 let mut mm = MemoryManager::init(provider);
619 let reused = mm.claim_page().expect("claim after reload");
620 assert_eq!(reused, RESERVED_PAGES as Page);
621 }
622
623 #[test]
624 fn test_zero_page_zeros_full_page_contents() {
625 let mut mm = make_mm();
626 let page = mm.claim_page().expect("claim");
627 mm.write_at_raw(page, 0, &[1, 2, 3, 4]).expect("write 0");
629 mm.write_at_raw(page, 30_000, &[9, 9]).expect("write 30k");
630
631 mm.zero_page(page).expect("zero_page");
632
633 let mut buf = [0u8; 4];
634 mm.read_at_raw(page, 0, &mut buf).expect("read");
635 assert_eq!(buf, [0u8; 4]);
636 let mut buf = [0u8; 2];
637 mm.read_at_raw(page, 30_000, &mut buf).expect("read");
638 assert_eq!(buf, [0u8; 2]);
639 }
640
641 #[test]
642 fn test_zero_page_rejects_unallocated_page() {
643 let mut mm = make_mm();
644 let result = mm.zero_page(99);
645 assert!(matches!(result, Err(MemoryError::SegmentationFault { .. })));
646 }
647
648 #[test]
649 fn test_should_check_unallocated_page() {
650 let mm = make_mm();
651 let result = mm.check_unallocated_page(100, 0, 10);
652 assert!(matches!(result, Err(MemoryError::SegmentationFault { .. })));
653
654 let last_page = mm.last_page().unwrap();
655 let result = mm.check_unallocated_page(last_page, 0, 10);
656 assert!(result.is_ok());
657 }
658
659 #[test]
660 fn test_should_compute_padding() {
661 assert_eq!(align_up::<DataWithAlignment>(0), 0);
662 assert_eq!(align_up::<DataWithAlignment>(1), 32);
663 assert_eq!(align_up::<DataWithAlignment>(2), 32);
664 assert_eq!(align_up::<DataWithAlignment>(3), 32);
665 assert_eq!(align_up::<DataWithAlignment>(31), 32);
666 assert_eq!(align_up::<DataWithAlignment>(32), 32);
667 assert_eq!(align_up::<DataWithAlignment>(48), 64);
668 assert_eq!(align_up::<DataWithAlignment>(147), 160);
669 }
670
671 #[derive(Debug, Clone, PartialEq)]
672 struct FixedSizeData {
673 a: u16,
674 b: u32,
675 }
676
677 impl Encode for FixedSizeData {
678 const SIZE: DataSize = DataSize::Fixed(6);
679 const ALIGNMENT: PageOffset = 6;
680
681 fn encode(&'_ self) -> Cow<'_, [u8]> {
682 let mut buf = vec![0u8; self.size() as usize];
683 buf[0..2].copy_from_slice(&self.a.to_le_bytes());
684 buf[2..6].copy_from_slice(&self.b.to_le_bytes());
685 Cow::Owned(buf)
686 }
687
688 fn decode(data: Cow<[u8]>) -> MemoryResult<Self>
689 where
690 Self: Sized,
691 {
692 let a = u16::from_le_bytes([data[0], data[1]]);
693 let b = u32::from_le_bytes([data[2], data[3], data[4], data[5]]);
694 Ok(FixedSizeData { a, b })
695 }
696
697 fn size(&self) -> MSize {
698 6
699 }
700 }
701
702 #[derive(Debug, Clone, PartialEq)]
703 struct DataWithAlignment {
704 a: u16,
705 b: u32,
706 }
707
708 impl Encode for DataWithAlignment {
709 const SIZE: DataSize = DataSize::Dynamic;
710 const ALIGNMENT: PageOffset = DEFAULT_ALIGNMENT;
711
712 fn encode(&'_ self) -> Cow<'_, [u8]> {
713 let mut buf = vec![0u8; self.size() as usize];
714 buf[0..2].copy_from_slice(&self.a.to_le_bytes());
715 buf[2..6].copy_from_slice(&self.b.to_le_bytes());
716 Cow::Owned(buf)
717 }
718
719 fn decode(data: Cow<[u8]>) -> MemoryResult<Self>
720 where
721 Self: Sized,
722 {
723 let a = u16::from_le_bytes([data[0], data[1]]);
724 let b = u32::from_le_bytes([data[2], data[3], data[4], data[5]]);
725 Ok(DataWithAlignment { a, b })
726 }
727
728 fn size(&self) -> MSize {
729 6
730 }
731 }
732
733 #[derive(Debug, Clone, PartialEq)]
736 struct TenAlignedData([u8; 6]);
737
738 impl Encode for TenAlignedData {
739 const SIZE: DataSize = DataSize::Dynamic;
740 const ALIGNMENT: PageOffset = 10;
741
742 fn encode(&'_ self) -> Cow<'_, [u8]> {
743 Cow::Owned(self.0.to_vec())
744 }
745
746 fn decode(data: Cow<[u8]>) -> MemoryResult<Self>
747 where
748 Self: Sized,
749 {
750 Ok(Self(data[0..6].try_into()?))
751 }
752
753 fn size(&self) -> MSize {
754 6
755 }
756 }
757}