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