verdict_parser/asn1/
printable_string.rs1use super::*;
2use std::fmt::{self, Debug, Formatter};
4use vstd::prelude::*;
5
6verus! {
7
8#[derive(Debug, View)]
12pub struct PrintableString;
13
14asn1_tagged!(PrintableString, tag_of!(PRINTABLE_STRING));
15
16pub type SpecPrintableStringValue = Seq<char>;
17pub type PrintableStringValue<'a> = &'a str;
18pub type PrintableStringValueOwned = String;
19
20impl SpecCombinator for PrintableString {
21 type SpecResult = SpecPrintableStringValue;
22
23 closed spec fn spec_parse(&self, s: Seq<u8>) -> Result<(usize, Self::SpecResult), ()> {
24 Refined {
25 inner: UTF8String,
26 predicate: PrintableStringPred,
27 }.spec_parse(s)
28 }
29
30 proof fn spec_parse_wf(&self, s: Seq<u8>) {
31 Refined {
32 inner: UTF8String,
33 predicate: PrintableStringPred,
34 }.spec_parse_wf(s)
35 }
36
37 closed spec fn spec_serialize(&self, v: Self::SpecResult) -> Result<Seq<u8>, ()> {
38 Refined {
39 inner: UTF8String,
40 predicate: PrintableStringPred,
41 }.spec_serialize(v)
42 }
43}
44
45impl SecureSpecCombinator for PrintableString {
46 open spec fn is_prefix_secure() -> bool {
47 true
48 }
49
50 proof fn theorem_serialize_parse_roundtrip(&self, v: Self::SpecResult) {
51 Refined {
52 inner: UTF8String,
53 predicate: PrintableStringPred,
54 }.theorem_serialize_parse_roundtrip(v);
55 }
56
57 proof fn theorem_parse_serialize_roundtrip(&self, buf: Seq<u8>) {
58 Refined {
59 inner: UTF8String,
60 predicate: PrintableStringPred,
61 }.theorem_parse_serialize_roundtrip(buf);
62 }
63
64 proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
65 Refined {
66 inner: UTF8String,
67 predicate: PrintableStringPred,
68 }.lemma_prefix_secure(s1, s2);
69 }
70}
71
72impl Combinator for PrintableString {
73 type Result<'a> = PrintableStringValue<'a>;
74 type Owned = PrintableStringValueOwned;
75
76 closed spec fn spec_length(&self) -> Option<usize> {
77 None
78 }
79
80 fn length(&self) -> Option<usize> {
81 None
82 }
83
84 #[inline(always)]
85 fn parse<'a>(&self, s: &'a [u8]) -> (res: Result<(usize, Self::Result<'a>), ParseError>) {
86 Refined {
87 inner: UTF8String,
88 predicate: PrintableStringPred,
89 }.parse(s)
90 }
91
92 #[inline(always)]
93 fn serialize(&self, v: Self::Result<'_>, data: &mut Vec<u8>, pos: usize) -> (res: Result<usize, SerializeError>) {
94 Refined {
95 inner: UTF8String,
96 predicate: PrintableStringPred,
97 }.serialize(v, data, pos)
98 }
99}
100
101#[derive(View)]
103pub struct PrintableStringPred;
104
105impl PrintableStringPred {
106 closed spec fn wf_char(c: char) -> bool {
107 ||| ('A' <= c && c <= 'Z')
109 ||| ('a' <= c && c <= 'z')
110 ||| ('0' <= c && c <= '9')
111 ||| c == ' '
112 ||| ('\'' <= c && c <= ')')
113 ||| ('+' <= c && c <= '/')
114 ||| c == ':'
115 ||| c == '='
116 ||| c == '?'
117 }
118
119 #[inline(always)]
120 fn exec_wf_char(c: char) -> (res: bool)
121 ensures res == Self::wf_char(c)
122 {
123 ('A' <= c && c <= 'Z') ||
124 ('a' <= c && c <= 'z') ||
125 ('0' <= c && c <= '9') ||
126 c == ' ' ||
127 ('\'' <= c && c <= ')') ||
128 ('+' <= c && c <= '/') ||
129 c == ':' ||
130 c == '=' ||
131 c == '?'
132 }
133}
134
135impl SpecPred for PrintableStringPred {
136 type Input = Seq<char>;
137
138 closed spec fn spec_apply(&self, s: &Self::Input) -> bool {
139 forall |i| 0 <= i < s.len() ==> #[trigger] Self::wf_char(s[i])
140 }
141}
142
143impl Pred for PrintableStringPred {
144 type Input<'a> = &'a str;
145 type InputOwned = String;
146
147 fn apply(&self, s: &Self::Input<'_>) -> (res: bool)
148 {
149 let len = s.unicode_len();
150 for i in 0..len
151 invariant
152 len == s@.len(),
153 forall |j| 0 <= j < i ==> #[trigger] Self::wf_char(s@[j]),
154 {
155 if !Self::exec_wf_char(s.get_char(i)) {
156 return false;
157 }
158 }
159 return true;
160 }
161}
162
163}