indexing/
container.rs

1
2use std::cmp;
3use std::ops;
4use std::ptr;
5use std::mem;
6
7use std::fmt::{self, Debug};
8
9use std::marker::PhantomData;
10
11use crate::index_error::IndexingError;
12use crate::index_error::index_error;
13use crate::proof::*;
14use std;
15
16use crate::container_traits::*;
17use crate::indexing::{IntoCheckedRange};
18use crate::{Id, Index, Range};
19use crate::ContainerPrivate;
20
21/// A branded container, that allows access only to indices and ranges with
22/// the exact same brand in the `'id` parameter.
23///
24/// The elements in the underlying data structure are accessible partly
25/// through special purpose methods, and through indexing/slicing.
26///
27/// The `Container` can be indexed like `self[i]` where `i` is a trusted
28/// dereferenceable index
29/// or range, and equivalently using `&self[i..]` or `&self[..i]` where
30/// `i` is a trusted index. Indexing like this uses no runtime bounds checking
31/// at all, and it statically guaranteed to be in bounds.
32///
33/// The container can also be sliced for its complete range: `&self[..]`.
34pub struct Container<'id, Array, Mode = ()> {
35    id: Id<'id>,
36    arr: Array,
37    mode: PhantomData<Mode>,
38}
39
40/// Only indexing mode for a container (disallows access through pointer).
41#[derive(Debug, Copy, Clone)]
42pub enum OnlyIndex { }
43
44impl<'id, Array, Mode> Debug for Container<'id, Array, Mode>
45    where Array: Debug
46{
47    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48        self.arr.fmt(f)
49    }
50}
51
52/// A container can be cloned if the inner array can (typically a shared
53/// slice).
54///
55/// But containers of vectors can not be cloned:
56///
57/// ```compile_fail
58/// use indexing::scope;
59/// scope(vec![0; 10], |v| {
60///     let _u = v.clone();
61/// });
62/// ```
63impl<'id, Array, Mode> Clone for Container<'id, Array, Mode>
64    where Array: Clone + FixedLength
65{
66    fn clone(&self) -> Self {
67        Container {
68            id: self.id,
69            arr: self.arr.clone(),
70            mode: self.mode,
71        }
72    }
73}
74
75impl<'id, Array, Mode> ContainerPrivate for Container<'id, Array, Mode> {
76    type Array = Array;
77    #[inline(always)]
78    fn array(&self) -> &Self::Array {
79        &self.arr
80    }
81    #[inline(always)]
82    fn array_mut(&mut self) -> &mut Self::Array {
83        &mut self.arr
84    }
85}
86
87impl<'id, Array, T, Mode> Container<'id, Array, Mode>
88    where Array: Trustworthy<Item=T>,
89{
90    #[inline]
91    pub fn len(&self) -> usize {
92        self.arr.base_len()
93    }
94
95    /// Convert the container into an only-indexing container.
96    ///
97    /// The container no longer allows pointer access. This unlocks
98    /// some features.
99    pub fn only_index(self) -> Container<'id, Array, OnlyIndex> {
100        Container {
101            id: self.id,
102            arr: self.arr,
103            mode: PhantomData,
104        }
105    }
106
107    /// Return the range [0, 0)
108    #[inline]
109    pub fn empty_range(&self) -> Range<'id> {
110        unsafe {
111            Range::from(0, 0)
112        }
113    }
114
115    /// Return the full range of the Container.
116    #[inline]
117    pub fn range(&self) -> Range<'id> {
118        unsafe {
119            Range::from(0, self.len())
120        }
121    }
122
123    /// Vet the absolute `index`.
124    #[inline]
125    pub fn vet(&self, index: usize) -> Result<Index<'id>, IndexingError> {
126        if index < self.len() {
127            unsafe {
128                Ok(Index::new(index))
129            }
130        } else {
131            Err(index_error())
132        }
133    }
134
135    /// Vet the range `r`.
136    #[inline]
137    pub fn vet_range(&self, r: ops::Range<usize>) -> Result<Range<'id>, IndexingError> {
138        if r.start <= r.end && r.end <= self.len() {
139            unsafe {
140                Ok(Range::from(r.start, r.end))
141            }
142        } else {
143            Err(index_error())
144        }
145    }
146
147    #[inline]
148    pub fn split_at<P>(&self, index: Index<'id, P>) -> (Range<'id>, Range<'id, P>) {
149        unsafe {
150            (Range::from(0, index.index), Range::from_any(index.index, self.len()))
151        }
152    }
153
154    /// Split in two ranges, where the first includes the `index` and the second
155    /// starts with the following index.
156    #[inline]
157    pub fn split_after(&self, index: Index<'id>) -> (Range<'id, NonEmpty>, Range<'id>) {
158        let mid = index.index + 1; // must be <= len since `index` is in bounds
159        unsafe {
160            (Range::from_ne(0, mid), Range::from(mid, self.len()))
161        }
162    }
163
164    /// Split around the Range `r`: Return ranges corresponding to `0..r.start`
165    /// and `r.end..`.
166    ///
167    /// So that input `r` and return values `(s, t)` cover the whole container
168    /// in the order `s`, `r`, `t`.
169    #[inline]
170    pub fn split_around<P>(&self, r: Range<'id, P>) -> (Range<'id>, Range<'id>) {
171        unsafe {
172            (Range::from(0, r.start), Range::from(r.end, self.len()))
173        }
174    }
175
176
177    /// Return the range before (not including) the index itself
178    #[inline]
179    pub fn before<P>(&self, index: Index<'id, P>) -> Range<'id> {
180        self.range_of(..index)
181    }
182
183    /// Return the range after (not including) the index itself
184    #[inline]
185    pub fn after(&self, index: Index<'id>) -> Range<'id> {
186        self.range_of(index.after()..)
187    }
188
189    #[inline]
190    pub fn range_of<P, R>(&self, r: R) -> Range<'id>
191        where R: OnePointRange<Index<'id, P>>,
192    {
193        debug_assert!(!(r.start().is_some() && r.end().is_some()));
194        unsafe {
195            let start = r.start().map(|i| i.index).unwrap_or(0);
196            let end = r.end().map(|i| i.index).unwrap_or(self.len());
197            debug_assert!(start <= end && end <= self.len());
198            Range::from(start, end)
199        }
200    }
201
202
203    /// Increment `index`, if doing so would still be in bounds.
204    ///
205    /// Return `true` if the index was incremented.
206    #[inline]
207    pub fn forward(&self, index: &mut Index<'id>) -> bool {
208        let i = index.index + 1;
209        if i < self.len() {
210            index.index = i;
211            true
212        } else { false }
213    }
214
215    /// Increment `index`, if doing so would still be in bounds.
216    ///
217    /// Return `true` if the index was incremented.
218    #[inline]
219    pub fn forward_by(&self, index: &mut Index<'id>, offset: usize) -> bool {
220        let i = index.index + offset;
221        if i < self.len() {
222            index.index = i;
223            true
224        } else { false }
225    }
226
227    /// Increment `r`, clamping to the end of the Container.
228    #[inline]
229    pub fn forward_range_by<P>(&self, r: Range<'id, P>, offset: usize) -> Range<'id> {
230        let start = r.start.saturating_add(offset);
231        let end = r.end.saturating_add(offset);
232        let len = self.len();
233        unsafe {
234            Range::from(cmp::min(len, start), cmp::min(len, end))
235        }
236    }
237
238    /// Decrement `index`, if doing so would still be in bounds.
239    ///
240    /// Return `true` if the index was decremented.
241    #[inline]
242    pub fn backward(&self, index: &mut Index<'id>) -> bool {
243        let i = index.index;
244        if i > 0 {
245            index.index = i - 1;
246            true
247        } else { false }
248    }
249
250    /// Examine the elements after `index` in order from lower indices towards higher.
251    /// While the closure returns `true`, continue scan and include the scanned
252    /// element in the range.
253    ///
254    /// Result always includes `index` in the range
255    #[inline]
256    pub fn scan_from<'b, F>(&'b self, index: Index<'id>, mut f: F) -> Range<'id, NonEmpty>
257        where F: FnMut(&'b T) -> bool, T: 'b,
258              Array: Contiguous<Item=T>,
259    {
260        let mut end = index;
261        for elt in &self[self.after(index)] {
262            if !f(elt) {
263                break;
264            }
265            end.index += 1;
266        }
267        end.index += 1;
268        unsafe {
269            Range::from_ne(index.index, end.index)
270        }
271    }
272
273    /// Examine the elements before `index` in order from higher indices towards lower.
274    /// While the closure returns `true`, continue scan and include the scanned
275    /// element in the range.
276    ///
277    /// Result always includes `index` in the range.
278    #[inline]
279    pub fn scan_from_rev<'b, F>(&'b self, index: Index<'id>, mut f: F) -> Range<'id, NonEmpty>
280        where F: FnMut(&'b T) -> bool, T: 'b,
281              Array: Contiguous<Item=T>,
282    {
283        unsafe {
284            let mut start = index;
285            for elt in self[..index].iter().rev() {
286                if !f(elt) {
287                    break;
288                }
289                start.index -= 1;
290            }
291            Range::from_ne(start.index, index.index + 1)
292        }
293    }
294
295    /// Examine the elements `range` in order from lower indices towards higher.
296    /// While the closure returns `true`, continue scan and include the scanned
297    /// element in the range.
298    #[inline]
299    pub fn scan_range<'b, F, P>(&'b self, range: Range<'id, P>, mut f: F)
300        -> (Range<'id>, Range<'id>)
301        where F: FnMut(&'b T) -> bool, T: 'b,
302              Array: Contiguous<Item=T>,
303    {
304        let mut end = range.start;
305        for elt in &self[range] {
306            if !f(elt) {
307                break;
308            }
309            end += 1;
310        }
311        unsafe {
312            (Range::from(range.start, end),
313             Range::from(end, range.end))
314        }
315    }
316
317    /// Swap elements at `i` and `j` (they may be equal).
318    #[inline]
319    pub fn swap(&mut self, i: Index<'id>, j: Index<'id>)
320        where Array: GetUncheckedMut
321    {
322        unsafe {
323            let self_mut = self as *mut Self;
324            let pi: *mut _ = &mut (*self_mut)[i];
325            let pj: *mut _ = &mut (*self_mut)[j];
326            ptr::swap(pi, pj);
327        }
328    }
329
330    /// Rotate elements in the range `r` by one step to the right (towards higher indices)
331    #[inline]
332    pub fn rotate1_up<R>(&mut self, r: R)
333        where Array: Contiguous + GetUncheckedMut,
334              R: IntoCheckedRange<'id>
335    {
336        if let Ok(r) = r.into() {
337            if r.first() != r.last() {
338                unsafe {
339                    let last_ptr = &self[r.last()] as *const Array::Item;
340                    let first_ptr = &mut self[r.first()] as *mut Array::Item;
341                    let tmp = ptr::read(last_ptr);
342                    ptr::copy(first_ptr,
343                              first_ptr.offset(1),
344                              r.len() - 1);
345                    ptr::copy_nonoverlapping(&tmp, first_ptr, 1);
346                    mem::forget(tmp);
347                }
348            }
349        }
350    }
351
352    /// Rotate elements in the range `r` by one step to the left (towards lower indices)
353    #[inline]
354    pub fn rotate1_down<R>(&mut self, r: R)
355        where Array: Contiguous + GetUncheckedMut,
356              R: IntoCheckedRange<'id>
357    {
358        if let Ok(r) = r.into() {
359            if r.first() != r.last() {
360                unsafe {
361                    let last_ptr = &mut self[r.last()] as *mut Array::Item;
362                    let first_ptr = &mut self[r.first()] as *mut Array::Item;
363                    let tmp = ptr::read(first_ptr);
364                    ptr::copy(first_ptr.offset(1),
365                              first_ptr,
366                              r.len() - 1);
367                    ptr::copy_nonoverlapping(&tmp, last_ptr, 1);
368                    mem::forget(tmp);
369                }
370            }
371        }
372    }
373
374    /// Index by two nonoverlapping ranges, where `r` is before `s`.
375    #[inline]
376    pub fn index_twice<P, Q>(&mut self, r: Range<'id, P>, s: Range<'id, Q>)
377        -> Result<(&mut [T], &mut [T]), IndexingError>
378        where Array: ContiguousMut
379    {
380        if r.end <= s.start {
381            let self_mut = self as *mut Self;
382            unsafe {
383                Ok((&mut (*self_mut)[r], &mut (*self_mut)[s]))
384            }
385        } else {
386            Err(index_error())
387        }
388    }
389
390    /// Zip by raw pointer (will be indentical if ranges have same starting point)
391    pub fn zip_mut_raw<P, Q, F>(&mut self, r: Range<'id, P>, s: Range<'id, Q>, mut f: F)
392        where F: FnMut(*mut T, *mut T),
393              Array: GetUncheckedMut,
394    {
395        let len = cmp::min(r.len(), s.len());
396        for i in 0..len {
397            unsafe {
398                f(
399                    self.arr.xget_unchecked_mut(r.start + i),
400                    self.arr.xget_unchecked_mut(s.start + i)
401                )
402            }
403        }
404    }
405}
406
407/// Methods specific to only index mode
408impl<'id, Array, T> Container<'id, Array, OnlyIndex>
409    where Array: Pushable<Item=T>,
410{
411    /// Add one element to the underlying storage, and return its index.
412    ///
413    /// All outstanding indices remain valid, only the length of the
414    /// container is now larger.
415    pub fn push(&mut self, element: T) -> Index<'id> {
416        let i = self.arr.push(element);
417        debug_assert!(i < self.arr.base_len());
418        unsafe {
419            Index::new(i)
420        }
421    }
422
423    /// Insert one element in the underlying storage at `index`.
424    ///
425    /// All outstanding indices remain valid (in bounds), but elements have
426    /// shifted.
427    pub fn insert<Q>(&mut self, index: Index<'id, Q>, element: T) {
428        debug_assert!(index.index <= self.arr.base_len());
429        unsafe {
430            self.arr.insert_unchecked(index.index, element);
431        }
432    }
433}
434
435impl<'id, Array, T, Mode> Container<'id, Array, Mode>
436    where Array: Trustworthy<Item=T> + FixedLength
437{
438    /// Create a twin Container, that admits the same branded indices as self
439    ///
440    /// Checks the compatibilty (length) of both arrays and returns the
441    /// twin container if it is admissible.
442    ///
443    /// The twin container is OnlyIndex-marked, because only indices/index
444    /// ranges transfer between twins, and branded raw pointers of course not.
445    pub fn make_twin<Array2>(&self, arr: Array2) -> Result<Container<'id, Array2, OnlyIndex>, IndexingError>
446        where Array2: Trustworthy + FixedLength
447    {
448        if self.len() != arr.base_len() {
449            Err(index_error())
450        } else {
451            Ok(Container { id: self.id, arr: arr, mode: PhantomData })
452        }
453    }
454}
455
456/// `&self[i]` where `i` is an `Index<'id>`.
457impl<'id, Array, M> ops::Index<Index<'id>> for Container<'id, Array, M>
458    where Array: GetUnchecked
459{
460    type Output = Array::Item;
461    #[inline(always)]
462    fn index(&self, index: Index<'id>) -> &Self::Output {
463        unsafe {
464            self.arr.xget_unchecked(index.index)
465        }
466    }
467}
468
469/// `&mut self[i]` where `i` is an `Index<'id>`.
470impl<'id, Array, M> ops::IndexMut<Index<'id>> for Container<'id, Array, M>
471    where Array: GetUncheckedMut
472{
473    #[inline(always)]
474    fn index_mut(&mut self, index: Index<'id>) -> &mut Self::Output {
475        unsafe {
476            self.arr.xget_unchecked_mut(index.index)
477        }
478    }
479}
480
481/// `&self[r]` where `r` is a `Range<'id>`.
482impl<'id, T, Array, P, M> ops::Index<Range<'id, P>> for Container<'id, Array, M>
483    where Array: Contiguous<Item=T>,
484{
485    type Output = [T];
486    #[inline(always)]
487    fn index(&self, r: Range<'id, P>) -> &Self::Output {
488        unsafe {
489            std::slice::from_raw_parts(
490                self.arr.begin().offset(r.start as isize),
491                r.len())
492        }
493    }
494}
495
496/// `&mut self[r]` where `r` is a `Range<'id>`.
497impl<'id, Array, P, M> ops::IndexMut<Range<'id, P>> for Container<'id, Array, M>
498    where Array: ContiguousMut,
499{
500    #[inline(always)]
501    fn index_mut(&mut self, r: Range<'id, P>) -> &mut Self::Output {
502        unsafe {
503            std::slice::from_raw_parts_mut(
504                self.arr.begin_mut().offset(r.start as isize),
505                r.len())
506        }
507    }
508}
509
510/// `&self[i..]` where `i` is an `Index<'id, P>` which may be an edge index.
511impl<'id, T, P, Array, M> ops::Index<ops::RangeFrom<Index<'id, P>>> for Container<'id, Array, M>
512    where Array: Contiguous<Item=T>,
513{
514    type Output = [T];
515    #[inline(always)]
516    fn index(&self, r: ops::RangeFrom<Index<'id, P>>) -> &[T] {
517        let i = r.start.index;
518        unsafe {
519            std::slice::from_raw_parts(
520                self.arr.begin().offset(i as isize),
521                self.len() - i)
522        }
523    }
524}
525
526/// `&mut self[i..]` where `i` is an `Index<'id, P>` which may be an edge index.
527impl<'id, T, P, Array, M> ops::IndexMut<ops::RangeFrom<Index<'id, P>>> for Container<'id, Array, M>
528    where Array: ContiguousMut<Item=T>,
529{
530    #[inline(always)]
531    fn index_mut(&mut self, r: ops::RangeFrom<Index<'id, P>>) -> &mut [T] {
532        let i = r.start.index;
533        unsafe {
534            std::slice::from_raw_parts_mut(
535                self.arr.begin_mut().offset(i as isize),
536                self.len() - i)
537        }
538    }
539}
540
541/// `&self[..i]` where `i` is an `Index<'id, P>`, which may be an edge index.
542impl<'id, T, P, Array, M> ops::Index<ops::RangeTo<Index<'id, P>>> for Container<'id, Array, M>
543    where Array: Contiguous<Item=T>,
544{
545    type Output = [T];
546    #[inline(always)]
547    fn index(&self, r: ops::RangeTo<Index<'id, P>>) -> &[T] {
548        let i = r.end.index;
549        unsafe {
550            std::slice::from_raw_parts(self.arr.begin(), i)
551        }
552    }
553}
554
555/// `&mut self[..i]` where `i` is an `Index<'id, P>`, which may be an edge index.
556impl<'id, T, P, Array, M> ops::IndexMut<ops::RangeTo<Index<'id, P>>> for Container<'id, Array, M>
557    where Array: ContiguousMut<Item=T>,
558{
559    #[inline(always)]
560    fn index_mut(&mut self, r: ops::RangeTo<Index<'id, P>>) -> &mut [T] {
561        let i = r.end.index;
562        unsafe {
563            std::slice::from_raw_parts_mut(self.arr.begin_mut(), i)
564        }
565    }
566}
567
568/// `&self[..]`
569impl<'id, T, Array, M> ops::Index<ops::RangeFull> for Container<'id, Array, M>
570    where Array: Contiguous<Item=T>,
571{
572    type Output = [T];
573    #[inline(always)]
574    fn index(&self, _: ops::RangeFull) -> &[T] {
575        self.arr.as_slice()
576    }
577}
578
579/// `&mut self[..]`
580impl<'id, T, Array> ops::IndexMut<ops::RangeFull> for Container<'id, Array>
581    where Array: ContiguousMut<Item=T>,
582{
583    #[inline(always)]
584    fn index_mut(&mut self, _: ops::RangeFull) -> &mut [T] {
585        self.arr.as_mut_slice()
586    }
587}
588
589
590/*
591// ###### Bounds checking impls #####
592impl<'id, 'a, T> ops::Index<ops::Range<usize>> for Container<'id, &'a mut [T]> {
593    type Output = [T];
594    #[inline(always)]
595    fn index(&self, r: ops::Range<usize>) -> &[T] {
596        &self.arr[r]
597    }
598}
599
600impl<'id, 'a, T> ops::Index<ops::RangeFrom<usize>> for Container<'id, &'a mut [T]> {
601    type Output = [T];
602    #[inline(always)]
603    fn index(&self, r: ops::RangeFrom<usize>) -> &[T] {
604        &self.arr[r]
605    }
606}
607
608impl<'id, 'a, T> ops::Index<ops::RangeTo<usize>> for Container<'id, &'a mut [T]> {
609    type Output = [T];
610    #[inline(always)]
611    fn index(&self, r: ops::RangeTo<usize>) -> &[T] {
612        &self.arr[r]
613    }
614}
615
616impl<'id, 'a, T> ops::IndexMut<ops::Range<usize>> for Container<'id, &'a mut [T]> {
617    #[inline(always)]
618    fn index_mut(&mut self, r: ops::Range<usize>) -> &mut [T] {
619        &mut self.arr[r]
620    }
621}
622
623impl<'id, 'a, T> ops::IndexMut<ops::RangeFrom<usize>> for Container<'id, &'a mut [T]> {
624    #[inline(always)]
625    fn index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut [T] {
626        &mut self.arr[r]
627    }
628}
629
630impl<'id, 'a, T> ops::IndexMut<ops::RangeTo<usize>> for Container<'id, &'a mut [T]> {
631    #[inline(always)]
632    fn index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut [T] {
633        &mut self.arr[r]
634    }
635}
636// ####
637*/
638
639/// Create an indexing scope for a container.
640///
641/// The indexing scope is a closure that is passed a unique lifetime for
642/// the parameter `'id`; this lifetime brands the container and its indices
643/// and ranges, so that they are trusted to be in bounds.
644///
645/// Indices and ranges branded with `'id` can not leave the closure. The
646/// container can only be accessed and mutated through the `Container` wrapper
647/// passed as the first argument to the indexing scope.
648pub fn scope<Array, F, Out>(arr: Array, f: F) -> Out
649    where F: for<'id> FnOnce(Container<'id, Array>) -> Out,
650          Array: Trustworthy,
651{
652    // This is where the magic happens. We bind the indexer and indices
653    // to the same invariant lifetime (a constraint established by F's
654    // definition). As such, each call to `indices` produces a unique
655    // signature that only these two values can share.
656    //
657    // Within this function, the borrow solver can choose literally any lifetime,
658    // including `'static`, but we don't care what the borrow solver does in
659    // *this* function. We only need to trick the solver in the caller's
660    // scope. Since borrowck doesn't do interprocedural analysis, it
661    // sees every call to this function produces values with some opaque
662    // fresh lifetime and can't unify any of them.
663    //
664    // In principle a "super borrowchecker" that does interprocedural
665    // analysis would break this design, but we could go out of our way
666    // to somehow bind the lifetime to the inside of this function, making
667    // it sound again. Borrowck will never do such analysis, so we don't
668    // care.
669    f(Container { id: Id::default(), arr: arr, mode: PhantomData })
670}
671
672#[test]
673fn test_intervals() {
674    let mut data = [0; 8];
675    scope(&mut data[..], |mut data| {
676        let r = data.range();
677        for (index, part) in r.subdivide(3).enumerate() {
678            for elt in &mut data[part] {
679                *elt = index;
680            }
681        }
682    });
683    assert_eq!(&data[..], &[0, 0, 1, 1, 1, 2, 2, 2]);
684}
685
686
687#[test]
688fn intervals() {
689    let mut data = [0; 16];
690    scope(&mut data[..], |mut arr| {
691        let r = arr.range();
692        for elt in &mut arr[r] {
693            *elt += 1;
694        }
695        // println!("{:?}", &mut arr[r]);
696    });
697}
698
699
700#[test]
701fn test_scan() {
702    let mut data = [0, 0, 0, 1, 2];
703    scope(&mut data[..], |data| {
704        let r = data.range().nonempty().unwrap();
705        let range = data.scan_from(r.first(), |elt| *elt == 0);
706        assert_eq!(&data[range], &[0, 0, 0]);
707        let range = data.scan_from(range.last(), |elt| *elt != 0);
708        assert_eq!(&data[range], &[0, 1, 2]);
709    });
710}
711
712#[test]
713fn test_nonempty() {
714    let mut data = [0, 1, 2, 3, 4, 5];
715    scope(&mut data[..], |data| {
716        let mut r = data.range().nonempty().unwrap();
717        assert_eq!(data[r.first()], 0);
718        assert_eq!(data[r.lower_middle()], 2);
719        assert_eq!(data[r.upper_middle()], 3);
720        assert_eq!(data[r.last()], 5);
721
722        assert!(r.advance());
723        assert_eq!(data[r.first()], 1);
724        assert_eq!(data[r.lower_middle()], 3);
725        assert_eq!(data[r.upper_middle()], 3);
726        assert_eq!(data[r.last()], 5);
727
728        assert!(r.advance());
729        assert_eq!(data[r.first()], 2);
730        assert_eq!(data[r.lower_middle()], 3);
731        assert_eq!(data[r.upper_middle()], 4);
732        assert_eq!(data[r.last()], 5);
733
734        // skip to end
735        while r.advance() { }
736        assert_eq!(data[r.first()], 5);
737        assert_eq!(data[r.lower_middle()], 5);
738        assert_eq!(data[r.upper_middle()], 5);
739        assert_eq!(data[r.last()], 5);
740    });
741}
742
743#[test]
744fn test_contains() {
745    let mut data = [0, 1, 2, 3, 4, 5];
746    scope(&mut data[..], |data| {
747        let r = data.range();
748        for i in 0..data.len() {
749            assert!(r.contains(i).is_some());
750            assert_eq!(r.contains(i).unwrap(), data.vet(i).unwrap());
751        }
752        assert!(r.contains(r.len()).is_none());
753        assert!(data.vet(r.len()).is_err());
754    });
755}
756
757#[test]
758fn test_is_send_sync() {
759    fn _is_send_sync<T: Send + Sync>() { }
760
761    fn _test<'id>() {
762        _is_send_sync::<Id<'id>>();
763        _is_send_sync::<Index<'id>>();
764        _is_send_sync::<Range<'id>>();
765    }
766}