1
Fork 0

std -- replaces uses where const borrows would be required

This commit is contained in:
Niko Matsakis 2014-02-07 06:33:11 -05:00
parent be3cbcb431
commit 852a49fd9c
3 changed files with 125 additions and 70 deletions

View file

@ -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`

View file

@ -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]

View file

@ -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
} }
} }