vest_lib/asn1/
printablestring.rs1use super::utf8string::{is_valid_utf8, utf8_from_bytes_unchecked};
3use crate::core::exec::input::{InputBuf, InputSlice};
4use crate::core::exec::output::*;
5use crate::core::exec::{
6 parser::{PResult, Parser},
7 serializer::{ByteLen, PreSerializeError, Prepare, Serializer},
8 ParseError,
9};
10use crate::{
11 combinators::{mapped::spec::FnSpecMapper, Mapped, Refined, Tail},
12 core::{proof::*, spec::*},
13};
14#[cfg(feature = "alloc")]
15use alloc::string::String;
16use vstd::prelude::*;
17use vstd::string::StringSliceAdditionalSpecFns;
18use OutputBuf;
19
20verus! {
21
22pub struct PrintableString<'a> {
23 inner: &'a str,
24}
25
26#[cfg(feature = "alloc")]
29pub struct PrintableStringOwned {
30 inner: String,
31}
32
33#[verifier::ext_equal]
34pub struct PrintableStringSpec {
35 pub inner: Seq<char>,
36}
37
38impl<'a> DeepView for PrintableString<'a> {
39 type V = PrintableStringSpec;
40
41 closed spec fn deep_view(&self) -> Self::V {
42 PrintableStringSpec { inner: self.inner.deep_view() }
43 }
44}
45
46#[cfg(feature = "alloc")]
47impl DeepView for PrintableStringOwned {
48 type V = PrintableStringSpec;
49
50 closed spec fn deep_view(&self) -> Self::V {
51 PrintableStringSpec { inner: self.inner.deep_view() }
52 }
53}
54
55impl<'a> PrintableString<'a> {
56 #[verifier::type_invariant]
57 spec fn wf(&self) -> bool {
58 self.deep_view().wf()
59 }
60
61 pub fn new(inner: &'a str) -> (res: Self)
62 requires
63 is_valid_printable_string_spec(vstd::utf8::encode_utf8(inner.deep_view())),
64 ensures
65 res.deep_view() == (PrintableStringSpec { inner: inner.deep_view() }),
66 {
67 PrintableString { inner }
68 }
69
70 pub fn inner(&self) -> (res: &'a str)
71 ensures
72 res.deep_view() == self.deep_view().inner,
73 {
74 self.inner
75 }
76}
77
78#[cfg(feature = "alloc")]
79impl PrintableStringOwned {
80 #[verifier::type_invariant]
81 spec fn wf(&self) -> bool {
82 self.deep_view().wf()
83 }
84
85 pub fn new(inner: String) -> (res: Self)
86 requires
87 is_valid_printable_string_spec(vstd::utf8::encode_utf8(inner.deep_view())),
88 ensures
89 res.deep_view() == (PrintableStringSpec { inner: inner.deep_view() }),
90 {
91 Self { inner }
92 }
93
94 pub fn inner(&self) -> (res: &str)
95 ensures
96 res.deep_view() == self.deep_view().inner,
97 {
98 self.inner.as_str()
99 }
100}
101
102impl PrintableStringSpec {
103 pub open spec fn wf(&self) -> bool {
104 is_valid_printable_string_spec(vstd::utf8::encode_utf8(self.inner))
105 }
106}
107
108#[verifier::allow_in_spec]
110pub fn is_printable_byte(b: u8) -> bool
111 returns
112 matches!(b, b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9'
113 | b' ' | b'\'' | b'(' | b')' | b'+' | b',' | b'-' | b'.' | b'/'
114 | b':' | b'=' | b'?'),
115{
116 matches!(b, b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9'
117 | b' ' | b'\'' | b'(' | b')' | b'+' | b',' | b'-' | b'.' | b'/'
118 | b':' | b'=' | b'?')
119}
120
121pub open spec fn is_valid_printable_string_spec(bytes: Seq<u8>) -> bool {
122 forall|i: int| 0 <= i < bytes.len() ==> is_printable_byte(#[trigger] bytes[i])
123}
124
125#[verifier::allow_in_spec]
127pub fn is_valid_printable_string(bytes: &[u8]) -> (res: bool)
128 returns
129 is_valid_printable_string_spec(bytes.deep_view()),
130{
131 assert(bytes@ == bytes.deep_view());
132 bytes.iter().all(
133 |&b: &u8| -> (valid: bool)
134 ensures
135 valid == is_printable_byte(b),
136 { is_printable_byte(b) },
137 )
138}
139
140type PrintableStringFmt = Mapped<
141 Refined<Tail, PredFnSpec<Seq<u8>>>,
142 FnSpecMapper<Seq<u8>, PrintableStringSpec>,
143>;
144
145pub open spec fn printablestring_fmt() -> PrintableStringFmt {
146 Mapped {
147 inner: Refined(
148 Tail,
149 |bytes: Seq<u8>| is_valid_printable_string_spec(bytes) && vstd::utf8::valid_utf8(bytes),
150 ),
151 mapper: (
152 |bytes: Seq<u8>| PrintableStringSpec { inner: vstd::utf8::decode_utf8(bytes) },
153 |s: PrintableStringSpec| vstd::utf8::encode_utf8(s.inner),
154 ),
155 }
156}
157
158mod derived_specs {
159 use super::*;
160
161 impl SpecParser for super::super::PrintableStringFmt {
162 type PVal = PrintableStringSpec;
163
164 open spec fn spec_parse(&self, ibuf: Seq<u8>) -> Option<(int, Self::PVal)> {
165 printablestring_fmt().spec_parse(ibuf)
166 }
167 }
168
169 impl Consistency for super::super::PrintableStringFmt {
170 type Val = PrintableStringSpec;
171
172 open spec fn consistent(&self, v: Self::Val) -> bool {
173 printablestring_fmt().consistent(v)
174 }
175 }
176
177 impl SpecSerializerDps for super::super::PrintableStringFmt {
178 type SValue = PrintableStringSpec;
179
180 open spec fn spec_serialize_dps(&self, v: Self::SValue, obuf: Seq<u8>) -> Seq<u8> {
181 printablestring_fmt().spec_serialize_dps(v, obuf)
182 }
183 }
184
185 impl SpecSerializer for super::super::PrintableStringFmt {
186 type SVal = PrintableStringSpec;
187
188 open spec fn spec_serialize(&self, v: Self::SVal) -> Seq<u8> {
189 printablestring_fmt().spec_serialize(v)
190 }
191 }
192
193 impl SpecByteLen for super::super::PrintableStringFmt {
194 type T = PrintableStringSpec;
195
196 open spec fn byte_len(&self, v: Self::T) -> nat {
197 printablestring_fmt().byte_len(v)
198 }
199 }
200
201}
202
203mod derived_proofs {
204 use super::*;
205
206 impl SafeParser for super::super::PrintableStringFmt {
207 proof fn lemma_parse_safe(&self, ibuf: Seq<u8>) {
208 printablestring_fmt().lemma_parse_safe(ibuf);
209 }
210 }
211
212 impl Productive for super::super::PrintableStringFmt {
213 open spec fn productive_inv(&self) -> bool {
214 false
215 }
216
217 proof fn lemma_productive(&self, s: Seq<u8>) {
218 }
219 }
220
221 impl SoundParser for super::super::PrintableStringFmt {
222 proof fn lemma_parse_sound_consumption(&self, ibuf: Seq<u8>) {
223 broadcast use vstd::utf8::decode_utf8_encode_utf8;
224
225 printablestring_fmt().lemma_parse_sound_consumption(ibuf);
226 }
227
228 proof fn lemma_parse_sound_value(&self, ibuf: Seq<u8>) {
229 broadcast use vstd::utf8::decode_utf8_encode_utf8;
230
231 printablestring_fmt().lemma_parse_sound_value(ibuf);
232 }
233 }
234
235 impl GoodSerializer for super::super::PrintableStringFmt {
236 proof fn lemma_serialize_len(&self, v: Self::SVal) {
237 printablestring_fmt().lemma_serialize_len(v);
238 }
239 }
240
241 impl SPRoundTripDps for super::super::PrintableStringFmt {
242 proof fn theorem_serialize_dps_parse_roundtrip(&self, v: Self::T, obuf: Seq<u8>) {
243 broadcast use vstd::utf8::encode_utf8_decode_utf8;
244
245 printablestring_fmt().theorem_serialize_dps_parse_roundtrip(v, obuf);
246 }
247 }
248
249 impl NonMalleable for super::super::PrintableStringFmt {
250 proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
251 broadcast use vstd::utf8::decode_utf8_encode_utf8;
252
253 printablestring_fmt().lemma_parse_non_malleable(buf1, buf2);
254 }
255 }
256
257 impl EquivSerializers for super::super::PrintableStringFmt {
258 proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
259 printablestring_fmt().lemma_serialize_equiv_on_empty(v);
260 }
261 }
262
263}
264
265impl<'i> Parser<&'i [u8]> for super::PrintableStringFmt {
266 type PT = PrintableString<'i>;
267
268 fn parse(&self, ibuf: &&'i [u8]) -> PResult<Self::PT> {
269 let (n, bytes) = Tail.parse(ibuf)?;
270 if !is_valid_printable_string(bytes) {
271 Err(ParseError::custom("Invalid PrintableString"))
272 } else if !is_valid_utf8(bytes) {
273 Err(ParseError::custom("Invalid UTF-8"))
274 } else {
275 let inner = utf8_from_bytes_unchecked(bytes);
276 Ok((n, PrintableString::new(inner)))
277 }
278 }
279}
280
281impl<Output: OutputBuf, 'i> Serializer<Output, PrintableString<'i>> for super::PrintableStringFmt {
282 fn serialize_into(&self, v: &PrintableString<'i>, obuf: &mut Output) {
283 proof {
284 use_type_invariant(v);
285 }
286 let bytes = v.inner.as_bytes();
287 Tail.serialize_into(&bytes, obuf);
288 }
289}
290
291impl<'i> Prepare<PrintableString<'i>> for super::PrintableStringFmt {
292 fn prepare(&self, v: &PrintableString<'i>) -> Result<usize, PreSerializeError> {
293 broadcast use vstd::utf8::encode_utf8_valid_utf8;
294
295 proof {
296 use_type_invariant(v);
297 }
298 let bytes = v.inner.as_bytes();
299 Tail.prepare(&bytes)
300 }
301}
302
303impl<'i> ByteLen<PrintableString<'i>> for super::PrintableStringFmt {
304 fn length(&self, v: &PrintableString<'i>) -> usize {
305 proof {
306 use_type_invariant(v);
307 }
308 let bytes = v.inner.as_bytes();
309 Tail.length(&bytes)
310 }
311}
312
313#[cfg(feature = "alloc")]
314impl<Output: OutputBuf> Serializer<Output, PrintableStringOwned> for super::PrintableStringFmt {
315 fn serialize_into(&self, v: &PrintableStringOwned, obuf: &mut Output) {
316 proof {
317 use_type_invariant(v);
318 }
319 let bytes = v.inner.as_str().as_bytes();
320 Tail.serialize_into(&bytes, obuf);
321 }
322}
323
324#[cfg(feature = "alloc")]
325impl Prepare<PrintableStringOwned> for super::PrintableStringFmt {
326 fn prepare(&self, v: &PrintableStringOwned) -> Result<usize, PreSerializeError> {
327 broadcast use vstd::utf8::encode_utf8_valid_utf8;
328
329 proof {
330 use_type_invariant(v);
331 }
332 let bytes = v.inner.as_str().as_bytes();
333 Tail.prepare(&bytes)
334 }
335}
336
337#[cfg(feature = "alloc")]
338impl ByteLen<PrintableStringOwned> for super::PrintableStringFmt {
339 fn length(&self, v: &PrintableStringOwned) -> usize {
340 proof {
341 use_type_invariant(v);
342 }
343 let bytes = v.inner.as_str().as_bytes();
344 Tail.length(&bytes)
345 }
346}
347
348}