vest_lib/asn1/
utf8string.rs1use crate::core::exec::input::{InputBuf, InputSlice};
3use crate::core::exec::output::*;
4use crate::core::exec::{
5 parser::{PResult, Parser},
6 serializer::{ByteLen, PreSerializeError, Prepare, Serializer},
7 ParseError,
8};
9use crate::{
10 combinators::{mapped::spec::FnSpecMapper, Mapped, Refined, Tail},
11 core::{proof::*, spec::*},
12};
13#[cfg(feature = "alloc")]
14use alloc::{string::String, vec::Vec};
15use vstd::prelude::*;
16use vstd::string::StringSliceAdditionalSpecFns;
17use OutputBuf;
18
19verus! {
20
21pub type Utf8String<'a> = &'a str;
22
23#[cfg(feature = "alloc")]
26pub type Utf8StringOwned = String;
27
28#[verifier::allow_in_spec]
30pub(crate) fn is_unicode_scalar(value: u32) -> bool
31 returns
32 vstd::utf8::is_scalar(value),
33{
34 value <= 0x10ffff && !(0xd800 <= value && value <= 0xdfff)
35}
36
37#[verifier::external_body]
38pub fn is_valid_utf8(bytes: &[u8]) -> (res: bool)
39 ensures
40 res == vstd::utf8::valid_utf8(bytes.deep_view()),
41{
42 str::from_utf8(bytes).is_ok()
43}
44
45pub fn utf8_from_bytes_unchecked<'a>(bytes: &'a [u8]) -> (res: &'a str)
46 requires
47 vstd::utf8::valid_utf8(bytes.deep_view()),
48 ensures
49 res.spec_bytes() == bytes.deep_view(),
50 res.deep_view() == vstd::utf8::decode_utf8(bytes.deep_view()),
51{
52 broadcast use vstd::utf8::decode_utf8_encode_utf8;
53 broadcast use vstd::utf8::encode_utf8_decode_utf8;
54
55 assert(bytes@ == bytes.deep_view());
56 unsafe { str::from_utf8_unchecked(bytes) }
58}
59
60#[cfg(feature = "alloc")]
63pub assume_specification[ String::from_utf8_unchecked ](bytes: Vec<u8>) -> (res: String)
64 requires
65 vstd::utf8::valid_utf8(bytes.deep_view()),
66 ensures
67 res.deep_view() == vstd::utf8::decode_utf8(bytes.deep_view()),
68;
69
70type Utf8StringFmt = Mapped<Refined<Tail, PredFnSpec<Seq<u8>>>, FnSpecMapper<Seq<u8>, Seq<char>>>;
71
72pub open spec fn utf8string_fmt() -> Utf8StringFmt {
73 Mapped {
74 inner: Refined(Tail, |bytes: Seq<u8>| vstd::utf8::valid_utf8(bytes)),
75 mapper: (
76 |bytes: Seq<u8>| vstd::utf8::decode_utf8(bytes),
77 |chars: Seq<char>| vstd::utf8::encode_utf8(chars),
78 ),
79 }
80}
81
82mod derived_specs {
83 use super::*;
84
85 impl SpecParser for super::super::Utf8StringFmt {
86 type PVal = Seq<char>;
87
88 open spec fn spec_parse(&self, ibuf: Seq<u8>) -> Option<(int, Self::PVal)> {
89 utf8string_fmt().spec_parse(ibuf)
90 }
91 }
92
93 impl Consistency for super::super::Utf8StringFmt {
94 type Val = Seq<char>;
95
96 open spec fn consistent(&self, v: Self::Val) -> bool {
97 utf8string_fmt().consistent(v)
98 }
99 }
100
101 impl SpecSerializerDps for super::super::Utf8StringFmt {
102 type SValue = Seq<char>;
103
104 open spec fn spec_serialize_dps(&self, v: Self::SValue, obuf: Seq<u8>) -> Seq<u8> {
105 utf8string_fmt().spec_serialize_dps(v, obuf)
106 }
107 }
108
109 impl SpecSerializer for super::super::Utf8StringFmt {
110 type SVal = Seq<char>;
111
112 open spec fn spec_serialize(&self, v: Self::SVal) -> Seq<u8> {
113 utf8string_fmt().spec_serialize(v)
114 }
115 }
116
117 impl SpecByteLen for super::super::Utf8StringFmt {
118 type T = Seq<char>;
119
120 open spec fn byte_len(&self, v: Self::T) -> nat {
121 utf8string_fmt().byte_len(v)
122 }
123 }
124
125}
126
127mod derived_proofs {
128 use super::*;
129
130 impl SafeParser for super::super::Utf8StringFmt {
131 proof fn lemma_parse_safe(&self, ibuf: Seq<u8>) {
132 utf8string_fmt().lemma_parse_safe(ibuf);
133 }
134 }
135
136 impl Productive for super::super::Utf8StringFmt {
137 open spec fn productive_inv(&self) -> bool {
138 false
139 }
140
141 proof fn lemma_productive(&self, s: Seq<u8>) {
142 }
143 }
144
145 impl SoundParser for super::super::Utf8StringFmt {
146 proof fn lemma_parse_sound_consumption(&self, ibuf: Seq<u8>) {
147 broadcast use vstd::utf8::decode_utf8_encode_utf8;
148
149 utf8string_fmt().lemma_parse_sound_consumption(ibuf);
150 }
151
152 proof fn lemma_parse_sound_value(&self, ibuf: Seq<u8>) {
153 broadcast use vstd::utf8::decode_utf8_encode_utf8;
154
155 utf8string_fmt().lemma_parse_sound_value(ibuf);
156 }
157 }
158
159 impl GoodSerializer for super::super::Utf8StringFmt {
160 proof fn lemma_serialize_len(&self, v: Self::SVal) {
161 utf8string_fmt().lemma_serialize_len(v);
162 }
163 }
164
165 impl SPRoundTripDps for super::super::Utf8StringFmt {
166 proof fn theorem_serialize_dps_parse_roundtrip(&self, v: Self::T, obuf: Seq<u8>) {
167 broadcast use vstd::utf8::encode_utf8_decode_utf8;
168
169 utf8string_fmt().theorem_serialize_dps_parse_roundtrip(v, obuf);
170 }
171 }
172
173 impl NonMalleable for super::super::Utf8StringFmt {
174 proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
175 broadcast use vstd::utf8::decode_utf8_encode_utf8;
176
177 utf8string_fmt().lemma_parse_non_malleable(buf1, buf2);
178 }
179 }
180
181 impl EquivSerializers for super::super::Utf8StringFmt {
182 proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
183 utf8string_fmt().lemma_serialize_equiv_on_empty(v);
184 }
185 }
186
187}
188
189impl<'i> Parser<&'i [u8]> for super::Utf8StringFmt {
190 type PT = &'i str;
191
192 fn parse(&self, ibuf: &&'i [u8]) -> PResult<Self::PT> {
193 let (n, bytes) = Tail.parse(ibuf)?;
194 if is_valid_utf8(bytes) {
195 let inner = utf8_from_bytes_unchecked(bytes);
196 Ok((n, inner))
197 } else {
198 Err(ParseError::custom("Invalid UTF-8"))
199 }
200 }
201}
202
203impl<Output: OutputBuf, 'i> Serializer<Output, &'i str> for super::Utf8StringFmt {
204 fn serialize_into(&self, v: &&'i str, obuf: &mut Output) {
205 let bytes = v.as_bytes();
206 Tail.serialize_into(&bytes, obuf);
207 }
208}
209
210impl<'i> Prepare<&'i str> for super::Utf8StringFmt {
211 fn prepare(&self, v: &&'i str) -> Result<usize, PreSerializeError> {
212 broadcast use vstd::utf8::encode_utf8_valid_utf8;
213
214 let bytes = v.as_bytes();
215 Tail.prepare(&bytes)
216 }
217}
218
219impl<'i> ByteLen<&'i str> for super::Utf8StringFmt {
220 fn length(&self, v: &&'i str) -> usize {
221 let bytes = v.as_bytes();
222 Tail.length(&bytes)
223 }
224}
225
226#[cfg(feature = "alloc")]
227impl<Output: OutputBuf> Serializer<Output, Utf8StringOwned> for super::Utf8StringFmt {
228 fn serialize_into(&self, v: &Utf8StringOwned, obuf: &mut Output) {
229 let bytes = v.as_str().as_bytes();
230 Tail.serialize_into(&bytes, obuf);
231 }
232}
233
234#[cfg(feature = "alloc")]
235impl Prepare<Utf8StringOwned> for super::Utf8StringFmt {
236 fn prepare(&self, v: &Utf8StringOwned) -> Result<usize, PreSerializeError> {
237 broadcast use vstd::utf8::encode_utf8_valid_utf8;
238
239 let bytes = v.as_str().as_bytes();
240 Tail.prepare(&bytes)
241 }
242}
243
244#[cfg(feature = "alloc")]
245impl ByteLen<Utf8StringOwned> for super::Utf8StringFmt {
246 fn length(&self, v: &Utf8StringOwned) -> usize {
247 let bytes = v.as_str().as_bytes();
248 Tail.length(&bytes)
249 }
250}
251
252}