vest_lib/core/exec/
output.rs1#[cfg(feature = "alloc")]
3use alloc::vec::Vec;
4use vstd::prelude::*;
5
6verus! {
7
8pub trait OutputBuf: View<V = Seq<u8>> {
13 spec fn fits(&self, len: nat) -> bool;
15
16 broadcast proof fn lemma_fits_mono(&self, shorter: nat, longer: nat)
18 requires
19 shorter <= longer,
20 self.fits(longer),
21 ensures
22 #![all_triggers]
23 self.fits(shorter),
24 ;
25
26 #[verifier::prophetic]
31 spec fn same_destination(&self, other: &Self) -> bool;
32
33 broadcast proof fn lemma_same_destination_reflexive(&self)
35 ensures
36 #[trigger] self.same_destination(self),
37 ;
38
39 broadcast proof fn lemma_same_destination_transitive(&self, middle: &Self, last: &Self)
41 requires
42 self.same_destination(middle),
43 middle.same_destination(last),
44 ensures
45 #![all_triggers]
46 self.same_destination(last),
47 ;
48
49 fn write_byte(&mut self, byte: u8)
51 requires
52 old(self).fits(1),
53 ensures
54 final(self)@ == old(self)@.push(byte),
55 forall|n| old(self).fits(1 + n) <==> #[trigger] final(self).fits(n),
56 old(self).same_destination(final(self)),
57 ;
58
59 fn write_bytes(&mut self, bytes: &[u8])
61 requires
62 old(self).fits(bytes@.len()),
63 ensures
64 final(self)@ == old(self)@ + bytes@,
65 forall|n| old(self).fits(bytes@.len() + n) <==> #[trigger] final(self).fits(n),
66 old(self).same_destination(final(self)),
67 {
68 broadcast use OutputBuf::lemma_same_destination_reflexive;
69
70 let ghost initial_view = self@;
71 for i in 0..bytes.len()
72 invariant
73 self@ == initial_view + bytes@.take(i as int),
74 old(self).fits(bytes@.len()),
75 forall|n| old(self).fits(i as nat + n) <==> #[trigger] self.fits(n),
76 old(self).same_destination(self),
77 {
78 broadcast use OutputBuf::lemma_same_destination_transitive;
79
80 proof {
81 old(self).lemma_fits_mono(i as nat + 1, bytes@.len());
82 assert(self.fits(1));
83 }
84 self.write_byte(bytes[i]);
85 }
86 }
87}
88
89pub struct OutputSlice<'a> {
93 pub obuf: &'a mut [u8],
94 pub pos: usize,
95}
96
97impl View for OutputSlice<'_> {
98 type V = Seq<u8>;
99
100 open spec fn view(&self) -> Self::V {
101 self.obuf@.take(self.pos as int)
102 }
103}
104
105impl<'a> OutputSlice<'a> {
106 #[verifier::prophetic]
108 pub open spec fn final_destination(&self) -> Seq<u8> {
109 final(self.obuf)@
110 }
111
112 pub fn new(obuf: &'a mut [u8]) -> (output: Self)
114 ensures
115 output@ == Seq::empty(),
116 output.fits(old(obuf)@.len()),
117 forall|len: nat| #[trigger] output.fits(len) == (len <= old(obuf)@.len()),
118 output.final_destination() == final(obuf)@,
119 {
120 Self { obuf, pos: 0 }
121 }
122}
123
124impl OutputBuf for OutputSlice<'_> {
125 open spec fn fits(&self, len: nat) -> bool {
126 self.pos as nat + len <= self.obuf@.len()
127 }
128
129 proof fn lemma_fits_mono(&self, shorter: nat, longer: nat) {
130 }
131
132 #[verifier::prophetic]
133 open spec fn same_destination(&self, other: &Self) -> bool {
134 self.final_destination() == other.final_destination()
135 }
136
137 proof fn lemma_same_destination_reflexive(&self) {
138 }
139
140 proof fn lemma_same_destination_transitive(&self, _middle: &Self, _last: &Self) {
141 }
142
143 fn write_byte(&mut self, byte: u8) {
144 assert(self.pos < self.obuf.len());
145 self.obuf[self.pos] = byte;
146 self.pos += 1;
147 }
148
149 fn write_bytes(&mut self, bytes: &[u8]) {
150 let ghost old_view = self@;
151 let old_pos = self.pos;
152 let len = bytes.len();
153 assert(old_pos + len <= self.obuf.len());
154 {
155 let (_prefix, rest) = self.obuf.split_at_mut(old_pos);
156 let (destination, _suffix) = rest.split_at_mut(len);
157 destination.copy_from_slice(bytes);
158 }
159 self.pos = old_pos + len;
160 assert(self@ == old_view + bytes@);
161 }
162}
163
164#[cfg(feature = "alloc")]
165impl OutputBuf for Vec<u8> {
166 open spec fn fits(&self, _len: nat) -> bool {
167 true
168 }
169
170 proof fn lemma_fits_mono(&self, _shorter: nat, _longer: nat) {
171 }
172
173 #[verifier::prophetic]
174 open spec fn same_destination(&self, _other: &Self) -> bool {
175 true
176 }
177
178 proof fn lemma_same_destination_reflexive(&self) {
179 }
180
181 proof fn lemma_same_destination_transitive(&self, _middle: &Self, _last: &Self) {
182 }
183
184 fn write_byte(&mut self, byte: u8) {
185 self.push(byte);
186 }
187
188 fn write_bytes(&mut self, bytes: &[u8]) {
189 self.extend_from_slice(bytes);
190 }
191}
192
193pub broadcast group outbuf_lemmas {
194 OutputBuf::lemma_fits_mono,
195 OutputBuf::lemma_same_destination_reflexive,
196 OutputBuf::lemma_same_destination_transitive,
197}
198
199}