about summary refs log tree commit diff
path: root/src/libcore/util.rs
blob: 43616ebfd3032fda9ef5a6668eaaf963063709ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

Miscellaneous helpers for common patterns.

*/

use prelude::*;

/// The identity function.
#[inline(always)]
pub fn id<T>(x: T) -> T { x }

/// Ignores a value.
#[inline(always)]
pub fn ignore<T>(_x: T) { }

/// Sets `*ptr` to `new_value`, invokes `op()`, and then restores the
/// original value of `*ptr`.
///
/// NB: This function accepts `@mut T` and not `&mut T` to avoid
/// an obvious borrowck hazard. Typically passing in `&mut T` will
/// cause borrow check errors because it freezes whatever location
/// that `&mut T` is stored in (either statically or dynamically).
#[inline(always)]
pub fn with<T,R>(
    ptr: @mut T,
    mut value: T,
    op: &fn() -> R) -> R
{
    value <-> *ptr;
    let result = op();
    *ptr = value;
    return result;
}

/**
 * Swap the values at two mutable locations of the same type, without
 * deinitialising or copying either one.
 */
#[inline(always)]
pub fn swap<T>(x: &mut T, y: &mut T) {
    *x <-> *y;
}

/**
 * Replace the value at a mutable location with a new one, returning the old
 * value, without deinitialising or copying either one.
 */
#[inline(always)]
pub fn replace<T>(dest: &mut T, src: T) -> T {
    let mut tmp = src;
    swap(dest, &mut tmp);
    tmp
}

/// A non-copyable dummy type.
pub struct NonCopyable {
    i: (),
}

impl Drop for NonCopyable {
    fn finalize(&self) { }
}

pub fn NonCopyable() -> NonCopyable { NonCopyable { i: () } }

/**
A utility function for indicating unreachable code. It will fail if
executed. This is occasionally useful to put after loops that never
terminate normally, but instead directly return from a function.

# Example

~~~
fn choose_weighted_item(v: &[Item]) -> Item {
    assert!(!v.is_empty());
    let mut so_far = 0u;
    for v.each |item| {
        so_far += item.weight;
        if so_far > 100 {
            return item;
        }
    }
    // The above loop always returns, so we must hint to the
    // type checker that it isn't possible to get down here
    util::unreachable();
}
~~~

*/
pub fn unreachable() -> ! {
    fail!(~"internal error: entered unreachable code");
}

#[cfg(test)]
mod tests {
    use option::{None, Some};
    use util::{NonCopyable, id, replace, swap};

    #[test]
    pub fn identity_crisis() {
        // Writing a test for the identity function. How did it come to this?
        let x = ~[(5, false)];
        //FIXME #3387 assert!(x.eq(id(copy x)));
        let y = copy x;
        assert!(x.eq(&id(y)));
    }
    #[test]
    pub fn test_swap() {
        let mut x = 31337;
        let mut y = 42;
        swap(&mut x, &mut y);
        assert!(x == 42);
        assert!(y == 31337);
    }
    #[test]
    pub fn test_replace() {
        let mut x = Some(NonCopyable());
        let y = replace(&mut x, None);
        assert!(x.is_none());
        assert!(y.is_some());
    }
}