std -- replaces uses where const borrows would be required
This commit is contained in:
parent
be3cbcb431
commit
852a49fd9c
3 changed files with 125 additions and 70 deletions
|
@ -277,7 +277,7 @@ use str::{StrSlice, OwnedStr};
|
||||||
use str;
|
use str;
|
||||||
use to_str::ToStr;
|
use to_str::ToStr;
|
||||||
use uint;
|
use uint;
|
||||||
use unstable::finally::Finally;
|
use unstable::finally::try_finally;
|
||||||
use vec::{OwnedVector, MutableVector, ImmutableVector, OwnedCloneableVector};
|
use vec::{OwnedVector, MutableVector, ImmutableVector, OwnedCloneableVector};
|
||||||
use vec;
|
use vec;
|
||||||
|
|
||||||
|
@ -473,25 +473,33 @@ pub trait Reader {
|
||||||
/// pushed on to the vector, otherwise the amount `len` bytes couldn't be
|
/// pushed on to the vector, otherwise the amount `len` bytes couldn't be
|
||||||
/// read (an error was encountered), and the error is returned.
|
/// read (an error was encountered), and the error is returned.
|
||||||
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) -> IoResult<()> {
|
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) -> IoResult<()> {
|
||||||
|
struct State<'a> {
|
||||||
|
buf: &'a mut ~[u8],
|
||||||
|
total_read: uint
|
||||||
|
}
|
||||||
|
|
||||||
let start_len = buf.len();
|
let start_len = buf.len();
|
||||||
let mut total_read = 0;
|
let mut s = State { buf: buf, total_read: 0 };
|
||||||
|
|
||||||
buf.reserve_additional(len);
|
s.buf.reserve_additional(len);
|
||||||
unsafe { buf.set_len(start_len + len); }
|
unsafe { s.buf.set_len(start_len + len); }
|
||||||
|
|
||||||
(|| {
|
try_finally(
|
||||||
while total_read < len {
|
&mut s, (),
|
||||||
let len = buf.len();
|
|s, _| {
|
||||||
let slice = buf.mut_slice(start_len + total_read, len);
|
while s.total_read < len {
|
||||||
match self.read(slice) {
|
let len = s.buf.len();
|
||||||
Ok(nread) => {
|
let slice = s.buf.mut_slice(start_len + s.total_read, len);
|
||||||
total_read += nread;
|
match self.read(slice) {
|
||||||
|
Ok(nread) => {
|
||||||
|
s.total_read += nread;
|
||||||
|
}
|
||||||
|
Err(e) => return Err(e)
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e)
|
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
Ok(())
|
},
|
||||||
}).finally(|| unsafe { buf.set_len(start_len + total_read) })
|
|s| unsafe { s.buf.set_len(start_len + s.total_read) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads `len` bytes and gives you back a new vector of length `len`
|
/// Reads `len` bytes and gives you back a new vector of length `len`
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
The Finally trait provides a method, `finally` on
|
The Finally trait provides a method, `finally` on
|
||||||
stack closures that emulates Java-style try/finally blocks.
|
stack closures that emulates Java-style try/finally blocks.
|
||||||
|
|
||||||
|
Using the `finally` method is sometimes convenient, but the type rules
|
||||||
|
prohibit any shared, mutable state between the "try" case and the
|
||||||
|
"finally" case. For advanced cases, the `try_finally` function can
|
||||||
|
also be used. See that function for more details.
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -31,53 +36,89 @@ pub trait Finally<T> {
|
||||||
fn finally(&self, dtor: ||) -> T;
|
fn finally(&self, dtor: ||) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! finally_fn {
|
|
||||||
($fnty:ty) => {
|
|
||||||
impl<T> Finally<T> for $fnty {
|
|
||||||
fn finally(&self, dtor: ||) -> T {
|
|
||||||
let _d = Finallyalizer {
|
|
||||||
dtor: dtor
|
|
||||||
};
|
|
||||||
(*self)()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T> Finally<T> for 'a || -> T {
|
impl<'a,T> Finally<T> for 'a || -> T {
|
||||||
fn finally(&self, dtor: ||) -> T {
|
fn finally(&self, dtor: ||) -> T {
|
||||||
let _d = Finallyalizer {
|
try_finally(&mut (), (),
|
||||||
dtor: dtor
|
|_, _| (*self)(),
|
||||||
};
|
|_| dtor())
|
||||||
|
|
||||||
(*self)()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finally_fn!(extern "Rust" fn() -> T)
|
impl<T> Finally<T> for fn() -> T {
|
||||||
|
fn finally(&self, dtor: ||) -> T {
|
||||||
|
try_finally(&mut (), (),
|
||||||
|
|_, _| (*self)(),
|
||||||
|
|_| dtor())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Finallyalizer<'a> {
|
/**
|
||||||
dtor: 'a ||
|
* The most general form of the `finally` functions. The function
|
||||||
|
* `try_fn` will be invoked first; whether or not it fails, the
|
||||||
|
* function `finally_fn` will be invoked next. The two parameters
|
||||||
|
* `mutate` and `drop` are used to thread state through the two
|
||||||
|
* closures. `mutate` is used for any shared, mutable state that both
|
||||||
|
* closures require access to; `drop` is used for any state that the
|
||||||
|
* `try_fn` requires ownership of.
|
||||||
|
*
|
||||||
|
* **WARNING:** While shared, mutable state between the try and finally
|
||||||
|
* function is often necessary, one must be very careful; the `try`
|
||||||
|
* function could have failed at any point, so the values of the shared
|
||||||
|
* state may be inconsistent.
|
||||||
|
*
|
||||||
|
* # Example
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* struct State<'a> { buffer: &'a mut [u8], len: uint }
|
||||||
|
* let mut state = State { buffer: buf, len: 0 };
|
||||||
|
* try_finally(
|
||||||
|
* &mut state, (),
|
||||||
|
* |state, ()| {
|
||||||
|
* // use state.buffer, state.len
|
||||||
|
* }
|
||||||
|
* |state| {
|
||||||
|
* // use state.buffer, state.len to cleanup
|
||||||
|
* })
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
pub fn try_finally<T,U,R>(mutate: &mut T,
|
||||||
|
drop: U,
|
||||||
|
try_fn: |&mut T, U| -> R,
|
||||||
|
finally_fn: |&mut T|)
|
||||||
|
-> R {
|
||||||
|
let f = Finallyalizer {
|
||||||
|
mutate: mutate,
|
||||||
|
dtor: finally_fn,
|
||||||
|
};
|
||||||
|
try_fn(&mut *f.mutate, drop)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Finallyalizer<'a,A> {
|
||||||
|
mutate: &'a mut A,
|
||||||
|
dtor: 'a |&mut A|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<'a> Drop for Finallyalizer<'a> {
|
impl<'a,A> Drop for Finallyalizer<'a,A> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
(self.dtor)();
|
(self.dtor)(self.mutate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_success() {
|
fn test_success() {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
(|| {
|
try_finally(
|
||||||
i = 10;
|
&mut i, (),
|
||||||
}).finally(|| {
|
|i, ()| {
|
||||||
assert!(!failing());
|
*i = 10;
|
||||||
assert_eq!(i, 10);
|
},
|
||||||
i = 20;
|
|i| {
|
||||||
});
|
assert!(!failing());
|
||||||
|
assert_eq!(*i, 10);
|
||||||
|
*i = 20;
|
||||||
|
});
|
||||||
assert_eq!(i, 20);
|
assert_eq!(i, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,13 +126,16 @@ fn test_success() {
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn test_fail() {
|
fn test_fail() {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
(|| {
|
try_finally(
|
||||||
i = 10;
|
&mut i, (),
|
||||||
fail!();
|
|i, ()| {
|
||||||
}).finally(|| {
|
*i = 10;
|
||||||
assert!(failing());
|
fail!();
|
||||||
assert_eq!(i, 10);
|
},
|
||||||
})
|
|i| {
|
||||||
|
assert!(failing());
|
||||||
|
assert_eq!(*i, 10);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -119,7 +119,8 @@ use mem;
|
||||||
use mem::size_of;
|
use mem::size_of;
|
||||||
use kinds::marker;
|
use kinds::marker;
|
||||||
use uint;
|
use uint;
|
||||||
use unstable::finally::Finally;
|
use unstable::finally::try_finally;
|
||||||
|
use unstable::intrinsics;
|
||||||
use unstable::raw::{Repr, Slice, Vec};
|
use unstable::raw::{Repr, Slice, Vec};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,15 +133,16 @@ pub fn from_fn<T>(n_elts: uint, op: |uint| -> T) -> ~[T] {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut v = with_capacity(n_elts);
|
let mut v = with_capacity(n_elts);
|
||||||
let p = v.as_mut_ptr();
|
let p = v.as_mut_ptr();
|
||||||
let mut i: uint = 0u;
|
let mut i = 0;
|
||||||
(|| {
|
try_finally(
|
||||||
while i < n_elts {
|
&mut i, (),
|
||||||
mem::move_val_init(&mut(*ptr::mut_offset(p, i as int)), op(i));
|
|i, ()| while *i < n_elts {
|
||||||
i += 1u;
|
mem::move_val_init(
|
||||||
}
|
&mut(*ptr::mut_offset(p, *i as int)),
|
||||||
}).finally(|| {
|
op(*i));
|
||||||
v.set_len(i);
|
*i += 1u;
|
||||||
});
|
},
|
||||||
|
|i| v.set_len(*i));
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,14 +162,15 @@ pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> ~[T] {
|
||||||
let mut v = with_capacity(n_elts);
|
let mut v = with_capacity(n_elts);
|
||||||
let p = v.as_mut_ptr();
|
let p = v.as_mut_ptr();
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
(|| {
|
try_finally(
|
||||||
while i < n_elts {
|
&mut i, (),
|
||||||
mem::move_val_init(&mut(*ptr::mut_offset(p, i as int)), t.clone());
|
|i, ()| while *i < n_elts {
|
||||||
i += 1u;
|
mem::move_val_init(
|
||||||
}
|
&mut(*ptr::mut_offset(p, *i as int)),
|
||||||
}).finally(|| {
|
t.clone());
|
||||||
v.set_len(i);
|
*i += 1u;
|
||||||
});
|
},
|
||||||
|
|i| v.set_len(*i));
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue