1use core::ops::Range;
8use core::slice::{Chunks, ChunksMut};
9
10use crate::access::{Access, ReadAccess, ReadOnly, WriteAccess, WriteOnly};
11
12pub enum Operation<'a, A: Access> {
13 Read {
14 buf: &'a mut [u8],
15 witness: A::ReadWitness,
16 },
17 Write {
18 buf: &'a [u8],
19 witness: A::WriteWitness,
20 },
21}
22
23#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
24pub enum OperationType {
25 Read,
26 Write,
27}
28
29impl OperationType {
30 pub fn is_read(self) -> bool {
31 self == Self::Read
32 }
33
34 pub fn is_write(self) -> bool {
35 self == Self::Write
36 }
37}
38
39impl<'a, A: Access> Operation<'a, A> {
40 pub fn with_read_access<A1: ReadAccess + Access<WriteWitness = A::WriteWitness>>(
41 &'a mut self,
42 ) -> Operation<'a, A1> {
43 match self {
44 Self::Read { buf, .. } => Operation::Read {
45 buf,
46 witness: A1::READ_WITNESS,
47 },
48 Self::Write { buf, witness } => Operation::Write {
49 buf,
50 witness: *witness,
51 },
52 }
53 }
54
55 pub fn with_write_access<A1: WriteAccess + Access<ReadWitness = A::ReadWitness>>(
56 &'a mut self,
57 ) -> Operation<'a, A1> {
58 match self {
59 Self::Read { buf, witness } => Operation::Read {
60 buf,
61 witness: *witness,
62 },
63 Self::Write { buf, .. } => Operation::Write {
64 buf,
65 witness: A1::WRITE_WITNESS,
66 },
67 }
68 }
69
70 pub fn len(&self) -> usize {
71 match self {
72 Self::Read { buf, .. } => buf.len(),
73 Self::Write { buf, .. } => buf.len(),
74 }
75 }
76
77 pub fn is_empty(&self) -> bool {
78 self.len() == 0
79 }
80
81 pub fn ty(&self) -> OperationType {
82 match self {
83 Self::Read { .. } => OperationType::Read,
84 Self::Write { .. } => OperationType::Write,
85 }
86 }
87
88 pub fn index(&'a mut self, index: Range<usize>) -> Self {
89 match self {
90 Self::Read { buf, witness } => Self::Read {
91 buf: &mut buf[index],
92 witness: *witness,
93 },
94 Self::Write { buf, witness } => Self::Write {
95 buf: &buf[index],
96 witness: *witness,
97 },
98 }
99 }
100
101 pub fn split_at(&'a mut self, mid: usize) -> (Self, Self) {
102 match self {
103 Self::Read { buf, witness } => {
104 let (left, right) = buf.split_at_mut(mid);
105 let left = Self::Read {
106 buf: left,
107 witness: *witness,
108 };
109 let right = Self::Read {
110 buf: right,
111 witness: *witness,
112 };
113 (left, right)
114 }
115 Self::Write { buf, witness } => {
116 let (left, right) = buf.split_at(mid);
117 let left = Self::Write {
118 buf: left,
119 witness: *witness,
120 };
121 let right = Self::Write {
122 buf: right,
123 witness: *witness,
124 };
125 (left, right)
126 }
127 }
128 }
129
130 pub fn chunks(&'a mut self, chunk_size: usize) -> impl Iterator<Item = Operation<'a, A>> {
131 match self {
132 Self::Read { buf, witness } => OperationChunks::Read {
133 it: buf.chunks_mut(chunk_size),
134 witness: *witness,
135 },
136 Self::Write { buf, witness } => OperationChunks::Write {
137 it: buf.chunks(chunk_size),
138 witness: *witness,
139 },
140 }
141 }
142}
143
144enum OperationChunks<'a, A: Access> {
145 Read {
146 it: ChunksMut<'a, u8>,
147 witness: A::ReadWitness,
148 },
149 Write {
150 it: Chunks<'a, u8>,
151 witness: A::WriteWitness,
152 },
153}
154
155impl<'a, A: Access> Iterator for OperationChunks<'a, A> {
156 type Item = Operation<'a, A>;
157
158 fn next(&mut self) -> Option<Operation<'a, A>> {
159 match self {
160 Self::Read { it, witness } => it.next().map(|buf| Operation::Read {
161 buf,
162 witness: *witness,
163 }),
164 Self::Write { it, witness } => it.next().map(|buf| Operation::Write {
165 buf,
166 witness: *witness,
167 }),
168 }
169 }
170}
171
172impl<'a> Operation<'a, ReadOnly> {
173 #[allow(clippy::explicit_auto_deref)]
174 pub fn as_read(&'a mut self) -> &'a mut [u8] {
175 match self {
176 Self::Read { buf, .. } => buf,
177 Self::Write { witness, .. } => witness.absurd(),
178 }
179 }
180}
181
182impl<'a> Operation<'a, WriteOnly> {
183 #[allow(clippy::explicit_auto_deref)]
184 pub fn as_write(&'a self) -> &'a [u8] {
185 match self {
186 Self::Read { witness, .. } => witness.absurd(),
187 Self::Write { buf, .. } => buf,
188 }
189 }
190}
191
192impl<'a, A: ReadAccess> Operation<'a, A> {
193 pub fn read(buf: &'a mut [u8]) -> Self {
194 Self::Read {
195 buf,
196 witness: A::READ_WITNESS,
197 }
198 }
199}
200
201impl<'a, A: WriteAccess> Operation<'a, A> {
202 pub fn write(buf: &'a [u8]) -> Self {
203 Self::Write {
204 buf,
205 witness: A::WRITE_WITNESS,
206 }
207 }
208}