/*! Dynamic vector A growable vector that makes use of unique pointers so that the result can be sent between tasks and so forth. Note that recursive use is not permitted. */ // NB: transitionary, de-mode-ing. #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; use cast::reinterpret_cast; use ptr::null; /** * A growable, modifiable vector type that accumulates elements into a * unique vector. * * # Limitations on recursive use * * This class works by swapping the unique vector out of the data * structure whenever it is to be used. Therefore, recursive use is not * permitted. That is, while iterating through a vector, you cannot * access the vector in any other way or else the program will fail. If * you wish, you can use the `swap()` method to gain access to the raw * vector and transform it or use it any way you like. Eventually, we * may permit read-only access during iteration or other use. * * # WARNING * * For maximum performance, this type is implemented using some rather * unsafe code. In particular, this innocent looking `~[mut A]` pointer * *may be null!* Therefore, it is important you not reach into the * data structure manually but instead use the provided extensions. * * The reason that I did not use an unsafe pointer in the structure * itself is that I wanted to ensure that the vector would be freed when * the dvec is dropped. The reason that I did not use an `Option` * instead of a nullable pointer is that I found experimentally that it * becomes approximately 50% slower. This can probably be improved * through optimization. You can run your own experiments using * `src/test/bench/vec-append.rs`. My own tests found that using null * pointers achieved about 103 million pushes/second. Using an option * type could only produce 47 million pushes/second. */ type DVec_ = { mut data: ~[A] }; pub enum DVec { DVec_(DVec_) } /// Creates a new, empty dvec pub fn DVec() -> DVec { DVec_({mut data: ~[]}) } /// Creates a new dvec with a single element pub fn from_elem(+e: A) -> DVec { DVec_({mut data: ~[move e]}) } /// Creates a new dvec with the contents of a vector pub fn from_vec(+v: ~[A]) -> DVec { DVec_({mut data: move v}) } /// Consumes the vector and returns its contents pub fn unwrap(+d: DVec) -> ~[A] { let DVec_({data: v}) <- d; move v } priv impl DVec { pure fn check_not_borrowed() { unsafe { let data: *() = cast::reinterpret_cast(&self.data); if data.is_null() { fail ~"Recursive use of dvec"; } } } #[inline(always)] fn check_out(f: &fn(+v: ~[A]) -> B) -> B { unsafe { let mut data = cast::reinterpret_cast(&null::<()>()); data <-> self.data; let data_ptr: *() = cast::reinterpret_cast(&data); if data_ptr.is_null() { fail ~"Recursive use of dvec"; } return f(move data); } } #[inline(always)] fn give_back(+data: ~[A]) { unsafe { self.data = move data; } } } // In theory, most everything should work with any A, but in practice // almost nothing works without the copy bound due to limitations // around closures. impl DVec { /// Reserves space for N elements fn reserve(count: uint) { vec::reserve(&mut self.data, count) } /** * Swaps out the current vector and hands it off to a user-provided * function `f`. The function should transform it however is desired * and return a new vector to replace it with. */ #[inline(always)] fn swap(f: &fn(+v: ~[A]) -> ~[A]) { self.check_out(|v| self.give_back(f(move v))) } /** * Swaps out the current vector and hands it off to a user-provided * function `f`. The function should transform it however is desired * and return a new vector to replace it with. */ #[inline(always)] fn swap_mut(f: &fn(-v: ~[mut A]) -> ~[mut A]) { do self.swap |v| { vec::from_mut(f(vec::to_mut(move v))) } } /// Returns the number of elements currently in the dvec pure fn len() -> uint { unsafe { do self.check_out |v| { let l = v.len(); self.give_back(move v); l } } } /// Overwrite the current contents fn set(+w: ~[A]) { self.check_not_borrowed(); self.data <- w; } /// Remove and return the last element fn pop() -> A { do self.check_out |v| { let mut v <- v; let result = vec::pop(v); self.give_back(move v); move result } } /// Insert a single item at the front of the list fn unshift(+t: A) { unsafe { let mut data = cast::reinterpret_cast(&null::<()>()); data <-> self.data; let data_ptr: *() = cast::reinterpret_cast(&data); if data_ptr.is_null() { fail ~"Recursive use of dvec"; } log(error, ~"a"); self.data <- ~[move t]; self.data.push_all_move(move data); log(error, ~"b"); } } /// Append a single item to the end of the list fn push(+t: A) { self.check_not_borrowed(); self.data.push(move t); } /// Remove and return the first element fn shift() -> A { do self.check_out |v| { let mut v = move v; let result = vec::shift(v); self.give_back(move v); move result } } /// Reverse the elements in the list, in place fn reverse() { do self.check_out |v| { let mut v = move v; vec::reverse(v); self.give_back(move v); } } /// Gives access to the vector as a slice with immutable contents fn borrow(op: fn(x: &[A]) -> R) -> R { do self.check_out |v| { let result = op(v); self.give_back(move v); move result } } /// Gives access to the vector as a slice with mutable contents fn borrow_mut(op: fn(x: &[mut A]) -> R) -> R { do self.check_out |v| { let mut v = move v; let result = op(v); self.give_back(move v); move result } } } impl DVec { /** * Append all elements of a vector to the end of the list * * Equivalent to `append_iter()` but potentially more efficient. */ fn push_all(ts: &[const A]) { self.push_slice(ts, 0u, vec::len(ts)); } /// Appends elements from `from_idx` to `to_idx` (exclusive) fn push_slice(ts: &[const A], from_idx: uint, to_idx: uint) { do self.swap |v| { let mut v <- v; let new_len = vec::len(v) + to_idx - from_idx; vec::reserve(&mut v, new_len); let mut i = from_idx; while i < to_idx { v.push(ts[i]); i += 1u; } move v } } /** * Append all elements of an iterable. * * Failure will occur if the iterable's `each()` method * attempts to access this vector. */ /* fn append_iter>(ts: I) { do self.swap |v| { let mut v = match ts.size_hint() { none { v } Some(h) { let len = v.len() + h; let mut v <- v; vec::reserve(v, len); v } }; for ts.each |t| { v.push(*t) }; v } } */ /** * Gets a copy of the current contents. * * See `unwrap()` if you do not wish to copy the contents. */ pure fn get() -> ~[A] { unsafe { do self.check_out |v| { let w = copy v; self.give_back(move v); move w } } } /// Copy out an individual element #[inline(always)] pure fn get_elt(idx: uint) -> A { self.check_not_borrowed(); return self.data[idx]; } /// Overwrites the contents of the element at `idx` with `a` fn set_elt(idx: uint, +a: A) { self.check_not_borrowed(); self.data[idx] = a; } /** * Overwrites the contents of the element at `idx` with `a`, * growing the vector if necessary. New elements will be initialized * with `initval` */ fn grow_set_elt(idx: uint, initval: A, +val: A) { do self.swap |v| { let mut v = move v; vec::grow_set(v, idx, initval, val); move v } } /// Returns the last element, failing if the vector is empty #[inline(always)] pure fn last() -> A { self.check_not_borrowed(); let length = self.len(); if length == 0 { fail ~"attempt to retrieve the last element of an empty vector"; } return self.data[length - 1]; } /// Iterates over the elements in reverse order #[inline(always)] fn rev_each(f: fn(v: &A) -> bool) { do self.swap |v| { // FIXME(#2263)---we should be able to write // `vec::rev_each(v, f);` but we cannot write now for vec::rev_each(v) |e| { if !f(e) { break; } } move v } } /// Iterates over the elements and indices in reverse order #[inline(always)] fn rev_eachi(f: fn(uint, v: &A) -> bool) { do self.swap |v| { // FIXME(#2263)---we should be able to write // `vec::rev_eachi(v, f);` but we cannot write now for vec::rev_eachi(v) |i, e| { if !f(i, e) { break; } } move v } } } impl DVec: Index { pure fn index(+idx: uint) -> A { self.get_elt(idx) } }