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