1#![feature(rustc_attrs)]
2#![allow(unused_imports)]
3
4#[cfg(all(feature = "alloc", not(verus_verify_core)))]
5use alloc::str::Chars;
6#[cfg(all(feature = "alloc", not(verus_verify_core)))]
7use alloc::string::{self, String, ToString};
8#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
9use core::ops::{Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
10#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
11use core::slice::SliceIndex;
12
13use super::prelude::*;
14use super::seq::Seq;
15use super::slice::*;
16#[cfg(all(verus_keep_ghost, feature = "alloc", not(verus_verify_core)))]
17use super::std_specs::fmt::DisplaySpec;
18#[cfg(verus_keep_ghost)]
19#[cfg(all(feature = "alloc", not(verus_verify_core)))]
20use super::std_specs::iter::IteratorSpec;
21#[cfg(verus_keep_ghost)]
22use super::std_specs::range::{
23 ExRange, RangeBoundsSpec, slice_range_end, slice_range_start, slice_range_valid,
24 spec_range_inclusive_is_empty,
25};
26use super::utf8::*;
27use super::view::*;
28
29#[cfg(verus_keep_ghost)]
30#[cfg(not(verus_verify_core))]
31use super::std_specs::cmp::PartialEqSpecImpl;
32
33verus! {
34
35broadcast use {super::seq::group_seq_lemmas, super::slice::group_slice_axioms};
36
37#[cfg(not(verus_verify_core))]
38impl View for str {
39 type V = Seq<char>;
40
41 uninterp spec fn view(&self) -> Seq<char>;
42}
43
44#[cfg(not(verus_verify_core))]
45impl DeepView for str {
46 type V = Seq<char>;
47
48 open spec fn deep_view(&self) -> Seq<char> {
49 self.view()
50 }
51}
52
53#[cfg(verus_keep_ghost)]
54#[cfg(not(verus_verify_core))]
55impl PartialEqSpecImpl for str {
56 open spec fn obeys_eq_spec() -> bool {
57 true
58 }
59
60 open spec fn eq_spec(&self, other: &str) -> bool {
61 self@ == other@
62 }
63}
64
65#[cfg(not(verus_verify_core))]
66pub trait StringSliceAdditionalSpecFns {
67 spec fn spec_bytes(&self) -> Seq<u8>;
68}
69
70#[cfg(not(verus_verify_core))]
71impl StringSliceAdditionalSpecFns for str {
72 open spec fn spec_bytes(&self) -> Seq<u8> {
73 encode_utf8(self@)
74 }
75}
76
77#[cfg(not(verus_verify_core))]
78pub open spec fn is_ascii(s: &str) -> bool {
79 is_ascii_chars(s@)
80}
81
82#[cfg(not(verus_verify_core))]
83pub broadcast proof fn is_ascii_spec_bytes(s: &str)
84 ensures
85 #[trigger] is_ascii(s) ==> #[trigger] s.spec_bytes() =~= Seq::new(
86 s@.len(),
87 |i| s@.index(i) as u8,
88 ),
89{
90 if (is_ascii(s)) {
91 is_ascii_chars_encode_utf8(s@);
92 }
93}
94
95#[cfg(not(verus_verify_core))]
96pub broadcast proof fn is_ascii_concat(s1: &str, s2: &str, s3: &str)
97 requires
98 s1@ =~= s2@ + s3@,
99 ensures
100 #![trigger s2@ + s3@, is_ascii(s1), is_ascii(s2), is_ascii(s3)]
101 is_ascii(s1) <==> is_ascii(s2) && is_ascii(s3),
102{
103 broadcast use is_ascii_chars_concat;
104
105 if (is_ascii(s1)) {
106 is_ascii_chars_concat(s1@, s2@, s3@);
107 }
108}
109
110#[cfg(not(verus_verify_core))]
111#[verifier::when_used_as_spec(is_ascii)]
112pub assume_specification[ str::is_ascii ](s: &str) -> (b: bool)
113 ensures
114 b == is_ascii(s),
115;
116
117#[cfg(all(feature = "alloc", not(verus_verify_core)))]
118use crate::alloc::borrow::ToOwned;
119
120#[cfg(all(feature = "alloc", not(verus_verify_core)))]
121pub assume_specification[ str::to_owned ](s: &str) -> (res: String)
122 ensures
123 s@ == res@,
124;
125
126#[cfg(not(verus_verify_core))]
127pub assume_specification[ str::as_bytes ](s: &str) -> (b: &[u8])
128 ensures
129 b@ == s.spec_bytes(),
130 opens_invariants none
131 no_unwind
132;
133
134#[cfg(not(verus_verify_core))]
135#[verifier::allow_in_spec]
136pub assume_specification[ str::len ](s: &str) -> usize
137 returns
138 s.spec_bytes().len() as usize,
139 opens_invariants none
140 no_unwind
141;
142
143#[cfg(not(verus_verify_core))]
144#[verifier::allow_in_spec]
145pub assume_specification[ str::is_empty ](s: &str) -> bool
146 returns
147 s@.len() == 0,
148 opens_invariants none
149 no_unwind
150;
151
152#[cfg(not(verus_verify_core))]
153#[verifier::allow_in_spec]
154pub assume_specification[ str::is_char_boundary ](s: &str, index: usize) -> bool
155 returns
156 is_char_boundary(s.spec_bytes(), index as int),
157;
158
159#[cfg(not(verus_verify_core))]
160pub assume_specification[ str::split_at ](s: &str, mid: usize) -> (res: (&str, &str))
161 requires
162 is_char_boundary(s.spec_bytes(), mid as int),
163 ensures
164 res.0.spec_bytes() =~= s.spec_bytes()[..mid],
165 res.1.spec_bytes() =~= s.spec_bytes()[mid..],
166;
167
168#[cfg(not(verus_verify_core))]
169pub assume_specification[ str::from_utf8_unchecked ](v: &[u8]) -> (res: &str)
170 requires
171 valid_utf8(v@),
172 ensures
173 res.spec_bytes() =~= v@,
174;
175
176#[cfg(all(feature = "alloc", not(verus_verify_core)))]
177pub uninterp spec fn to_string_from_display_ensures<T: core::fmt::Display + ?Sized>(
178 t: &T,
179 s: String,
180) -> bool;
181
182#[cfg(all(feature = "alloc", not(verus_verify_core)))]
183pub broadcast proof fn to_string_from_display_ensures_for_str(t: &str, res: String)
184 ensures
185 #[trigger] to_string_from_display_ensures::<str>(t, res) <==> (t@ == res@),
186{
187 admit();
188}
189
190#[cfg(all(feature = "alloc", not(verus_verify_core)))]
191pub assume_specification<T: core::fmt::Display + ?Sized>[ <T as ToString>::to_string ](
192 t: &T,
193) -> (res: String)
194 requires
195 forall|f: &core::fmt::Formatter<'_>| t.fmt_req(f),
196 ensures
197 to_string_from_display_ensures::<T>(t, res),
198;
199
200#[cfg(not(verus_verify_core))]
201#[verifier::external]
202pub trait StrSliceExecFns {
203 fn unicode_len(&self) -> usize;
204
205 fn get_char(&self, i: usize) -> char;
206
207 fn substring_ascii<'a>(&'a self, from: usize, to: usize) -> &'a str;
208
209 fn substring_char<'a>(&'a self, from: usize, to: usize) -> &'a str;
210
211 fn get_ascii(&self, i: usize) -> u8;
212
213 #[cfg(feature = "alloc")]
214 fn as_bytes_vec(&self) -> alloc::vec::Vec<u8>;
215}
216
217#[cfg(not(verus_verify_core))]
218impl StrSliceExecFns for str {
219 #[verifier::external_body]
224 fn unicode_len(&self) -> (l: usize)
225 ensures
226 l as nat == self@.len(),
227 {
228 self.chars().count()
229 }
230
231 #[verifier::external_body]
233 fn get_char(&self, i: usize) -> (c: char)
234 requires
235 i < self@.len(),
236 ensures
237 self@.index(i as int) == c,
238 {
239 self.chars().nth(i).unwrap()
240 }
241
242 #[verifier::external_body]
243 fn substring_ascii<'a>(&'a self, from: usize, to: usize) -> (ret: &'a str)
244 requires
245 self.is_ascii(),
246 from <= to <= self@.len(),
247 ensures
248 ret@ == self@[from..to],
249 ret.is_ascii(),
250 {
251 &self[from..to]
253 }
254
255 #[verifier::external_body]
256 fn substring_char<'a>(&'a self, from: usize, to: usize) -> (ret: &'a str)
257 requires
258 from <= to <= self@.len(),
259 ensures
260 ret@ == self@[from..to],
261 {
262 let mut char_pos = 0;
263 let mut byte_start = None;
264 let mut byte_end = None;
265 let mut byte_pos = 0;
266 let mut it = self.chars();
267 loop {
268 if char_pos == from {
269 byte_start = Some(byte_pos);
270 }
271 if char_pos == to {
272 byte_end = Some(byte_pos);
273 break;
274 }
275 if let Some(c) = it.next() {
276 char_pos += 1;
277 byte_pos += c.len_utf8();
278 } else {
279 break;
280 }
281 }
282 let byte_start = byte_start.unwrap();
283 let byte_end = byte_end.unwrap();
284 &self[byte_start..byte_end]
286 }
287
288 fn get_ascii(&self, i: usize) -> (b: u8)
289 requires
290 self.is_ascii(),
291 i < self@.len(),
292 ensures
293 self@.index(i as int) as u8 == b,
294 {
295 broadcast use is_ascii_spec_bytes;
296 self.as_bytes()[i]
299 }
300
301 #[cfg(feature = "alloc")]
302 fn as_bytes_vec(&self) -> (ret: alloc::vec::Vec<u8>)
303 ensures
304 ret@ == self.spec_bytes(),
305 {
306 slice_to_vec(self.as_bytes())
307 }
308}
309
310#[cfg(not(verus_verify_core))]
311pub uninterp spec fn strlit_view_id(s: Seq<char>) -> int;
312
313#[cfg(not(verus_verify_core))]
315pub broadcast axiom fn axiom_new_strlit_view_id(id: int)
316 ensures
317 strlit_view_id(#[trigger] strslice_new_strlit(id).view()) == id,
318;
319
320#[cfg(not(verus_verify_core))]
321pub broadcast axiom fn axiom_str_literal_len<'a>(s: &'a str)
322 ensures
323 #[trigger] s@.len() == strslice_len(s),
324;
325
326#[cfg(not(verus_verify_core))]
327pub broadcast axiom fn axiom_str_literal_get_char<'a>(s: &'a str, i: int)
328 ensures
329 #[trigger] s@.index(i) == strslice_get_char(s, i),
330;
331
332#[cfg(all(not(feature = "alloc"), not(verus_verify_core)))]
333pub broadcast group group_string_axioms {
334 axiom_new_strlit_view_id,
335 axiom_str_literal_len,
336 axiom_str_literal_get_char,
337 is_ascii_spec_bytes,
338 is_ascii_concat,
339}
340
341#[cfg(all(feature = "alloc", not(verus_verify_core)))]
342pub broadcast group group_string_axioms {
343 axiom_new_strlit_view_id,
344 axiom_str_literal_len,
345 axiom_str_literal_get_char,
346 to_string_from_display_ensures_for_str,
347 is_ascii_spec_bytes,
348 is_ascii_concat,
349}
350
351#[cfg(all(feature = "alloc", not(verus_verify_core)))]
352impl View for String {
353 type V = Seq<char>;
354
355 uninterp spec fn view(&self) -> Seq<char>;
356}
357
358#[cfg(all(feature = "alloc", not(verus_verify_core)))]
359impl DeepView for String {
360 type V = Seq<char>;
361
362 open spec fn deep_view(&self) -> Seq<char> {
363 self.view()
364 }
365}
366
367#[cfg(verus_keep_ghost)]
368#[cfg(all(feature = "alloc", not(verus_verify_core)))]
369impl PartialEqSpecImpl for String {
370 open spec fn obeys_eq_spec() -> bool {
371 true
372 }
373
374 open spec fn eq_spec(&self, other: &String) -> bool {
375 self@ == other@
376 }
377}
378
379#[cfg(all(feature = "alloc", not(verus_verify_core)))]
380#[verifier::external_type_specification]
381#[verifier::external_body]
382pub struct ExString(String);
383
384#[cfg(all(feature = "alloc", not(verus_verify_core)))]
385pub open spec fn string_is_ascii(s: &String) -> bool {
386 is_ascii_chars(s@)
387}
388
389#[cfg(all(feature = "alloc", not(verus_verify_core)))]
390pub assume_specification<'a>[ String::as_str ](s: &'a String) -> (res: &'a str)
391 ensures
392 res@ == s@,
393 opens_invariants none
394 no_unwind
395;
396
397#[cfg(all(feature = "alloc", not(verus_verify_core)))]
399pub assume_specification<'a>[ <String as core::ops::Deref>::deref ](s: &'a String) -> (res: &'a str)
400 ensures
401 res@ == s@,
402;
403
404#[cfg(all(feature = "alloc", not(verus_verify_core)))]
405pub assume_specification[ <String as Clone>::clone ](s: &String) -> (res: String)
406 ensures
407 res == s,
408;
409
410#[cfg(all(feature = "alloc", not(verus_verify_core)))]
411pub assume_specification[ <String as PartialEq>::eq ](s: &String, other: &String) -> (res: bool)
412 ensures
413 res == (s@ == other@),
414;
415
416#[cfg(all(feature = "alloc", not(verus_verify_core)))]
417pub assume_specification[ String::new ]() -> (res: String)
418 ensures
419 res@ == Seq::<char>::empty(),
420;
421
422#[cfg(all(feature = "alloc", not(verus_verify_core)))]
423pub assume_specification[ String::push ](s: &mut String, c: char)
424 ensures
425 final(s)@ == old(s)@.push(c),
426;
427
428#[cfg(all(feature = "alloc", not(verus_verify_core)))]
429pub assume_specification[ String::pop ](s: &mut String) -> (res: Option<char>)
430 ensures
431 old(s)@.len() == 0 ==> res is None && final(s)@ == old(s)@,
432 old(s)@.len() > 0 ==> res == Some(old(s)@.last()) && final(s)@ == old(s)@.drop_last(),
433;
434
435#[cfg(all(feature = "alloc", not(verus_verify_core)))]
436pub assume_specification[ String::push_str ](s: &mut String, other: &str)
437 ensures
438 final(s)@ == old(s)@ + other@,
439;
440
441#[cfg(all(feature = "alloc", not(verus_verify_core)))]
442pub assume_specification[ String::is_empty ](s: &String) -> (res: bool)
443 ensures
444 res == (s@.len() == 0),
445 opens_invariants none
446 no_unwind
447;
448
449#[cfg(all(feature = "alloc", not(verus_verify_core)))]
450pub assume_specification[ String::clear ](s: &mut String)
451 ensures
452 final(s)@ == Seq::<char>::empty(),
453;
454
455#[cfg(all(feature = "alloc", not(verus_verify_core)))]
456pub assume_specification[ <String as core::default::Default>::default ]() -> (r: String)
457 ensures
458 r@ == Seq::<char>::empty(),
459;
460
461#[cfg(all(feature = "alloc", not(verus_verify_core)))]
462pub trait StringExecFnsIsAscii: Sized {
463 fn is_ascii(&self) -> bool;
464}
465
466#[cfg(all(feature = "alloc", not(verus_verify_core)))]
467impl StringExecFnsIsAscii for String {
468 #[inline(always)]
469 #[verifier::when_used_as_spec(string_is_ascii)]
470 fn is_ascii(&self) -> (ret: bool)
471 ensures
472 ret == string_is_ascii(self),
473 {
474 self.as_str().is_ascii()
475 }
476}
477
478#[cfg(all(feature = "alloc", not(verus_verify_core)))]
479#[verifier::external]
480pub trait StringExecFns: Sized {
481 fn from_str<'a>(s: &'a str) -> String;
482
483 fn append<'a, 'b>(&'a mut self, other: &'b str);
484
485 fn concat<'b>(self, other: &'b str) -> String;
486}
487
488#[cfg(all(feature = "alloc", not(verus_verify_core)))]
489impl StringExecFns for String {
490 #[verifier::external_body]
491 fn from_str<'a>(s: &'a str) -> (ret: String)
492 ensures
493 s@ == ret@,
494 {
495 s.to_string()
496 }
497
498 #[verifier::external_body]
499 fn append<'a, 'b>(&'a mut self, other: &'b str)
500 ensures
501 final(self)@ == old(self)@ + other@,
502 {
503 *self += other;
504 }
505
506 #[verifier::external_body]
507 fn concat<'b>(self, other: &'b str) -> (ret: String)
508 ensures
509 ret@ == self@ + other@,
510 {
511 self + other
512 }
513}
514
515#[verifier::external_type_specification]
518#[verifier::external_body]
519#[cfg(all(feature = "alloc", not(verus_verify_core)))]
520pub struct ExChars<'a>(Chars<'a>);
521
522#[cfg(feature = "alloc")]
525pub uninterp spec fn into_iter_elts<'a>(i: Chars<'a>) -> Seq<char>;
526
527#[cfg(feature = "alloc")]
528pub assume_specification[ str::chars ](s: &str) -> (iter: Chars<'_>)
529 ensures
530 IteratorSpec::remaining(&iter) == s@,
531 IteratorSpec::decrease(&iter) is Some,
532;
533
534#[cfg(verus_keep_ghost)]
535#[cfg(feature = "alloc")]
536impl<'a> super::std_specs::iter::IteratorSpecImpl for Chars<'a> {
537 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
538 true
539 }
540
541 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
542
543 #[verifier::prophetic]
544 open spec fn produces(&self) -> Seq<bool> {
545 Seq::new(IteratorSpec::remaining(self).len(), |i: int| true)
546 }
547
548 uninterp spec fn decrease(&self) -> Option<nat>;
549
550 open spec fn peek(&self, index: int) -> Option<Self::Item> {
551 if 0 <= index < into_iter_elts(*self).len() {
552 Some(into_iter_elts(*self)[index])
553 } else {
554 None
555 }
556 }
557}
558
559#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
564pub open spec fn str_slice_in_bounds<R: RangeBoundsSpec<usize>>(range: &R, s: &str) -> bool {
565 &&& slice_range_valid(range, s.spec_bytes().len())
566 &&& is_char_boundary(s.spec_bytes(), slice_range_start(range))
567 &&& is_char_boundary(s.spec_bytes(), slice_range_end(range, s.spec_bytes().len()))
568}
569
570#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
575pub open spec fn str_slice_index_postcondition<R: RangeBoundsSpec<usize>>(
576 range: &R,
577 s: Seq<u8>,
578 r: Seq<u8>,
579) -> bool {
580 r == s[slice_range_start(range)..slice_range_end(range, s.len())]
581}
582
583#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
588pub open spec fn str_slice_index_mut_postcondition<R: RangeBoundsSpec<usize>>(
589 range: &R,
590 old_s: Seq<u8>,
591 final_s: Seq<u8>,
592 r: Seq<u8>,
593 final_r: Seq<u8>,
594) -> bool {
595 let start = slice_range_start(range);
596 let end = slice_range_end(range, old_s.len());
597 &&& r == old_s[start..end]
598 &&& final_s.len() == old_s.len()
599 &&& final_s[..start] == old_s[..start]
600 &&& final_s[start..end] == final_r
601 &&& final_s[end..old_s.len()] == old_s[end..]
602}
603
604#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
605impl super::slice::SliceIndexSpecImpl<str> for (Bound<usize>, Bound<usize>) {
606 open spec fn in_bounds(&self, s: &str) -> bool {
607 str_slice_in_bounds(self, s)
608 }
609
610 open spec fn index_postcondition(&self, s: &str, r: &str) -> bool {
611 str_slice_index_postcondition(self, s.spec_bytes(), r.spec_bytes())
612 }
613
614 open spec fn index_mut_postcondition(
615 &self,
616 old_slice: &str,
617 final_slice: &str,
618 immediate_output: &str,
619 final_output: &str,
620 ) -> bool {
621 str_slice_index_mut_postcondition(
622 self,
623 old_slice.spec_bytes(),
624 final_slice.spec_bytes(),
625 immediate_output.spec_bytes(),
626 final_output.spec_bytes(),
627 )
628 }
629}
630
631#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
632pub assume_specification[ <(Bound<usize>, Bound<usize>) as SliceIndex<str>>::get ](
633 i: (Bound<usize>, Bound<usize>),
634 s: &str,
635) -> (r: Option<&str>)
636;
637
638#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
639pub assume_specification[ <(Bound<usize>, Bound<usize>) as SliceIndex<str>>::index ](
640 i: (Bound<usize>, Bound<usize>),
641 s: &str,
642) -> (r: &str)
643;
644
645#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
646pub assume_specification[ <(Bound<usize>, Bound<usize>) as SliceIndex<str>>::get_mut ](
647 i: (Bound<usize>, Bound<usize>),
648 s: &mut str,
649) -> (r: Option<&mut str>)
650;
651
652#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
653pub assume_specification[ <(Bound<usize>, Bound<usize>) as SliceIndex<str>>::index_mut ](
654 i: (Bound<usize>, Bound<usize>),
655 s: &mut str,
656) -> (r: &mut str)
657;
658
659#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
660impl super::slice::SliceIndexSpecImpl<str> for Range<usize> {
661 open spec fn in_bounds(&self, s: &str) -> bool {
662 str_slice_in_bounds(self, s)
663 }
664
665 open spec fn index_postcondition(&self, s: &str, r: &str) -> bool {
666 str_slice_index_postcondition(self, s.spec_bytes(), r.spec_bytes())
667 }
668
669 open spec fn index_mut_postcondition(
670 &self,
671 old_slice: &str,
672 final_slice: &str,
673 immediate_output: &str,
674 final_output: &str,
675 ) -> bool {
676 str_slice_index_mut_postcondition(
677 self,
678 old_slice.spec_bytes(),
679 final_slice.spec_bytes(),
680 immediate_output.spec_bytes(),
681 final_output.spec_bytes(),
682 )
683 }
684}
685
686#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
687pub assume_specification[ <Range<usize> as SliceIndex<str>>::get ](i: Range<usize>, s: &str) -> (r:
688 Option<&<Range<usize> as SliceIndex<str>>::Output>)
689;
690
691#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
692pub assume_specification[ <Range<usize> as SliceIndex<str>>::index ](
693 i: Range<usize>,
694 s: &str,
695) -> (r: &<Range<usize> as SliceIndex<str>>::Output)
696;
697
698#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
699pub assume_specification[ <Range<usize> as SliceIndex<str>>::get_mut ](
700 i: Range<usize>,
701 s: &mut str,
702) -> (r: Option<&mut <Range<usize> as SliceIndex<str>>::Output>)
703;
704
705#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
706pub assume_specification[ <Range<usize> as SliceIndex<str>>::index_mut ](
707 i: Range<usize>,
708 s: &mut str,
709) -> (r: &mut <Range<usize> as SliceIndex<str>>::Output)
710;
711
712#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
713impl super::slice::SliceIndexSpecImpl<str> for RangeFrom<usize> {
714 open spec fn in_bounds(&self, s: &str) -> bool {
715 str_slice_in_bounds(self, s)
716 }
717
718 open spec fn index_postcondition(&self, s: &str, r: &str) -> bool {
719 str_slice_index_postcondition(self, s.spec_bytes(), r.spec_bytes())
720 }
721
722 open spec fn index_mut_postcondition(
723 &self,
724 old_slice: &str,
725 final_slice: &str,
726 immediate_output: &str,
727 final_output: &str,
728 ) -> bool {
729 str_slice_index_mut_postcondition(
730 self,
731 old_slice.spec_bytes(),
732 final_slice.spec_bytes(),
733 immediate_output.spec_bytes(),
734 final_output.spec_bytes(),
735 )
736 }
737}
738
739#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
740pub assume_specification[ <RangeFrom<usize> as SliceIndex<str>>::get ](
741 i: RangeFrom<usize>,
742 s: &str,
743) -> (r: Option<&<RangeFrom<usize> as SliceIndex<str>>::Output>)
744;
745
746#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
747pub assume_specification[ <RangeFrom<usize> as SliceIndex<str>>::index ](
748 i: RangeFrom<usize>,
749 s: &str,
750) -> (r: &<RangeFrom<usize> as SliceIndex<str>>::Output)
751;
752
753#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
754pub assume_specification[ <RangeFrom<usize> as SliceIndex<str>>::get_mut ](
755 i: RangeFrom<usize>,
756 s: &mut str,
757) -> (r: Option<&mut <RangeFrom<usize> as SliceIndex<str>>::Output>)
758;
759
760#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
761pub assume_specification[ <RangeFrom<usize> as SliceIndex<str>>::index_mut ](
762 i: RangeFrom<usize>,
763 s: &mut str,
764) -> (r: &mut <RangeFrom<usize> as SliceIndex<str>>::Output)
765;
766
767#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
768impl super::slice::SliceIndexSpecImpl<str> for RangeFull {
769 open spec fn in_bounds(&self, s: &str) -> bool {
770 str_slice_in_bounds(self, s)
771 }
772
773 open spec fn index_postcondition(&self, s: &str, r: &str) -> bool {
774 str_slice_index_postcondition(self, s.spec_bytes(), r.spec_bytes())
775 }
776
777 open spec fn index_mut_postcondition(
778 &self,
779 old_slice: &str,
780 final_slice: &str,
781 immediate_output: &str,
782 final_output: &str,
783 ) -> bool {
784 str_slice_index_mut_postcondition(
785 self,
786 old_slice.spec_bytes(),
787 final_slice.spec_bytes(),
788 immediate_output.spec_bytes(),
789 final_output.spec_bytes(),
790 )
791 }
792}
793
794#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
795pub assume_specification[ <RangeFull as SliceIndex<str>>::get ](i: RangeFull, s: &str) -> (r:
796 Option<&<RangeFull as SliceIndex<str>>::Output>)
797;
798
799#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
800pub assume_specification[ <RangeFull as SliceIndex<str>>::index ](i: RangeFull, s: &str) -> (r:
801 &<RangeFull as SliceIndex<str>>::Output)
802;
803
804#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
805pub assume_specification[ <RangeFull as SliceIndex<str>>::get_mut ](
806 i: RangeFull,
807 s: &mut str,
808) -> (r: Option<&mut <RangeFull as SliceIndex<str>>::Output>)
809;
810
811#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
812pub assume_specification[ <RangeFull as SliceIndex<str>>::index_mut ](
813 i: RangeFull,
814 s: &mut str,
815) -> (r: &mut <RangeFull as SliceIndex<str>>::Output)
816;
817
818#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
821pub uninterp spec fn spec_range_inclusive_unspecified_str_in_bounds(
822 range: &RangeInclusive<usize>,
823 s: &str,
824) -> bool;
825
826#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
827impl super::slice::SliceIndexSpecImpl<str> for RangeInclusive<usize> {
828 open spec fn in_bounds(&self, s: &str) -> bool {
829 if spec_range_inclusive_is_empty(self) {
830 spec_range_inclusive_unspecified_str_in_bounds(self, s)
831 } else {
832 str_slice_in_bounds(self, s)
833 }
834 }
835
836 open spec fn index_postcondition(&self, s: &str, r: &str) -> bool {
837 if spec_range_inclusive_is_empty(self) {
838 r.spec_bytes().len() == 0
839 } else {
840 str_slice_index_postcondition(self, s.spec_bytes(), r.spec_bytes())
841 }
842 }
843
844 open spec fn index_mut_postcondition(
845 &self,
846 old_slice: &str,
847 final_slice: &str,
848 immediate_output: &str,
849 final_output: &str,
850 ) -> bool {
851 if spec_range_inclusive_is_empty(self) {
852 &&& immediate_output.spec_bytes().len() == 0
853 &&& final_slice.spec_bytes() == old_slice.spec_bytes()
854 } else {
855 str_slice_index_mut_postcondition(
856 self,
857 old_slice.spec_bytes(),
858 final_slice.spec_bytes(),
859 immediate_output.spec_bytes(),
860 final_output.spec_bytes(),
861 )
862 }
863 }
864}
865
866#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
867pub assume_specification[ <RangeInclusive<usize> as SliceIndex<str>>::get ](
868 i: RangeInclusive<usize>,
869 s: &str,
870) -> (r: Option<&<RangeInclusive<usize> as SliceIndex<str>>::Output>)
871;
872
873#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
874pub assume_specification[ <RangeInclusive<usize> as SliceIndex<str>>::index ](
875 i: RangeInclusive<usize>,
876 s: &str,
877) -> (r: &<RangeInclusive<usize> as SliceIndex<str>>::Output)
878;
879
880#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
881pub assume_specification[ <RangeInclusive<usize> as SliceIndex<str>>::get_mut ](
882 i: RangeInclusive<usize>,
883 s: &mut str,
884) -> (r: Option<&mut <RangeInclusive<usize> as SliceIndex<str>>::Output>)
885;
886
887#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
888pub assume_specification[ <RangeInclusive<usize> as SliceIndex<str>>::index_mut ](
889 i: RangeInclusive<usize>,
890 s: &mut str,
891) -> (r: &mut <RangeInclusive<usize> as SliceIndex<str>>::Output)
892;
893
894#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
895impl super::slice::SliceIndexSpecImpl<str> for RangeTo<usize> {
896 open spec fn in_bounds(&self, s: &str) -> bool {
897 str_slice_in_bounds(self, s)
898 }
899
900 open spec fn index_postcondition(&self, s: &str, r: &str) -> bool {
901 str_slice_index_postcondition(self, s.spec_bytes(), r.spec_bytes())
902 }
903
904 open spec fn index_mut_postcondition(
905 &self,
906 old_slice: &str,
907 final_slice: &str,
908 immediate_output: &str,
909 final_output: &str,
910 ) -> bool {
911 str_slice_index_mut_postcondition(
912 self,
913 old_slice.spec_bytes(),
914 final_slice.spec_bytes(),
915 immediate_output.spec_bytes(),
916 final_output.spec_bytes(),
917 )
918 }
919}
920
921#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
922pub assume_specification[ <RangeTo<usize> as SliceIndex<str>>::get ](
923 i: RangeTo<usize>,
924 s: &str,
925) -> (r: Option<&<RangeTo<usize> as SliceIndex<str>>::Output>)
926;
927
928#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
929pub assume_specification[ <RangeTo<usize> as SliceIndex<str>>::index ](
930 i: RangeTo<usize>,
931 s: &str,
932) -> (r: &<RangeTo<usize> as SliceIndex<str>>::Output)
933;
934
935#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
936pub assume_specification[ <RangeTo<usize> as SliceIndex<str>>::get_mut ](
937 i: RangeTo<usize>,
938 s: &mut str,
939) -> (r: Option<&mut <RangeTo<usize> as SliceIndex<str>>::Output>)
940;
941
942#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
943pub assume_specification[ <RangeTo<usize> as SliceIndex<str>>::index_mut ](
944 i: RangeTo<usize>,
945 s: &mut str,
946) -> (r: &mut <RangeTo<usize> as SliceIndex<str>>::Output)
947;
948
949#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
950impl super::slice::SliceIndexSpecImpl<str> for RangeToInclusive<usize> {
951 open spec fn in_bounds(&self, s: &str) -> bool {
952 str_slice_in_bounds(self, s)
953 }
954
955 open spec fn index_postcondition(&self, s: &str, r: &str) -> bool {
956 str_slice_index_postcondition(self, s.spec_bytes(), r.spec_bytes())
957 }
958
959 open spec fn index_mut_postcondition(
960 &self,
961 old_slice: &str,
962 final_slice: &str,
963 immediate_output: &str,
964 final_output: &str,
965 ) -> bool {
966 str_slice_index_mut_postcondition(
967 self,
968 old_slice.spec_bytes(),
969 final_slice.spec_bytes(),
970 immediate_output.spec_bytes(),
971 final_output.spec_bytes(),
972 )
973 }
974}
975
976#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
977pub assume_specification[ <RangeToInclusive<usize> as SliceIndex<str>>::get ](
978 i: RangeToInclusive<usize>,
979 s: &str,
980) -> (r: Option<&<RangeToInclusive<usize> as SliceIndex<str>>::Output>)
981;
982
983#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
984pub assume_specification[ <RangeToInclusive<usize> as SliceIndex<str>>::index ](
985 i: RangeToInclusive<usize>,
986 s: &str,
987) -> (r: &<RangeToInclusive<usize> as SliceIndex<str>>::Output)
988;
989
990#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
991pub assume_specification[ <RangeToInclusive<usize> as SliceIndex<str>>::get_mut ](
992 i: RangeToInclusive<usize>,
993 s: &mut str,
994) -> (r: Option<&mut <RangeToInclusive<usize> as SliceIndex<str>>::Output>)
995;
996
997#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
998pub assume_specification[ <RangeToInclusive<usize> as SliceIndex<str>>::index_mut ](
999 i: RangeToInclusive<usize>,
1000 s: &mut str,
1001) -> (r: &mut <RangeToInclusive<usize> as SliceIndex<str>>::Output)
1002;
1003
1004#[cfg(all(verus_keep_ghost, not(verus_verify_core)))]
1008impl<I: SliceIndexSpec<str>> super::std_specs::core::IndexSpecImpl<I> for str {
1009 open spec fn index_req(&self, index: &I) -> bool {
1010 index.in_bounds(self)
1011 }
1012}
1013
1014pub use super::view::View;
1015
1016}