1use crate::Wqe;
7use guestmem::AccessError;
8use guestmem::GuestMemory;
9use guestmem::MemoryRead;
10use guestmem::MemoryWrite;
11use std::num::Wrapping;
12
13#[derive(Clone)]
14pub struct WqeAccess<'a> {
15 wqe: &'a Wqe,
16 gm: &'a GuestMemory,
17 sgi: usize,
18 offset: usize,
19 remaining_len: usize,
20}
21
22impl Wqe {
23 pub fn access<'a>(&'a self, gm: &'a GuestMemory) -> WqeAccess<'a> {
24 let remaining_len = if self.header.params.sgl_direct() {
25 self.header.sgl_direct_len()
26 } else {
27 self.sgl()
28 .iter()
29 .map(|sge| Wrapping(sge.size as usize))
30 .sum::<Wrapping<usize>>()
31 .0
32 };
33 WqeAccess {
34 wqe: self,
35 gm,
36 sgi: 0,
37 offset: 0,
38 remaining_len,
39 }
40 }
41}
42
43impl WqeAccess<'_> {
44 fn access(
45 &mut self,
46 mut len: usize,
47 mut f: impl FnMut(usize, Result<u64, usize>) -> Result<(), AccessError>,
48 ) -> Result<&mut Self, AccessError> {
49 if self.wqe.header.params.sgl_direct() {
50 let avail = self.wqe.header.sgl_direct_len() - self.offset;
51 if avail < len {
52 return Err(AccessError::OutOfRange(avail, len));
53 }
54 let offset = self.wqe.header.sgl_offset() + self.offset;
55 f(len, Err(offset))?;
56 self.offset += len;
57 self.remaining_len -= len;
58 } else {
59 while len > 0 {
60 let sge = self.wqe.sgl().get(self.sgi).ok_or_else(|| {
61 AccessError::OutOfRange(
62 self.sgi,
63 self.wqe.header.params.num_sgl_entries().into(),
64 )
65 })?;
66 let gpa = sge.address.wrapping_add(self.offset as u64);
67 let this_len = (sge.size as usize - self.offset).min(len);
68 f(this_len, Ok(gpa))?;
69 self.offset += this_len;
70 self.remaining_len -= this_len;
71 len -= this_len;
72 if sge.size as usize == self.offset {
73 self.offset = 0;
74 self.sgi += 1;
75 }
76 }
77 }
78 Ok(self)
79 }
80}
81
82impl MemoryRead for WqeAccess<'_> {
83 fn read(&mut self, data: &mut [u8]) -> Result<&mut Self, AccessError> {
84 let mut offset = 0;
85 self.access(data.len(), |len, r| {
86 match r {
87 Ok(gpa) => {
88 self.gm
89 .read_at(gpa, &mut data[offset..offset + len])
90 .map_err(AccessError::Memory)?;
91 offset += len;
92 }
93 Err(offset) => {
94 data.copy_from_slice(&self.wqe.data[offset..offset + data.len()]);
95 }
96 }
97 Ok(())
98 })
99 }
100
101 fn skip(&mut self, len: usize) -> Result<&mut Self, AccessError> {
102 self.access(len, |_, _| Ok(()))
103 }
104
105 fn len(&self) -> usize {
106 self.remaining_len
107 }
108}
109
110impl MemoryWrite for WqeAccess<'_> {
111 fn write(&mut self, data: &[u8]) -> Result<(), AccessError> {
112 let mut offset = 0;
113 self.access(data.len(), |len, r| {
114 match r {
115 Ok(gpa) => {
116 self.gm
117 .write_at(gpa, &data[offset..offset + len])
118 .map_err(AccessError::Memory)?;
119 offset += len;
120 }
121 Err(offset) => {
122 return Err(AccessError::OutOfRange(offset, 0));
124 }
125 }
126 Ok(())
127 })?;
128 Ok(())
129 }
130
131 fn fill(&mut self, _val: u8, _len: usize) -> Result<(), AccessError> {
132 unimplemented!()
133 }
134
135 fn len(&self) -> usize {
136 self.remaining_len
137 }
138}