1use crate::macros::passthrough_trait_fn;
10#[cfg(feature = "vm-memory")]
11use crate::misc_helpers::ImagoAsRef;
12use std::alloc::{self, GlobalAlloc};
13use std::fmt::{self, Debug, Formatter};
14use std::io::{IoSlice, IoSliceMut};
15use std::marker::PhantomData;
16#[cfg(unix)]
17use std::mem;
18use std::mem::{size_of, size_of_val};
19use std::ops::Range;
20use std::{cmp, io, ptr, slice};
21
22pub struct IoBuffer {
24 pointer: *mut u8,
26
27 size: usize,
29
30 layout: Option<alloc::Layout>,
32}
33
34pub struct IoBufferRef<'a> {
36 pointer: *const u8,
38
39 size: usize,
41
42 _lifetime: PhantomData<&'a [u8]>,
44}
45
46pub struct IoBufferMut<'a> {
48 pointer: *mut u8,
50
51 size: usize,
53
54 _lifetime: PhantomData<&'a mut [u8]>,
56}
57
58unsafe impl Send for IoBuffer {}
60unsafe impl Sync for IoBuffer {}
61unsafe impl Send for IoBufferRef<'_> {}
62unsafe impl Sync for IoBufferRef<'_> {}
63unsafe impl Send for IoBufferMut<'_> {}
64unsafe impl Sync for IoBufferMut<'_> {}
65
66impl IoBuffer {
67 pub fn new(size: usize, alignment: usize) -> io::Result<Self> {
72 let layout = alloc::Layout::from_size_align(size, alignment).map_err(io::Error::other)?;
73 Self::new_with_layout(layout)
74 }
75
76 pub fn new_with_layout(layout: alloc::Layout) -> io::Result<Self> {
78 if layout.size() == 0 {
79 return Ok(IoBuffer {
80 pointer: ptr::null_mut(),
81 size: 0,
82 layout: None,
83 });
84 }
85
86 let pointer = unsafe { alloc::System.alloc(layout) };
89
90 if pointer.is_null() {
91 return Err(io::Error::new(
92 io::ErrorKind::OutOfMemory,
93 format!(
94 "Failed to allocate memory (size={}, alignment={})",
95 layout.size(),
96 layout.align(),
97 ),
98 ));
99 }
100
101 Ok(IoBuffer {
102 pointer,
103 size: layout.size(),
104 layout: Some(layout),
105 })
106 }
107
108 pub fn len(&self) -> usize {
110 self.size
111 }
112
113 pub fn is_empty(&self) -> bool {
115 self.size == 0
116 }
117
118 pub fn as_ref(&self) -> IoBufferRef<'_> {
120 IoBufferRef {
121 pointer: self.pointer as *const u8,
122 size: self.size,
123 _lifetime: PhantomData,
124 }
125 }
126
127 pub fn as_ref_range(&self, range: Range<usize>) -> IoBufferRef<'_> {
129 IoBufferRef::from_slice(&self.as_ref().into_slice()[range])
130 }
131
132 pub fn as_mut(&mut self) -> IoBufferMut<'_> {
134 IoBufferMut {
135 pointer: self.pointer,
136 size: self.size,
137 _lifetime: PhantomData,
138 }
139 }
140
141 pub fn as_mut_range(&mut self, range: Range<usize>) -> IoBufferMut<'_> {
143 (&mut self.as_mut().into_slice()[range]).into()
144 }
145}
146
147impl Drop for IoBuffer {
148 fn drop(&mut self) {
150 if let Some(layout) = self.layout {
151 unsafe {
153 alloc::System.dealloc(self.pointer, layout);
154 }
155 }
156 }
157}
158
159#[allow(dead_code)]
161pub(crate) trait IoBufferRefTrait<'a>: Sized {
162 type SliceType<T: Copy + Sized + 'a>;
164
165 type PointerType<T: Copy + Sized + 'a>;
167
168 fn from_slice(slice: Self::SliceType<u8>) -> Self;
170
171 fn try_into_owned(self, alignment: usize) -> io::Result<IoBuffer>;
173
174 fn len(&self) -> usize;
176
177 fn is_empty(&self) -> bool {
179 self.len() == 0
180 }
181
182 fn as_ptr(&self) -> Self::PointerType<u8>;
184
185 fn into_slice(self) -> Self::SliceType<u8> {
191 unsafe { self.into_typed_slice::<u8>() }
193 }
194
195 unsafe fn into_typed_slice<T: Copy + Sized>(self) -> Self::SliceType<T>;
201
202 fn split_at(self, mid: usize) -> (Self, Self);
208
209 fn into_ref(self) -> IoBufferRef<'a>;
211}
212
213impl<'a> IoBufferRef<'a> {
214 pub fn from_slice(slice: &'a [u8]) -> Self {
216 IoBufferRef {
217 pointer: slice.as_ptr(),
218 size: size_of_val(slice),
219 _lifetime: PhantomData,
220 }
221 }
222
223 pub fn try_into_owned(self, alignment: usize) -> io::Result<IoBuffer> {
225 let mut new_buf = IoBuffer::new(self.len(), alignment)?;
226 new_buf
227 .as_mut()
228 .into_slice()
229 .copy_from_slice(self.into_slice());
230 Ok(new_buf)
231 }
232
233 pub fn len(&self) -> usize {
235 self.size
236 }
237
238 pub fn is_empty(&self) -> bool {
240 self.len() == 0
241 }
242
243 pub fn as_ptr(&self) -> *const u8 {
245 self.pointer
246 }
247
248 pub fn into_slice(self) -> &'a [u8] {
254 unsafe { self.into_typed_slice::<u8>() }
256 }
257
258 pub unsafe fn into_typed_slice<T: Copy + Sized>(self) -> &'a [T] {
264 if self.is_empty() {
265 return &[];
266 }
267
268 unsafe { slice::from_raw_parts(self.as_ptr() as *const T, self.len() / size_of::<T>()) }
271 }
272
273 pub fn split_at(self, mid: usize) -> (IoBufferRef<'a>, IoBufferRef<'a>) {
279 let head_len = cmp::min(mid, self.size);
280
281 (
282 IoBufferRef {
283 pointer: self.pointer,
284 size: head_len,
285 _lifetime: PhantomData,
286 },
287 IoBufferRef {
288 pointer: unsafe { self.pointer.add(head_len) },
290 size: self.size - head_len,
291 _lifetime: PhantomData,
292 },
293 )
294 }
295
296 pub fn into_ref(self) -> IoBufferRef<'a> {
298 self
299 }
300}
301
302impl<'a> IoBufferRefTrait<'a> for IoBufferRef<'a> {
303 type SliceType<T: Copy + Sized + 'a> = &'a [T];
304 type PointerType<T: Copy + Sized + 'a> = *const T;
305
306 passthrough_trait_fn! { fn from_slice(slice: Self::SliceType<u8>) -> Self; }
307 passthrough_trait_fn! { fn try_into_owned(self, alignment: usize) -> io::Result<IoBuffer>; }
308 passthrough_trait_fn! { fn len(&self) -> usize; }
309 passthrough_trait_fn! { fn as_ptr(&self) -> Self::PointerType<u8>; }
310 passthrough_trait_fn! { fn split_at(self, mid: usize) -> (Self, Self); }
311 passthrough_trait_fn! { fn into_ref(self) -> IoBufferRef<'a>; }
312
313 unsafe fn into_typed_slice<T: Copy + Sized>(self) -> Self::SliceType<T> {
314 unsafe { Self::into_typed_slice(self) }
316 }
317}
318
319impl<'a> From<IoSlice<'a>> for IoBufferRef<'a> {
320 fn from(slice: IoSlice<'a>) -> Self {
321 IoBufferRef {
322 pointer: slice.as_ptr(),
323 size: slice.len(),
324 _lifetime: PhantomData,
325 }
326 }
327}
328
329impl<'a> From<IoBufferRef<'a>> for IoSlice<'a> {
330 fn from(buf: IoBufferRef<'a>) -> Self {
331 IoSlice::new(buf.into_slice())
332 }
333}
334
335impl<'a> IoBufferMut<'a> {
336 pub fn from_slice(slice: &'a mut [u8]) -> Self {
338 IoBufferMut {
339 pointer: slice.as_mut_ptr(),
340 size: size_of_val(slice),
341 _lifetime: PhantomData,
342 }
343 }
344
345 pub fn try_into_owned(self, alignment: usize) -> io::Result<IoBuffer> {
347 let mut new_buf = IoBuffer::new(self.len(), alignment)?;
348 new_buf
349 .as_mut()
350 .into_slice()
351 .copy_from_slice(self.into_slice());
352 Ok(new_buf)
353 }
354
355 pub fn len(&self) -> usize {
357 self.size
358 }
359
360 pub fn is_empty(&self) -> bool {
362 self.len() == 0
363 }
364
365 pub fn as_ptr(&self) -> *mut u8 {
367 self.pointer
368 }
369
370 pub fn into_slice(self) -> &'a mut [u8] {
376 unsafe { self.into_typed_slice::<u8>() }
378 }
379
380 pub unsafe fn into_typed_slice<T: Copy + Sized>(self) -> &'a mut [T] {
386 if self.is_empty() {
387 return &mut [];
388 }
389
390 unsafe { slice::from_raw_parts_mut(self.as_ptr() as *mut T, self.len() / size_of::<T>()) }
393 }
394
395 pub fn split_at(self, mid: usize) -> (IoBufferMut<'a>, IoBufferMut<'a>) {
401 let head_len = cmp::min(mid, self.size);
402
403 (
404 IoBufferMut {
405 pointer: self.pointer,
406 size: head_len,
407 _lifetime: PhantomData,
408 },
409 IoBufferMut {
410 pointer: unsafe { self.pointer.add(head_len) },
412 size: self.size - head_len,
413 _lifetime: PhantomData,
414 },
415 )
416 }
417
418 pub fn into_ref(self) -> IoBufferRef<'a> {
420 IoBufferRef {
421 pointer: self.pointer,
422 size: self.size,
423 _lifetime: PhantomData,
424 }
425 }
426}
427
428impl<'a> IoBufferRefTrait<'a> for IoBufferMut<'a> {
429 type SliceType<T: Copy + Sized + 'a> = &'a mut [T];
430 type PointerType<T: Copy + Sized + 'a> = *mut T;
431
432 passthrough_trait_fn! { fn from_slice(slice: Self::SliceType<u8>) -> Self; }
433 passthrough_trait_fn! { fn try_into_owned(self, alignment: usize) -> io::Result<IoBuffer>; }
434 passthrough_trait_fn! { fn len(&self) -> usize; }
435 passthrough_trait_fn! { fn as_ptr(&self) -> Self::PointerType<u8>; }
436 passthrough_trait_fn! { fn split_at(self, mid: usize) -> (Self, Self); }
437 passthrough_trait_fn! { fn into_ref(self) -> IoBufferRef<'a>; }
438
439 unsafe fn into_typed_slice<T: Copy + Sized>(self) -> Self::SliceType<T> {
440 unsafe { Self::into_typed_slice(self) }
442 }
443}
444
445impl<'a, T: Sized> From<&'a mut [T]> for IoBufferMut<'a> {
446 fn from(slice: &'a mut [T]) -> Self {
447 IoBufferMut {
448 pointer: slice.as_mut_ptr() as *mut u8,
449 size: size_of_val(slice),
450 _lifetime: PhantomData,
451 }
452 }
453}
454
455impl<'a> From<IoSliceMut<'a>> for IoBufferMut<'a> {
456 fn from(mut slice: IoSliceMut<'a>) -> Self {
457 IoBufferMut {
458 pointer: slice.as_mut_ptr(),
459 size: slice.len(),
460 _lifetime: PhantomData,
461 }
462 }
463}
464
465impl<'a> From<IoBufferMut<'a>> for IoSliceMut<'a> {
466 fn from(buf: IoBufferMut<'a>) -> Self {
467 IoSliceMut::new(buf.into_slice())
468 }
469}
470
471#[allow(dead_code)]
473pub(crate) trait IoVectorTrait: Sized {
474 type SliceType;
476
477 type BufferType;
479
480 fn new() -> Self;
482
483 fn with_capacity(cap: usize) -> Self;
487
488 fn push(&mut self, slice: Self::SliceType);
490
491 fn push_ioslice(&mut self, ioslice: Self::BufferType);
493
494 fn insert(&mut self, index: usize, slice: Self::SliceType);
496
497 fn len(&self) -> u64;
499
500 fn buffer_count(&self) -> usize;
502
503 fn is_empty(&self) -> bool {
507 debug_assert!((self.len() == 0) == (self.buffer_count() == 0));
508 self.len() == 0
509 }
510
511 fn append(&mut self, other: Self);
513
514 fn split_at(self, mid: u64) -> (Self, Self);
519
520 fn split_tail_at(self, mid: u64) -> Self;
525
526 fn copy_into_slice(&self, slice: &mut [u8]);
530
531 fn try_into_owned(self, alignment: usize) -> io::Result<IoBuffer>;
533
534 #[cfg(unix)]
540 unsafe fn as_iovec<'a>(&'a self) -> &'a [libc::iovec]
541 where
542 Self: 'a;
543
544 fn is_aligned(&self, mem_alignment: usize, req_alignment: usize) -> bool;
549
550 fn into_inner(self) -> Vec<Self::BufferType>;
552}
553
554macro_rules! impl_io_vector {
556 ($type:tt, $inner_type:tt, $buffer_type:tt, $slice_type:ty, $slice_type_lifetime_b:ty) => {
557 pub struct $type<'a> {
559 vector: Vec<$inner_type<'a>>,
561
562 total_size: u64,
564 }
565
566 impl<'a> $type<'a> {
567 pub fn new() -> Self {
569 Self::default()
570 }
571
572 pub fn with_capacity(cap: usize) -> Self {
576 $type {
577 vector: Vec::with_capacity(cap),
578 total_size: 0,
579 }
580 }
581
582 pub fn push(&mut self, slice: $slice_type) {
584 debug_assert!(!slice.is_empty());
585 self.total_size += slice.len() as u64;
586 self.vector.push($inner_type::new(slice));
587 }
588
589 pub fn push_ioslice(&mut self, ioslice: $inner_type<'a>) {
591 debug_assert!(!ioslice.is_empty());
592 self.total_size += ioslice.len() as u64;
593 self.vector.push(ioslice);
594 }
595
596 pub fn insert(&mut self, index: usize, slice: $slice_type) {
598 debug_assert!(!slice.is_empty());
599 self.total_size += slice.len() as u64;
600 self.vector.insert(index, $inner_type::new(slice));
601 }
602
603 pub fn len(&self) -> u64 {
605 self.total_size
606 }
607
608 pub fn buffer_count(&self) -> usize {
610 self.vector.len()
611 }
612
613 pub fn is_empty(&self) -> bool {
617 debug_assert!((self.len() == 0) == (self.buffer_count() == 0));
618 self.len() == 0
619 }
620
621 pub fn append(&mut self, mut other: Self) {
623 self.total_size += other.total_size;
624 self.vector.append(&mut other.vector);
625 }
626
627 pub fn split_at(self, mid: u64) -> (Self, Self) {
632 let (head, tail) = self.do_split_at(mid, true);
633 (head.unwrap(), tail)
634 }
635
636 pub fn split_tail_at(self, mid: u64) -> Self {
641 self.do_split_at(mid, false).1
642 }
643
644 pub fn copy_into_slice(&self, slice: &mut [u8]) {
648 if slice.len() as u64 != self.total_size {
649 panic!("IoVectorTrait::copy_into_slice() called on a slice of different length from the vector");
650 }
651
652 assert!(self.total_size <= usize::MAX as u64);
653
654 let mut offset = 0usize;
655 for elem in self.vector.iter() {
656 let next_offset = offset + elem.len();
657 slice[offset..next_offset].copy_from_slice(&elem[..]);
658 offset = next_offset;
659 }
660 }
661
662 pub fn try_into_owned(self, alignment: usize) -> io::Result<IoBuffer> {
664 let size = self.total_size.try_into().map_err(|_| {
665 io::Error::other(format!("Buffer is too big ({})", self.total_size))
666 })?;
667 let mut new_buf = IoBuffer::new(size, alignment)?;
668 self.copy_into_slice(new_buf.as_mut().into_slice());
669 Ok(new_buf)
670 }
671
672 #[cfg(unix)]
678 pub unsafe fn as_iovec<'b>(&'b self) -> &'b [libc::iovec] where Self: 'b {
679 unsafe {
682 mem::transmute::<&'b [$inner_type<'b>], &'b [libc::iovec]>(&self.vector[..])
683 }
684 }
685
686 pub fn is_aligned(&self, mem_alignment: usize, req_alignment: usize) -> bool {
692 if mem_alignment == 1 && req_alignment == 1 {
694 return true;
695 }
696
697 debug_assert!(mem_alignment.is_power_of_two() && req_alignment.is_power_of_two());
698 let base_align_mask = mem_alignment - 1;
699 let len_align_mask = base_align_mask | (req_alignment - 1);
700
701 self.vector.iter().all(|buf| {
702 buf.as_ptr() as usize & base_align_mask == 0 &&
703 buf.len() & len_align_mask == 0
704 })
705 }
706
707 pub fn into_inner(self) -> Vec<$inner_type<'a>> {
709 self.vector
710 }
711
712 pub fn with_pushed<'b>(self, slice: $slice_type_lifetime_b) -> $type<'b>
717 where
718 'a: 'b,
719 {
720 let mut vec: $type<'b> = self;
721 vec.push(slice);
722 vec
723 }
724
725 pub fn with_inserted<'b>(self, index: usize, slice: $slice_type_lifetime_b) -> $type<'b>
730 where
731 'a: 'b,
732 {
733 let mut vec: $type<'b> = self;
734 vec.insert(index, slice);
735 vec
736 }
737
738 fn do_split_at(mut self, mid: u64, keep_head: bool) -> (Option<$type<'a>>, $type<'a>) {
743 if mid >= self.total_size {
744 return (
746 keep_head.then_some(self),
747 $type {
748 vector: Vec::new(),
749 total_size: 0,
750 },
751 );
752 }
753
754 let mut i = 0; let mut offset = 0u64; let (vec_head, vec_tail) = loop {
757 if offset == mid {
758 if keep_head {
760 let mut vec_head = self.vector;
761 let vec_tail = vec_head.split_off(i);
762 break (Some(vec_head), vec_tail);
763 } else {
764 break (None, self.vector.split_off(i));
765 }
766 }
767
768 let post_elm_offset = offset + self.vector[i].len() as u64;
769
770 if post_elm_offset > mid {
771 let mut vec_head = self.vector;
774 let mut tail_iter = vec_head.drain(i..);
775
776 let mid_elm = tail_iter.next().unwrap();
778 let mid_elm: $buffer_type<'a> = mid_elm.into();
779
780 let mid_elm_head_len: usize = (mid - offset).try_into().unwrap();
782 let (mid_head, mid_tail) = mid_elm.split_at(mid_elm_head_len);
783
784 let mut vec_tail: Vec<$inner_type<'a>> = vec![mid_tail.into()];
785 vec_tail.extend(tail_iter);
786
787 if keep_head {
788 vec_head.push(mid_head.into());
789 break (Some(vec_head), vec_tail);
790 } else {
791 break (None, vec_tail);
792 }
793 }
794
795 offset = post_elm_offset;
796
797 i += 1;
798 assert!(i < self.vector.len());
801 };
802
803 let head = keep_head.then(|| $type {
804 vector: vec_head.unwrap(),
805 total_size: mid,
806 });
807 let tail = $type {
808 vector: vec_tail,
809 total_size: self.total_size - mid,
810 };
811
812 (head, tail)
813 }
814 }
815
816 impl<'a> IoVectorTrait for $type<'a> {
817 type SliceType = $slice_type;
818 type BufferType = $inner_type<'a>;
819
820 passthrough_trait_fn! { fn new() -> Self; }
821 passthrough_trait_fn! { fn with_capacity(cap: usize) -> Self; }
822 passthrough_trait_fn! { fn push(&mut self, slice: Self::SliceType); }
823 passthrough_trait_fn! { fn push_ioslice(&mut self, ioslice: Self::BufferType); }
824 passthrough_trait_fn! { fn insert(&mut self, index: usize, slice: Self::SliceType); }
825 passthrough_trait_fn! { fn len(&self) -> u64; }
826 passthrough_trait_fn! { fn buffer_count(&self) -> usize; }
827 passthrough_trait_fn! { fn append(&mut self, other: Self); }
828 passthrough_trait_fn! { fn split_at(self, mid: u64) -> (Self, Self); }
829 passthrough_trait_fn! { fn split_tail_at(self, mid: u64) -> Self; }
830 passthrough_trait_fn! { fn copy_into_slice(&self, slice: &mut [u8]); }
831 passthrough_trait_fn! { fn try_into_owned(self, alignment: usize) -> io::Result<IoBuffer>; }
832 passthrough_trait_fn! { fn is_aligned(&self, mem_alignment: usize, req_alignment: usize) -> bool; }
833 passthrough_trait_fn! { fn into_inner(self) -> Vec<Self::BufferType>; }
834
835 #[cfg(unix)]
836 unsafe fn as_iovec<'b>(&'b self) -> &'b [libc::iovec]
837 where
838 Self: 'b
839 {
840 unsafe { Self::as_iovec(self) }
842 }
843 }
844
845 impl<'a> From<Vec<$inner_type<'a>>> for $type<'a> {
846 fn from(vector: Vec<$inner_type<'a>>) -> Self {
847 let total_size = vector
848 .iter()
849 .map(|e| e.len())
850 .fold(0u64, |sum, e| sum + e as u64);
851
852 $type { vector, total_size }
853 }
854 }
855
856 impl<'a> From<$buffer_type<'a>> for $type<'a> {
857 fn from(buffer: $buffer_type<'a>) -> Self {
858 let total_size = buffer.len() as u64;
859 if total_size > 0 {
860 $type {
861 vector: vec![buffer.into()],
862 total_size,
863 }
864 } else {
865 $type {
866 vector: Vec::new(),
867 total_size: 0,
868 }
869 }
870 }
871 }
872
873 impl<'a> From<$slice_type> for $type<'a> {
874 fn from(slice: $slice_type) -> Self {
875 let total_size = slice.len() as u64;
876 if total_size > 0 {
877 $type {
878 vector: vec![$inner_type::new(slice)],
879 total_size,
880 }
881 } else {
882 $type {
883 vector: Vec::new(),
884 total_size: 0,
885 }
886 }
887 }
888 }
889
890 impl<'a> Default for $type<'a> {
891 fn default() -> Self {
892 $type {
893 vector: Vec::new(),
894 total_size: 0,
895 }
896 }
897 }
898
899 impl Debug for $type<'_> {
900 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
901 f.debug_struct(std::stringify!($type))
902 .field("vector.len()", &self.vector.len())
903 .field("total_size", &self.total_size)
904 .finish()
905 }
906 }
907 };
908}
909
910impl_io_vector!(IoVector, IoSlice, IoBufferRef, &'a [u8], &'b [u8]);
911impl_io_vector!(
912 IoVectorMut,
913 IoSliceMut,
914 IoBufferMut,
915 &'a mut [u8],
916 &'b mut [u8]
917);
918
919#[cfg(feature = "vm-memory")]
920impl<'a> IoVector<'a> {
921 pub fn from_volatile_slice_one<B: vm_memory::bitmap::BitmapSlice>(
925 slice: &'a vm_memory::VolatileSlice<'a, B>,
926 ) -> (
927 Self,
928 VolatileSliceGuard<'a, vm_memory::volatile_memory::PtrGuard, B>,
929 ) {
930 Self::from_volatile_slice(std::iter::once(slice))
931 }
932
933 pub fn from_volatile_slice<
938 B: vm_memory::bitmap::BitmapSlice,
939 I: IntoIterator<
940 Item: ImagoAsRef<'a, vm_memory::VolatileSlice<'a, B>>,
941 IntoIter: ExactSizeIterator,
942 >,
943 >(
944 slices: I,
945 ) -> (
946 Self,
947 VolatileSliceGuard<'a, vm_memory::volatile_memory::PtrGuard, B>,
948 ) {
949 let ptr_guards =
950 OneOrMany::from_exact_iter(slices.into_iter().map(|slice| slice.as_ref().ptr_guard()));
951 let buffers = ptr_guards
952 .as_slice()
953 .iter()
954 .map(|pg| {
955 let slice = if pg.len() == 0 {
956 &[]
957 } else {
958 unsafe { std::slice::from_raw_parts(pg.as_ptr(), pg.len()) }
961 };
962 IoSlice::new(slice)
963 })
964 .collect::<Vec<_>>();
965
966 let vector = IoVector::from(buffers);
967 let guard = VolatileSliceGuard {
968 _ptr_guards: ptr_guards,
969 dirty_on_drop: None,
971 };
972
973 (vector, guard)
974 }
975}
976
977impl IoVectorMut<'_> {
978 pub fn fill(&mut self, value: u8) {
980 for slice in self.vector.iter_mut() {
981 slice.fill(value);
982 }
983 }
984
985 pub fn copy_from_slice(&mut self, slice: &[u8]) {
989 if slice.len() as u64 != self.total_size {
990 panic!("IoVectorMut::copy_from_slice() called on a slice of different length from the vector");
991 }
992
993 assert!(self.total_size <= usize::MAX as u64);
994
995 let mut offset = 0usize;
996 for elem in self.vector.iter_mut() {
997 let next_offset = offset + elem.len();
998 elem.copy_from_slice(&slice[offset..next_offset]);
999 offset = next_offset;
1000 }
1001 }
1002}
1003
1004#[cfg(feature = "vm-memory")]
1005impl<'a> IoVectorMut<'a> {
1006 pub fn from_volatile_slice_one<B: vm_memory::bitmap::BitmapSlice>(
1010 slice: &'a vm_memory::VolatileSlice<'a, B>,
1011 ) -> (
1012 Self,
1013 VolatileSliceGuard<'a, vm_memory::volatile_memory::PtrGuardMut, B>,
1014 ) {
1015 Self::from_volatile_slice(std::iter::once(slice))
1016 }
1017
1018 pub fn from_volatile_slice<
1023 B: vm_memory::bitmap::BitmapSlice,
1024 I: IntoIterator<
1025 Item: ImagoAsRef<'a, vm_memory::VolatileSlice<'a, B>>,
1026 IntoIter: ExactSizeIterator,
1027 >,
1028 >(
1029 slices: I,
1030 ) -> (
1031 Self,
1032 VolatileSliceGuard<'a, vm_memory::volatile_memory::PtrGuardMut, B>,
1033 ) {
1034 let guards = slices.into_iter().map(|slice| {
1035 let slice = slice.as_ref();
1036 (
1037 slice.ptr_guard_mut(),
1038 (slice.bitmap(), slice.len()),
1040 )
1041 });
1042 let (ptr_guards, dirty_on_drop) = OneOrMany::unzip_exact(guards);
1043
1044 let buffers = ptr_guards
1045 .as_slice()
1046 .iter()
1047 .map(|pg| {
1048 let slice = if pg.len() == 0 {
1049 &mut []
1050 } else {
1051 unsafe { std::slice::from_raw_parts_mut(pg.as_ptr(), pg.len()) }
1054 };
1055 IoSliceMut::new(slice)
1056 })
1057 .collect::<Vec<_>>();
1058
1059 let vector = IoVectorMut::from(buffers);
1060 let guard = VolatileSliceGuard {
1061 _ptr_guards: ptr_guards,
1062 dirty_on_drop: Some(dirty_on_drop),
1063 };
1064
1065 (vector, guard)
1066 }
1067}
1068
1069impl<'a> From<&'a Vec<u8>> for IoVector<'a> {
1070 fn from(vec: &'a Vec<u8>) -> Self {
1071 vec.as_slice().into()
1072 }
1073}
1074
1075impl<'a> From<&'a IoBuffer> for IoVector<'a> {
1076 fn from(buf: &'a IoBuffer) -> Self {
1077 buf.as_ref().into_slice().into()
1078 }
1079}
1080
1081impl<'a> From<&'a mut Vec<u8>> for IoVectorMut<'a> {
1082 fn from(vec: &'a mut Vec<u8>) -> Self {
1083 vec.as_mut_slice().into()
1084 }
1085}
1086
1087impl<'a> From<&'a mut IoBuffer> for IoVectorMut<'a> {
1088 fn from(buf: &'a mut IoBuffer) -> Self {
1089 buf.as_mut().into_slice().into()
1090 }
1091}
1092
1093#[cfg(feature = "vm-memory")]
1094enum OneOrMany<T> {
1096 One(T),
1098 Many(Vec<T>),
1100}
1101
1102#[cfg(feature = "vm-memory")]
1103impl<T> OneOrMany<T> {
1104 fn from_exact_iter(mut items: impl ExactSizeIterator<Item = T>) -> Self {
1106 if items.len() == 1 {
1107 Self::One(items.next().unwrap())
1108 } else {
1109 Self::Many(items.collect())
1110 }
1111 }
1112
1113 fn unzip_exact<U>(mut items: impl ExactSizeIterator<Item = (T, U)>) -> (Self, OneOrMany<U>) {
1115 if items.len() == 1 {
1116 let (left, right) = items.next().unwrap();
1117 (Self::One(left), OneOrMany::One(right))
1118 } else {
1119 let (left, right) = items.unzip();
1120 (Self::Many(left), OneOrMany::Many(right))
1121 }
1122 }
1123
1124 fn as_slice(&self) -> &[T] {
1126 match self {
1127 Self::One(item) => std::slice::from_ref(item),
1128 Self::Many(items) => items,
1129 }
1130 }
1131}
1132
1133#[cfg(feature = "vm-memory")]
1141pub struct VolatileSliceGuard<'a, PtrGuardType, BitmapType: vm_memory::bitmap::Bitmap> {
1142 _ptr_guards: OneOrMany<PtrGuardType>,
1144
1145 dirty_on_drop: Option<OneOrMany<(&'a BitmapType, usize)>>,
1150}
1151
1152#[cfg(feature = "vm-memory")]
1153impl<P, B: vm_memory::bitmap::Bitmap> Drop for VolatileSliceGuard<'_, P, B> {
1154 fn drop(&mut self) {
1155 if let Some(dirty_on_drop) = self.dirty_on_drop.take() {
1156 for &(bitmap, len) in dirty_on_drop.as_slice() {
1157 bitmap.mark_dirty(0, len);
1160 }
1161 }
1162 }
1163}
1164
1165#[cfg(all(test, feature = "vm-memory"))]
1166mod vm_memory_test {
1167 use crate::io_buffers::{IoVector, IoVectorMut};
1168 use vm_memory::bitmap::BitmapSlice;
1169 use vm_memory::VolatileSlice;
1170
1171 pub fn do_test_volatile_slice_owned<B: BitmapSlice>(slices: &[VolatileSlice<B>]) {
1172 {
1173 let _vec = IoVector::from_volatile_slice(slices);
1174 }
1175 {
1176 let _vec = IoVectorMut::from_volatile_slice(slices);
1177 }
1178 }
1179
1180 #[test]
1181 fn test_volatile_slice_owned() {
1182 let empty: Vec<VolatileSlice<()>> = Vec::new();
1183 do_test_volatile_slice_owned(&empty);
1184 }
1185
1186 pub fn do_test_volatile_slice_ref<B: BitmapSlice>(slices: &[&VolatileSlice<B>]) {
1187 {
1188 let _vec = IoVector::from_volatile_slice(slices);
1189 }
1190 {
1191 let _vec = IoVectorMut::from_volatile_slice(slices);
1192 }
1193 }
1194
1195 #[test]
1196 fn test_volatile_slice_ref() {
1197 let empty: Vec<&vm_memory::VolatileSlice<()>> = Vec::new();
1198 do_test_volatile_slice_ref(&empty);
1199 }
1200
1201 #[test]
1202 fn test_volatile_slice_one() {
1203 let mut data = [0u8; 4];
1204 {
1205 let slice = VolatileSlice::from(data.as_mut_slice());
1206
1207 let (vector, guard) = IoVector::from_volatile_slice_one(&slice);
1208 let mut copied = [1; 4];
1209 vector.copy_into_slice(&mut copied);
1210 assert_eq!(copied, [0; 4]);
1211 drop(vector);
1212 drop(guard);
1213
1214 let (mut vector, guard) = IoVectorMut::from_volatile_slice_one(&slice);
1215 vector.fill(1);
1216 drop(vector);
1217 drop(guard);
1218 }
1219 assert_eq!(data, [1; 4]);
1220 }
1221}