<commit_before>/// The Toml Set extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use tokenizer::Token;
use error::*;

pub trait TomlValueSetExt {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &String, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

}

impl TomlValueSetExt for Value {

    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last = tokens.pop_last();

        let mut val = try!(resolve(self, &tokens));
        let last = last.unwrap_or_else(|| Box::new(tokens));

        match *last {
            Token::Identifier { ident, .. } => {
                match val {
                    &mut Value::Table(ref mut t) => {
                        Ok(t.insert(ident, value))
                    }
                    _ => unimplemented!()
                }
            }

            Token::Index { idx, .. } => {
                match val {
                    &mut Value::Array(ref mut a) => {
                        if a.len() > idx {
                            let result = a.swap_remove(idx);
                            a.insert(idx, value);
                            Ok(Some(result))
                        } else {
                            a.push(value);
                            Ok(None)
                        }
                    }
                    _ => unimplemented!()
                }
            }

        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_key_nonexistent() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());
        let res = res.unwrap();

        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_index_nonexistent() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_table() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::IdentifierNotFoundInDocument(_)));
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_array() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("[0]"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::NoIndexInTable(0)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_ary() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::NoIdentifierInArray(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_table() {
        let mut toml : Value = toml_from_str(r#"
        foo = { bar = 1 }
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::NoIndexInTable(_)));
    }

}

<commit_msg>Impl Value::set_with_seperator to fix test_set_with_seperator_ident_into_ary<commit_after>/// The Toml Set extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use tokenizer::Token;
use error::*;

pub trait TomlValueSetExt {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &String, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

}

impl TomlValueSetExt for Value {

    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last = tokens.pop_last();

        let mut val = try!(resolve(self, &tokens));
        let last = last.unwrap_or_else(|| Box::new(tokens));

        match *last {
            Token::Identifier { ident, .. } => {
                match val {
                    &mut Value::Table(ref mut t) => {
                        Ok(t.insert(ident, value))
                    },
                    &mut Value::Array(_) => {
                        let kind = ErrorKind::NoIdentifierInArray(ident);
                        Err(Error::from(kind))
                    }
                    _ => unimplemented!()
                }
            }

            Token::Index { idx, .. } => {
                match val {
                    &mut Value::Array(ref mut a) => {
                        if a.len() > idx {
                            let result = a.swap_remove(idx);
                            a.insert(idx, value);
                            Ok(Some(result))
                        } else {
                            a.push(value);
                            Ok(None)
                        }
                    }
                    _ => unimplemented!()
                }
            }

        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_key_nonexistent() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());
        let res = res.unwrap();

        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_index_nonexistent() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_table() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::IdentifierNotFoundInDocument(_)));
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_array() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("[0]"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::NoIndexInTable(0)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_ary() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::NoIdentifierInArray(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_table() {
        let mut toml : Value = toml_from_str(r#"
        foo = { bar = 1 }
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::NoIndexInTable(_)));
    }

}

<|endoftext|>


<commit_before>use super::board::{Field, HEIGHT, WIDTH};
use super::tetromino::{
	Direction,
    Point,
    Rotation,
    Tetromino,
    TetrominoType,
};

/// Rotates a Tetromino located inside a field in a specified direction
pub fn rotate(field: &Field, tetromino: &Tetromino, dir: Direction) -> Option<(Field, Tetromino)> {
    let mut field = field.clone();

    // Remove the original piece from the field. Since we cloned the field,
    // we are able to freely manipulate it without worry. Assuming the
    // rotation is possible, this will make performing it easier later on
    erase(&mut field, &tetromino);

    // Rotate the piece if possible
    match is_rotatable(&field, &tetromino, dir) {
        Some(rotated) => {
            do_rotation(&mut field, &rotated);
            Some((field, rotated))
        },

        None => None,
    }
}

/// Erases a Tetromino from a field
fn erase(field: &mut Field, tetromino: &Tetromino) {
    for &mino in tetromino.minos.iter() {
        let pos = Point::new(tetromino.pos.x + mino.x, tetromino.pos.y + mino.y);
        field[pos.y as usize][pos.x as usize] = None;
    }
}

/// Determines if a Tetromino is rotatable within a specified field
fn is_rotatable(field: &Field, tetromino: &Tetromino, dir: Direction) -> Option<Tetromino> {
    let rotated = next_rotated_tetromino(tetromino, dir);

    for &mino in rotated.minos.iter() {
        let pos = Point::new(tetromino.pos.x + mino.x, tetromino.pos.y + mino.y);
        if pos.x < 0 || pos.y < 0 || pos.x as usize >= WIDTH  || pos.y as usize >= HEIGHT {
            return None;
        }
    }

    Some(rotated)
}

/// Performs the actual rotation
fn do_rotation(field: &mut Field, rotated: &Tetromino) {
    for &mino in rotated.minos.iter() {
        let pos = Point::new(rotated.pos.x + mino.x, rotated.pos.y + mino.y);
        field[pos.y as usize][pos.x as usize] = Some(rotated.tetro_type.clone());
    }
}

/// Gets the next rotation of a Tetromino in a specified direction
fn next_rotated_tetromino(tetromino: &Tetromino, dir: Direction) -> Tetromino {
    let rot = match dir {
        Direction::Clockwise => {
            match tetromino.rot {
                Rotation::Spawn => Rotation::Right,
                Rotation::Right => Rotation::Rot2,
                Rotation::Rot2  => Rotation::Left,
                Rotation::Left  => Rotation::Spawn,
            }
        },

        Direction::CounterClockwise => {
            match tetromino.rot {
                Rotation::Spawn => Rotation::Left,
                Rotation::Right => Rotation::Spawn,
                Rotation::Rot2  => Rotation::Right,
                Rotation::Left  => Rotation::Rot2,
            }
        }
    };

    Tetromino::new(tetromino.pos, tetromino.tetro_type, rot)
}

const TESTS: usize = 5;
const DIRECTIONS: usize = 2;
const ROTS: usize = 4;

// Wall kick data as specified by the Super Rotation System
const WALL_KICKS: [[[Point; TESTS]; DIRECTIONS]; ROTS] = [SPAWN_WK, RIGHT_WK, ROT2_WK, LEFT_WK];
const WALL_KICKS_I: [[[Point; TESTS]; DIRECTIONS]; ROTS] = [SPAWN_WK_I, RIGHT_WK_I, ROT2_WK_I, LEFT_WK_I];

// The wall kick data for J, L, O, S, T, and Z
const SPAWN_WK: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x: -1, y: -1 },
        Point { x:  0, y:  2 },
        Point { x: -1, y:  2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x:  1, y: -1 },
        Point { x:  0, y:  2 },
        Point { x:  1, y:  2 },
    ]
];

const RIGHT_WK: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x:  1, y:  1 },
        Point { x:  0, y: -2 },
        Point { x:  1, y: -2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x:  1, y:  1 },
        Point { x:  0, y: -2 },
        Point { x:  1, y: -2 },
    ]
];

const ROT2_WK: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x:  1, y: -1 },
        Point { x:  0, y:  2 },
        Point { x:  1, y:  2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x: -1, y: -1 },
        Point { x:  0, y:  2 },
        Point { x: -1, y:  2 },
    ]
];

const LEFT_WK: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x: -1, y:  1 },
        Point { x:  0, y: -2 },
        Point { x: -1, y: -2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x: -1, y:  1 },
        Point { x:  0, y:  2 },
        Point { x: -1, y: -2 },
    ]
];

// The wall kick data for I
const SPAWN_WK_I: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x: -2, y:  0 },
        Point { x:  1, y:  0 },
        Point { x: -2, y:  1 },
        Point { x:  1, y: -2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y: -2 },
        Point { x:  2, y:  1 },
    ]
];

const RIGHT_WK_I: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y: -2 },
        Point { x:  2, y:  1 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y:  1 },
        Point { x: -1, y:  2 },
    ]
];

const ROT2_WK_I: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y: -1 },
        Point { x: -1, y:  2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x: -2, y:  0 },
        Point { x:  1, y:  2 },
        Point { x: -2, y: -1 },
    ]
];

const LEFT_WK_I: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x: -2, y:  0 },
        Point { x:  1, y:  2 },
        Point { x: -2, y: -1 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y: -2 },
        Point { x:  2, y:  1 },
    ]
];<commit_msg>Prevent rotations if the mino positions to be rotated to are already occupied<commit_after>use super::board::{Field, HEIGHT, WIDTH};
use super::tetromino::{
    Direction,
    Point,
    Rotation,
    Tetromino,
    TetrominoType,
};

/// Rotates a Tetromino located inside a field in a specified direction
pub fn rotate(field: &Field, tetromino: &Tetromino, dir: Direction) -> Option<(Field, Tetromino)> {
    let mut field = field.clone();

    // Remove the original piece from the field. Since we cloned the field,
    // we are able to freely manipulate it without worry. Assuming the
    // rotation is possible, this will make performing it easier later on
    erase(&mut field, &tetromino);

    // Rotate the piece if possible
    match is_rotatable(&field, &tetromino, dir) {
        Some(rotated) => {
            do_rotation(&mut field, &rotated);
            Some((field, rotated))
        },

        None => None,
    }
}

/// Erases a Tetromino from a field
fn erase(field: &mut Field, tetromino: &Tetromino) {
    for &mino in tetromino.minos.iter() {
        let pos = Point::new(tetromino.pos.x + mino.x, tetromino.pos.y + mino.y);
        field[pos.y as usize][pos.x as usize] = None;
    }
}

/// Determines if a Tetromino is rotatable within a specified field. Returns the rotated
/// Tetromino if the rotation is possible
fn is_rotatable(field: &Field, tetromino: &Tetromino, dir: Direction) -> Option<Tetromino> {
    let rotated = next_rotated_tetromino(tetromino, dir);

    for &mino in rotated.minos.iter() {
        let pos = Point::new(tetromino.pos.x + mino.x, tetromino.pos.y + mino.y);

        // Determine if it is possible for the rotated mino to move to the new position.
        // If the new position is outside the bounds or is already occupied, then it is
        // not possible and the entire rotation fails
        if pos.x < 0 || pos.y < 0 || pos.x as usize >= WIDTH  || pos.y as usize >= HEIGHT
                || field[pos.y as usize][pos.x as usize].is_some() {
            return None;
        }
    }

    Some(rotated)
}

/// Performs the actual rotation
fn do_rotation(field: &mut Field, rotated: &Tetromino) {
    for &mino in rotated.minos.iter() {
        let pos = Point::new(rotated.pos.x + mino.x, rotated.pos.y + mino.y);
        field[pos.y as usize][pos.x as usize] = Some(rotated.tetro_type.clone());
    }
}

/// Gets the next rotation of a Tetromino in a specified direction
fn next_rotated_tetromino(tetromino: &Tetromino, dir: Direction) -> Tetromino {
    let rot = match dir {
        Direction::Clockwise => {
            match tetromino.rot {
                Rotation::Spawn => Rotation::Right,
                Rotation::Right => Rotation::Rot2,
                Rotation::Rot2  => Rotation::Left,
                Rotation::Left  => Rotation::Spawn,
            }
        },

        Direction::CounterClockwise => {
            match tetromino.rot {
                Rotation::Spawn => Rotation::Left,
                Rotation::Right => Rotation::Spawn,
                Rotation::Rot2  => Rotation::Right,
                Rotation::Left  => Rotation::Rot2,
            }
        }
    };

    Tetromino::new(tetromino.pos, tetromino.tetro_type, rot)
}

const TESTS: usize = 5;
const DIRECTIONS: usize = 2;
const ROTS: usize = 4;

// Wall kick data as specified by the Super Rotation System
const WALL_KICKS: [[[Point; TESTS]; DIRECTIONS]; ROTS] = [SPAWN_WK, RIGHT_WK, ROT2_WK, LEFT_WK];
const WALL_KICKS_I: [[[Point; TESTS]; DIRECTIONS]; ROTS] = [SPAWN_WK_I, RIGHT_WK_I, ROT2_WK_I, LEFT_WK_I];

// The wall kick data for J, L, O, S, T, and Z
const SPAWN_WK: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x: -1, y: -1 },
        Point { x:  0, y:  2 },
        Point { x: -1, y:  2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x:  1, y: -1 },
        Point { x:  0, y:  2 },
        Point { x:  1, y:  2 },
    ]
];

const RIGHT_WK: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x:  1, y:  1 },
        Point { x:  0, y: -2 },
        Point { x:  1, y: -2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x:  1, y:  1 },
        Point { x:  0, y: -2 },
        Point { x:  1, y: -2 },
    ]
];

const ROT2_WK: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x:  1, y: -1 },
        Point { x:  0, y:  2 },
        Point { x:  1, y:  2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x: -1, y: -1 },
        Point { x:  0, y:  2 },
        Point { x: -1, y:  2 },
    ]
];

const LEFT_WK: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x: -1, y:  1 },
        Point { x:  0, y: -2 },
        Point { x: -1, y: -2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x: -1, y:  1 },
        Point { x:  0, y:  2 },
        Point { x: -1, y: -2 },
    ]
];

// The wall kick data for I
const SPAWN_WK_I: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x: -2, y:  0 },
        Point { x:  1, y:  0 },
        Point { x: -2, y:  1 },
        Point { x:  1, y: -2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y: -2 },
        Point { x:  2, y:  1 },
    ]
];

const RIGHT_WK_I: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y: -2 },
        Point { x:  2, y:  1 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y:  1 },
        Point { x: -1, y:  2 },
    ]
];

const ROT2_WK_I: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y: -1 },
        Point { x: -1, y:  2 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x: -2, y:  0 },
        Point { x:  1, y:  2 },
        Point { x: -2, y: -1 },
    ]
];

const LEFT_WK_I: [[Point; TESTS]; DIRECTIONS] = [
    [
        Point { x:  0, y:  0 },
        Point { x:  1, y:  0 },
        Point { x: -2, y:  0 },
        Point { x:  1, y:  2 },
        Point { x: -2, y: -1 },
    ],

    [
        Point { x:  0, y:  0 },
        Point { x: -1, y:  0 },
        Point { x:  2, y:  0 },
        Point { x: -1, y: -2 },
        Point { x:  2, y:  1 },
    ]
];<|endoftext|>


<commit_before>#![allow(dead_code)]
use core::mem;

/// A Multiboot tag structure is just a queryable blob of bytes. The implementation presently
/// assumes that the size is at least 8 bytes (for the end tag), and does not check this.
const BOOT_COMMAND_LINE: u32   = 1;
const BOOT_LOADER_NAME: u32    = 2;
const MODULE: u32            = 3;
const MEMORY_INFORMATION: u32 = 4;
const BIOS_BOOT_DEVICE: u32    = 5;
const MEMORY_MAP: u32         = 6;
const VBE_INFO: u32           = 7;
const FRAME_BUFFER_INFO: u32   = 8;
const ELF_SYMBOLS: u32        = 9;
const APM_TABLE: u32          = 10;

#[repr(C)]
struct Tag {
	// Pointer to the first byte of the Tag block.
	ptr: *const u8,
}

impl Tag {
	fn tag_type(&self) -> u32 {
		let ptr = self.ptr as *const u32;
		unsafe {
			*ptr
		}
	}

	fn size(&self) -> u32 {
		let ptr = ((self.ptr as usize) + 4) as *const u32;
		unsafe {
			*ptr
		}
	}
}<commit_msg>Add tag iterator to fetch multiboot tag information.<commit_after>#![allow(dead_code)]
/// A Multiboot tag structure is just a queryable blob of bytes. The implementation presently
/// assumes that the size is at least 8 bytes (for the end tag), and does not check this.
pub enum TagType {
	BootCommandLine   = 1,
	BootLoaderName    = 2,
	Module            = 3,
	MemoryInformation = 4,
	BiosBootDevice    = 5,
	MemoryMap         = 6,
	VBEInfo           = 7,
	FrameBufferInfo   = 8,
	ElfSymbols        = 9,
	APMTable          = 10,
}

#[repr(C)]
struct Tag {
	tag_type: u32,
	size: u32,
	// The tag data follows these two fields.
}

struct TagIter {
	current: *const Tag
}

impl Iterator for TagIter {
	type Item = &'static Tag;

	fn next(&mut self) -> Option<&'static Tag> {
		let current = unsafe { &*self.current };
		match current {
			&Tag { tag_type: 0, size: 8 } => None, // End tag.
			tag => {
				// Jump to the next tag.
				let mut tag_address = self.current as usize;
				tag_address += tag.size as usize;
				tag_address = ((tag_address - 1) & !0x07) + 0x08;
				self.current = tag_address as *const Tag;

				Some(tag)
			}
		}
	}
}<|endoftext|>


<commit_before>use libc;

#[allow(non_camel_case_types)]
pub type size_t = ::std::os::raw::c_ulong;

#[allow(non_camel_case_types)]
#[derive(Debug)]
pub enum Struct___locale_map { }

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug)]
pub struct Struct___locale_struct {
    pub cat: [*const Struct___locale_map; 6usize],
}

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug)]
pub struct tls_module {
    pub next: *mut tls_module,
    pub image: *mut ::std::os::raw::c_void,
    pub len: size_t,
    pub size: size_t,
    pub align: size_t,
    pub offset: size_t,
}

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug)]
pub struct __libc {
    pub can_do_threads: ::std::os::raw::c_int,
    pub threaded: ::std::os::raw::c_int,
    pub secure: ::std::os::raw::c_int,
    pub threads_minus_1: ::std::os::raw::c_int,
    pub auxv: *mut size_t,
    pub tls_head: *mut tls_module,
    pub tls_size: size_t,
    pub tls_align: size_t,
    pub tls_cnt: size_t,
    pub page_size: size_t,
    pub global_locale: Struct___locale_struct,
}

extern {
    pub static mut __libc: __libc;
}

// example of tls init structure for libc
/*
l_tls_initimage = 0x7ffff7bb2788,
l_tls_initimage_size = 16,
l_tls_blocksize = 120,
l_tls_align = 8,
l_tls_firstbyte_offset = 0,
l_tls_offset = 128,
l_tls_modid = 2,
l_tls_dtor_count = 0,
*/

#[derive(Debug, Clone, Copy)]
pub struct TlsInfo {
    pub blocksize: usize, // actual memory size ph_memsz
    pub align: usize,
    pub offset: isize,
    pub modid: u32,
    pub firstbyte_offset: usize,
    pub image: usize,
    pub image_size: usize,
}

impl TlsInfo {
    pub fn new (){
        unimplemented!();
    }
}

/// Memset yo!
unsafe fn memset(ptr: *mut u8, byte: u8, size: usize) {
    let mut i = 0;
    while i < size {
        *ptr.offset(i as isize) = byte;
        i += 1;
    }
}

// glibc api
// always remember, for x86_64: TLS_TCB_AT_TP
// the TCB follows the TLS blocks

#[repr(C)]
#[derive(Debug)]
struct Pointer {
    val: *mut libc::c_void,
    is_static: bool
}

#[repr(C)]
#[derive(Debug)]
struct Dtv {
    counter: usize,
    pointer: Pointer
}

pub const SIZEOF_DTV: usize = 0x10;

#[inline(always)]
unsafe fn get_dtv(tls_storage: *mut libc::c_void) -> *mut Dtv {
    let descr_dtv = tls_storage.offset(1) as *mut *mut Dtv;
    *descr_dtv
}

#[inline(always)]
/// Installs the dtv in the tcbhead_t struct, which is the second element; we hack it for now by simply casting and setting the offset; see `sysdeps/x86_64/nptl/tls.h:128`
unsafe fn install_dtv(tls_storage: *mut libc::c_void, dtv: *mut Dtv) {
    let descr_dtv = tls_storage.offset(1) as *mut *mut Dtv;
    *descr_dtv = dtv.offset(1);
}

unsafe fn allocate_dtv (tls_storage: *mut libc::c_void) -> *mut libc::c_void {
    let dtv_len = 2 + DTV_SURPLUS;
    let dtv = libc::calloc(dtv_len + 2, SIZEOF_DTV as libc::size_t) as *mut Dtv;
    if !dtv.is_null() {
        // hehe surries!
        (*dtv.offset(0)).counter = dtv_len;
        install_dtv(tls_storage, dtv);
        tls_storage
    } else {
        ::std::ptr::null_mut::<libc::c_void>()
    }
}

pub unsafe fn _dl_allocate_tls_storage () -> *mut libc::c_void {
    let mut result = libc::memalign(TLS_STATIC_SIZE, TLS_STATIC_ALIGN);
    let allocated = result; // to be used by free in case fails, unimplemented
    result = result.offset(TLS_STATIC_SIZE as isize - TLS_TCB_SIZE as isize);
    memset(result as *mut u8, 0x0, TLS_TCB_SIZE);
    allocate_dtv(result)
}

pub const TLS_STATIC_SIZE: libc::size_t = 0x1000;
pub const TLS_STATIC_ALIGN: libc::size_t = 0x40;
pub const TLS_STATIC_ALIGN_MASK: libc::size_t = !(TLS_STATIC_ALIGN - 1);
// sizeof (struct pthread)
pub const TLS_TCB_SIZE: libc::size_t = 0x900;
// ±sysdeps/generic/ldsodefs.h:402
pub const DTV_SURPLUS: libc::size_t = 14;
<commit_msg>tls: add dbgc prints, add unimplemented methods, and more research into order and which functions need to call; add initial struct for an object based implementation of the thread initializer<commit_after>use libc;

#[allow(non_camel_case_types)]
pub type size_t = ::std::os::raw::c_ulong;

#[allow(non_camel_case_types)]
#[derive(Debug)]
pub enum Struct___locale_map { }

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug)]
pub struct Struct___locale_struct {
    pub cat: [*const Struct___locale_map; 6usize],
}

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug)]
pub struct tls_module {
    pub next: *mut tls_module,
    pub image: *mut ::std::os::raw::c_void,
    pub len: size_t,
    pub size: size_t,
    pub align: size_t,
    pub offset: size_t,
}

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug)]
pub struct __libc {
    pub can_do_threads: ::std::os::raw::c_int,
    pub threaded: ::std::os::raw::c_int,
    pub secure: ::std::os::raw::c_int,
    pub threads_minus_1: ::std::os::raw::c_int,
    pub auxv: *mut size_t,
    pub tls_head: *mut tls_module,
    pub tls_size: size_t,
    pub tls_align: size_t,
    pub tls_cnt: size_t,
    pub page_size: size_t,
    pub global_locale: Struct___locale_struct,
}

extern {
    pub static mut __libc: __libc;
}

// example of tls init structure for libc
/*
l_tls_initimage = 0x7ffff7bb2788,
l_tls_initimage_size = 16,
l_tls_blocksize = 120,
l_tls_align = 8,
l_tls_firstbyte_offset = 0,
l_tls_offset = 128,
l_tls_modid = 2,
l_tls_dtor_count = 0,
*/

#[derive(Debug, Clone, Copy)]
pub struct TlsInfo {
    pub blocksize: usize, // actual memory size ph_memsz
    pub align: usize,
    pub offset: isize,
    pub modid: u32,
    pub firstbyte_offset: usize,
    pub image: usize,
    pub image_size: usize,
}

impl TlsInfo {
    pub fn new (){
        unimplemented!();
    }
}

/// Memset yo!
unsafe fn memset(ptr: *mut u8, byte: u8, size: usize) {
    let mut i = 0;
    while i < size {
        *ptr.offset(i as isize) = byte;
        i += 1;
    }
}

// glibc api
// always remember, for x86_64: TLS_TCB_AT_TP
// the TCB follows the TLS blocks

#[repr(C)]
#[derive(Debug)]
struct Pointer {
    val: *mut libc::c_void,
    is_static: bool
}

#[repr(C)]
#[derive(Debug)]
struct Dtv {
    counter: usize,
    pointer: Pointer
}

pub const SIZEOF_DTV: usize = 0x10;

#[inline(always)]
unsafe fn get_dtv(tls_storage: *mut libc::c_void) -> *mut Dtv {
    let descr_dtv = tls_storage.offset(1) as *mut *mut Dtv;
    dbgc!(purple_bold: true, "tls", "get_dtv: {:?}", **descr_dtv);
    *descr_dtv
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct DtvInfo {
    generation: u32,
    info: TlsInfo
}

#[inline(always)]
/// Installs the dtv in the tcbhead_t struct, which is the second element; we hack it for now by simply casting and setting the offset; see `sysdeps/x86_64/nptl/tls.h:128`
unsafe fn install_dtv(tls_storage: *mut libc::c_void, dtv: *mut Dtv) {
    let descr_dtv = tls_storage.offset(1) as *mut *mut Dtv;
    *descr_dtv = dtv.offset(1);
}

unsafe fn allocate_dtv (tls_storage: *mut libc::c_void) -> *mut libc::c_void {
    let dtv_len = 2 + DTV_SURPLUS;
    dbgc!(purple_bold: true, "tls", "allocate_dtv dtv_len: {:?}", dtv_len);
    let dtv = libc::calloc(dtv_len + 2, SIZEOF_DTV as libc::size_t) as *mut Dtv;
    dbgc!(purple_bold: true, "tls", "allocate_dtv calloc dtv: {:?}", dtv);
    if !dtv.is_null() {
        // hehe surries!
        (*dtv.offset(0)).counter = dtv_len;
        dbgc!(purple_bold: true, "tls", "allocate_dtv calloc dtv: {:?}", *dtv);
        install_dtv(tls_storage, dtv);
        dbgc!(purple_bold: true, "tls", "allocate_dtv calloc post install: {:?} dtv: {:?}", **(tls_storage.offset(1) as *mut *mut Dtv), *dtv);
        tls_storage
    } else {
        dbgc!(purple_bold: true, "tls", "allocate_dtv dtv is NULL");
        ::std::ptr::null_mut::<libc::c_void>()
    }
}

pub unsafe fn _dl_allocate_tls_storage () -> *mut libc::c_void {
    let mut result = libc::memalign(TLS_STATIC_SIZE, TLS_STATIC_ALIGN);
    dbgc!(purple_bold: true, "tls", "_dl_allocate_tls_storage result: {:?}", result);
    let allocated = result; // to be used by free in case fails, unimplemented
    result = result.offset(TLS_STATIC_SIZE as isize - TLS_TCB_SIZE as isize);
    dbgc!(purple_bold: true, "tls", "_dl_allocate_tls_storage post result: {:?}", result);
    memset(result as *mut u8, 0x0, TLS_TCB_SIZE);
    dbgc!(purple_bold: true, "tls", "_dl_allocate_tls_storage memset result: {:?}", result);
    allocate_dtv(result)
}

// TODO: finish
// dl-tls.c:448 _dl_allocate_tls_init (void *result)
// TODO: replace max_dtv_idx/modid and tls_clients with mut self
pub unsafe fn allocate_tls (max_dtv_idx: u32, tls_clients: Vec<DtvInfo>) -> *mut libc::c_void {
    let tls_storage = _dl_allocate_tls_storage ();
    if tls_storage.is_null() {
        panic!("Error: tls storage failed to allocate");
    }
    let dtv = get_dtv(tls_storage);
    // TODO: check if current dtv is large enough
    // do this by examining the len (which is 14 + whatever modules we loaded) and checking if it's smaller than our dtv_idx counter (basically last modid)
    // need to write a resize_dtv routine of course, too
    // and then call install_dtv
    let total = 0;
    let maxgen = 0;
    loop {
        let cnt = if total == 0 { 1 } else { 0 };
        for cnt in cnt..2 {
            if total + cnt > max_dtv_idx {
                break;
            }
//            maxgen = max(maxgen,
        }
        // TODO: remove after fixed
        break;
    }
    unimplemented!();
//    tls_storage
}

// TODO: finish
// dl-tls.c:137 _dl_determine_tlsoffset (void)
unsafe fn determine_offset(clients: &mut[DtvInfo]) {
    unimplemented!();
}

// TODO: finish
// sysdeps/x86_64/nptl/tls.h:148 TLS_INIT_TP(thrdescr)
unsafe fn tls_init_tp (tcbp: *mut libc::c_void) {
    unimplemented!();
}

// for special tls just for local process i believe, so it can access errno, etc.
// TODO: rtld.c:572 init_tls (void)
// 1. allocates the necessary tcbp
// 2. allocates the slot info list
// 3. sets the appropriate data into the slot info list (determine_offset)
// 4. and installs it via syscall tls_init_tp to the main thread
unsafe fn init_tls() {
    unimplemented!();
}

// final process
// 1. init_tls in main thread = dryad
// 2. load, relocate, etc.
// 3. allocate_tls_init (tcbp)
// 4. call TLS_INIT_TP

pub const TLS_STATIC_SIZE: libc::size_t = 0x1000;
pub const TLS_STATIC_ALIGN: libc::size_t = 0x40;
pub const TLS_STATIC_ALIGN_MASK: libc::size_t = !(TLS_STATIC_ALIGN - 1);
// sizeof (struct pthread)
pub const TLS_TCB_SIZE: libc::size_t = 0x900;
// sysdeps/generic/ldsodefs.h:402
pub const DTV_SURPLUS: libc::size_t = 14;
// sysdeps/generic/ldsodefs.h:399
pub const TLS_SLOTINFO_SURPLUS: libc::size_t = 62;

/// https://en.wikipedia.org/wiki/Lachesis_(mythology)
pub struct Lachesis {
    pub clients: Vec<DtvInfo>
}
<|endoftext|>


<commit_before>//! Endpoints for push notifications.

use std::convert::TryFrom;

use ruma_common::push::PushCondition;
use serde::{Deserialize, Serialize};
use strum::{Display, EnumString};

pub mod delete_pushrule;
pub mod get_notifications;
pub mod get_pushers;
pub mod get_pushrule;
pub mod get_pushrule_actions;
pub mod get_pushrule_enabled;
pub mod get_pushrules_all;
pub mod get_pushrules_global_scope;
pub mod set_pusher;
pub mod set_pushrule;
pub mod set_pushrule_actions;
pub mod set_pushrule_enabled;

/// The kinds of push rules that are available
#[derive(
    Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Display, EnumString,
)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum RuleKind {
    /// User-configured rules that override all other kinds
    Override,

    /// Lowest priority user-defined rules
    Underride,

    /// Sender-specific rules
    Sender,

    /// Room-specific rules
    Room,

    /// Content-specific rules
    Content,
}

impl TryFrom<&'_ str> for RuleKind {
    type Error = strum::ParseError;

    fn try_from(s: &str) -> Result<Self, Self::Error> {
        s.parse()
    }
}

/// Defines a pusher
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Pusher {
    /// This is a unique identifier for this pusher. Max length, 512 bytes.
    pub pushkey: String,

    /// The kind of the pusher. If set to None in a call to set_pusher, this
    /// will delete the pusher
    pub kind: Option<PusherKind>,

    /// This is a reverse-DNS style identifier for the application. Max length, 64 chars.
    pub app_id: String,

    /// A string that will allow the user to identify what application owns this pusher.
    pub app_display_name: String,

    /// A string that will allow the user to identify what device owns this pusher.
    pub device_display_name: String,

    /// This string determines which set of device specific rules this pusher executes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub profile_tag: Option<String>,

    /// The preferred language for receiving notifications (e.g. 'en' or 'en-US')
    pub lang: String,

    /// Information for the pusher implementation itself.
    pub data: PusherData,
}

/// Which kind a pusher is
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PusherKind {
    /// A pusher that sends HTTP pokes.
    Http,

    /// A pusher that emails the user with unread notifications.
    Email,
}

/// Information for the pusher implementation itself.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PusherData {
    /// Required if the pusher's kind is http. The URL to use to send notifications to.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub url: Option<String>,

    /// The format to use when sending notifications to the Push Gateway.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub format: Option<PushFormat>,
}

/// A special format that the homeserver should use when sending notifications to a Push Gateway.
/// Currently, only "event_id_only" is supported as of [Push Gateway API r0.1.1](https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour)
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PushFormat {
    /// Require the homeserver to only send a reduced set of fields in the push.
    EventIdOnly,
}
<commit_msg>Remove unused import<commit_after>//! Endpoints for push notifications.

use std::convert::TryFrom;

use serde::{Deserialize, Serialize};
use strum::{Display, EnumString};

pub mod delete_pushrule;
pub mod get_notifications;
pub mod get_pushers;
pub mod get_pushrule;
pub mod get_pushrule_actions;
pub mod get_pushrule_enabled;
pub mod get_pushrules_all;
pub mod get_pushrules_global_scope;
pub mod set_pusher;
pub mod set_pushrule;
pub mod set_pushrule_actions;
pub mod set_pushrule_enabled;

/// The kinds of push rules that are available
#[derive(
    Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Display, EnumString,
)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum RuleKind {
    /// User-configured rules that override all other kinds
    Override,

    /// Lowest priority user-defined rules
    Underride,

    /// Sender-specific rules
    Sender,

    /// Room-specific rules
    Room,

    /// Content-specific rules
    Content,
}

impl TryFrom<&'_ str> for RuleKind {
    type Error = strum::ParseError;

    fn try_from(s: &str) -> Result<Self, Self::Error> {
        s.parse()
    }
}

/// Defines a pusher
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Pusher {
    /// This is a unique identifier for this pusher. Max length, 512 bytes.
    pub pushkey: String,

    /// The kind of the pusher. If set to None in a call to set_pusher, this
    /// will delete the pusher
    pub kind: Option<PusherKind>,

    /// This is a reverse-DNS style identifier for the application. Max length, 64 chars.
    pub app_id: String,

    /// A string that will allow the user to identify what application owns this pusher.
    pub app_display_name: String,

    /// A string that will allow the user to identify what device owns this pusher.
    pub device_display_name: String,

    /// This string determines which set of device specific rules this pusher executes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub profile_tag: Option<String>,

    /// The preferred language for receiving notifications (e.g. 'en' or 'en-US')
    pub lang: String,

    /// Information for the pusher implementation itself.
    pub data: PusherData,
}

/// Which kind a pusher is
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PusherKind {
    /// A pusher that sends HTTP pokes.
    Http,

    /// A pusher that emails the user with unread notifications.
    Email,
}

/// Information for the pusher implementation itself.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PusherData {
    /// Required if the pusher's kind is http. The URL to use to send notifications to.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub url: Option<String>,

    /// The format to use when sending notifications to the Push Gateway.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub format: Option<PushFormat>,
}

/// A special format that the homeserver should use when sending notifications to a Push Gateway.
/// Currently, only "event_id_only" is supported as of [Push Gateway API r0.1.1](https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour)
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PushFormat {
    /// Require the homeserver to only send a reduced set of fields in the push.
    EventIdOnly,
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    loop
    {
        println!("Please input your guess.");

	let mut guess = String::new();

	io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

	let guess: u32 = guess.trim().parse()
            .expect("Please type a number!");

	println!("You guessed: {}", guess);

	match guess.cmp(&secret_number) {
              Ordering::Less    => println!("Too small!"),
	      Ordering::Greater => println!("Too big!"),
	      Ordering::Equal   => println!("You win!"),
        }
    }
}
<commit_msg>Break loop<commit_after>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    loop
    {
        println!("Please input your guess.");

	let mut guess = String::new();

	io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

	let guess: u32 = match guess.trim().parse() {
	    Ok(num) => num,
	    Err(_) => continue,
	};

	println!("You guessed: {}", guess);

	match guess.cmp(&secret_number) {
              Ordering::Less    => println!("Too small!"),
	      Ordering::Greater => println!("Too big!"),
	      Ordering::Equal   => {
	      			println!("You win!");
				break;
	      }
	}
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 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.

// Extracted from https://github.com/rust-num/num.

// Rust 1.5 is unhappy that this private module is undocumented.
#![allow(missing_docs)]

use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::mem::size_of;

/// Numbers which have upper and lower bounds
pub trait Bounded {
    // FIXME (#5527): These should be associated constants
    /// returns the smallest finite number this type can represent
    fn min_value() -> Self;
    /// returns the largest finite number this type can represent
    fn max_value() -> Self;
}

macro_rules! bounded_impl {
    ($t:ty, $min:expr, $max:expr) => {
        impl Bounded for $t {
            #[inline]
            fn min_value() -> $t { $min }

            #[inline]
            fn max_value() -> $t { $max }
        }
    }
}

bounded_impl!(usize, usize::MIN, usize::MAX);
bounded_impl!(u8, u8::MIN, u8::MAX);
bounded_impl!(u16, u16::MIN, u16::MAX);
bounded_impl!(u32, u32::MIN, u32::MAX);
bounded_impl!(u64, u64::MIN, u64::MAX);

bounded_impl!(isize, isize::MIN, isize::MAX);
bounded_impl!(i8, i8::MIN, i8::MAX);
bounded_impl!(i16, i16::MIN, i16::MAX);
bounded_impl!(i32, i32::MIN, i32::MAX);
bounded_impl!(i64, i64::MIN, i64::MAX);

bounded_impl!(f32, f32::MIN, f32::MAX);
bounded_impl!(f64, f64::MIN, f64::MAX);

/// A generic trait for converting a value to a number.
pub trait ToPrimitive {
    /// Converts the value of `self` to an `isize`.
    fn to_isize(&self) -> Option<isize>;

    /// Converts the value of `self` to an `i8`.
    fn to_i8(&self) -> Option<i8>;

    /// Converts the value of `self` to an `i16`.
    fn to_i16(&self) -> Option<i16>;

    /// Converts the value of `self` to an `i32`.
    fn to_i32(&self) -> Option<i32>;

    /// Converts the value of `self` to an `i64`.
    fn to_i64(&self) -> Option<i64>;

    /// Converts the value of `self` to a `usize`.
    fn to_usize(&self) -> Option<usize>;

    /// Converts the value of `self` to an `u8`.
    fn to_u8(&self) -> Option<u8>;

    /// Converts the value of `self` to an `u16`.
    fn to_u16(&self) -> Option<u16>;

    /// Converts the value of `self` to an `u32`.
    fn to_u32(&self) -> Option<u32>;

    /// Converts the value of `self` to an `u64`.
    fn to_u64(&self) -> Option<u64>;

    /// Converts the value of `self` to an `f32`.
    fn to_f32(&self) -> Option<f32>;

    /// Converts the value of `self` to an `f64`.
    fn to_f64(&self) -> Option<f64>;
}

macro_rules! impl_to_primitive_int_to_int {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            if size_of::<$SrcT>() <= size_of::<$DstT>() {
                Some($slf as $DstT)
            } else {
                let n = $slf as i64;
                let min_value: $DstT = Bounded::min_value();
                let max_value: $DstT = Bounded::max_value();
                if min_value as i64 <= n && n <= max_value as i64 {
                    Some($slf as $DstT)
                } else {
                    None
                }
            }
        }
    )
}

macro_rules! impl_to_primitive_int_to_uint {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            let zero: $SrcT = 0;
            let max_value: $DstT = Bounded::max_value();
            if zero <= $slf && $slf as u64 <= max_value as u64 {
                Some($slf as $DstT)
            } else {
                None
            }
        }
    )
}

macro_rules! impl_to_primitive_int {
    ($T:ty) => (
        impl ToPrimitive for $T {
            #[inline]
            fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) }
            #[inline]
            fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) }
            #[inline]
            fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) }
            #[inline]
            fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) }
            #[inline]
            fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) }

            #[inline]
            fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) }
            #[inline]
            fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) }
            #[inline]
            fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) }
            #[inline]
            fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) }
            #[inline]
            fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) }

            #[inline]
            fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
            #[inline]
            fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
        }
    )
}

impl_to_primitive_int! { isize }
impl_to_primitive_int! { i8 }
impl_to_primitive_int! { i16 }
impl_to_primitive_int! { i32 }
impl_to_primitive_int! { i64 }

macro_rules! impl_to_primitive_uint_to_int {
    ($DstT:ty, $slf:expr) => (
        {
            let max_value: $DstT = Bounded::max_value();
            if $slf as u64 <= max_value as u64 {
                Some($slf as $DstT)
            } else {
                None
            }
        }
    )
}

macro_rules! impl_to_primitive_uint_to_uint {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            if size_of::<$SrcT>() <= size_of::<$DstT>() {
                Some($slf as $DstT)
            } else {
                let zero: $SrcT = 0;
                let max_value: $DstT = Bounded::max_value();
                if zero <= $slf && $slf as u64 <= max_value as u64 {
                    Some($slf as $DstT)
                } else {
                    None
                }
            }
        }
    )
}

macro_rules! impl_to_primitive_uint {
    ($T:ty) => (
        impl ToPrimitive for $T {
            #[inline]
            fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) }
            #[inline]
            fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) }
            #[inline]
            fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) }
            #[inline]
            fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) }
            #[inline]
            fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) }

            #[inline]
            fn to_usize(&self) -> Option<usize> {
                impl_to_primitive_uint_to_uint!($T, usize, *self)
            }
            #[inline]
            fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) }
            #[inline]
            fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) }
            #[inline]
            fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) }
            #[inline]
            fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) }

            #[inline]
            fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
            #[inline]
            fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
        }
    )
}

impl_to_primitive_uint! { usize }
impl_to_primitive_uint! { u8 }
impl_to_primitive_uint! { u16 }
impl_to_primitive_uint! { u32 }
impl_to_primitive_uint! { u64 }

pub trait FromPrimitive: Sized {
    fn from_isize(n: isize) -> Option<Self>;
    fn from_i8(n: i8) -> Option<Self>;
    fn from_i16(n: i16) -> Option<Self>;
    fn from_i32(n: i32) -> Option<Self>;
    fn from_i64(n: i64) -> Option<Self>;
    fn from_usize(n: usize) -> Option<Self>;
    fn from_u8(n: u8) -> Option<Self>;
    fn from_u16(n: u16) -> Option<Self>;
    fn from_u32(n: u32) -> Option<Self>;
    fn from_u64(n: u64) -> Option<Self>;
}

macro_rules! impl_from_primitive {
    ($T:ty, $to_ty:ident) => (
        impl FromPrimitive for $T {
            #[inline] fn from_isize(n: isize) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_usize(n: usize) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
            #[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
        }
    )
}

impl_from_primitive! { isize, to_isize }
impl_from_primitive! { i8, to_i8 }
impl_from_primitive! { i16, to_i16 }
impl_from_primitive! { i32, to_i32 }
impl_from_primitive! { i64, to_i64 }
impl_from_primitive! { usize, to_usize }
impl_from_primitive! { u8, to_u8 }
impl_from_primitive! { u16, to_u16 }
impl_from_primitive! { u32, to_u32 }
impl_from_primitive! { u64, to_u64 }
impl_from_primitive! { f32, to_f32 }
impl_from_primitive! { f64, to_f64 }
<commit_msg>Remove unused ToPrimitive trait<commit_after>// Copyright 2013-2014 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.

// Extracted from https://github.com/rust-num/num.

// Rust 1.5 is unhappy that this private module is undocumented.
#![allow(missing_docs)]

use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::mem::size_of;

/// Numbers which have upper and lower bounds
pub trait Bounded {
    // FIXME (#5527): These should be associated constants
    /// returns the smallest finite number this type can represent
    fn min_value() -> Self;
    /// returns the largest finite number this type can represent
    fn max_value() -> Self;
}

macro_rules! bounded_impl {
    ($t:ty, $min:expr, $max:expr) => {
        impl Bounded for $t {
            #[inline]
            fn min_value() -> $t { $min }

            #[inline]
            fn max_value() -> $t { $max }
        }
    }
}

bounded_impl!(usize, usize::MIN, usize::MAX);
bounded_impl!(u8, u8::MIN, u8::MAX);
bounded_impl!(u16, u16::MIN, u16::MAX);
bounded_impl!(u32, u32::MIN, u32::MAX);
bounded_impl!(u64, u64::MIN, u64::MAX);

bounded_impl!(isize, isize::MIN, isize::MAX);
bounded_impl!(i8, i8::MIN, i8::MAX);
bounded_impl!(i16, i16::MIN, i16::MAX);
bounded_impl!(i32, i32::MIN, i32::MAX);
bounded_impl!(i64, i64::MIN, i64::MAX);

macro_rules! int_to_int {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            if size_of::<$SrcT>() <= size_of::<$DstT>() {
                Some($slf as $DstT)
            } else {
                let n = $slf as i64;
                let min_value: $DstT = Bounded::min_value();
                let max_value: $DstT = Bounded::max_value();
                if min_value as i64 <= n && n <= max_value as i64 {
                    Some($slf as $DstT)
                } else {
                    None
                }
            }
        }
    )
}

macro_rules! int_to_uint {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            let zero: $SrcT = 0;
            let max_value: $DstT = Bounded::max_value();
            if zero <= $slf && $slf as u64 <= max_value as u64 {
                Some($slf as $DstT)
            } else {
                None
            }
        }
    )
}

macro_rules! uint_to_int {
    ($DstT:ty, $slf:expr) => (
        {
            let max_value: $DstT = Bounded::max_value();
            if $slf as u64 <= max_value as u64 {
                Some($slf as $DstT)
            } else {
                None
            }
        }
    )
}

macro_rules! uint_to_uint {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            if size_of::<$SrcT>() <= size_of::<$DstT>() {
                Some($slf as $DstT)
            } else {
                let zero: $SrcT = 0;
                let max_value: $DstT = Bounded::max_value();
                if zero <= $slf && $slf as u64 <= max_value as u64 {
                    Some($slf as $DstT)
                } else {
                    None
                }
            }
        }
    )
}

pub trait FromPrimitive: Sized {
    fn from_isize(n: isize) -> Option<Self>;
    fn from_i8(n: i8) -> Option<Self>;
    fn from_i16(n: i16) -> Option<Self>;
    fn from_i32(n: i32) -> Option<Self>;
    fn from_i64(n: i64) -> Option<Self>;
    fn from_usize(n: usize) -> Option<Self>;
    fn from_u8(n: u8) -> Option<Self>;
    fn from_u16(n: u16) -> Option<Self>;
    fn from_u32(n: u32) -> Option<Self>;
    fn from_u64(n: u64) -> Option<Self>;
}

macro_rules! impl_from_primitive_for_int {
    ($T:ty) => (
        impl FromPrimitive for $T {
            #[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!(isize, $T, n) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!(i8, $T, n) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!(i16, $T, n) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!(i32, $T, n) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!(i64, $T, n) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { uint_to_int!($T, n) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { uint_to_int!($T, n) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { uint_to_int!($T, n) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { uint_to_int!($T, n) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { uint_to_int!($T, n) }
        }
    )
}

macro_rules! impl_from_primitive_for_uint {
    ($T:ty) => (
        impl FromPrimitive for $T {
            #[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!(isize, $T, n) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!(i8, $T, n) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!(i16, $T, n) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!(i32, $T, n) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!(i64, $T, n) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { uint_to_uint!(usize, $T, n) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { uint_to_uint!(u8, $T, n) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { uint_to_uint!(u16, $T, n) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { uint_to_uint!(u32, $T, n) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { uint_to_uint!(u64, $T, n) }
        }
    )
}

macro_rules! impl_from_primitive_for_float {
    ($T:ty) => (
        impl FromPrimitive for $T {
            #[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
        }
    )
}

impl_from_primitive_for_int!(isize);
impl_from_primitive_for_int!(i8);
impl_from_primitive_for_int!(i16);
impl_from_primitive_for_int!(i32);
impl_from_primitive_for_int!(i64);
impl_from_primitive_for_uint!(usize);
impl_from_primitive_for_uint!(u8);
impl_from_primitive_for_uint!(u16);
impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64);
<|endoftext|>


<commit_before>mod linkedlist_test;
mod linkedlist{

    pub enum List{
        Cons(int, Box<List>),
        Nil
    }

    pub fn visual_compare(l1: &List, l2: &List) -> String{
        let equality = match equal(l1, l2){
            true  => "",
            false => "not ",
        };
        format!("{} and {} are {}equal", repr(l1), repr(l2), equality)
    }

    pub fn repr(list: &List) -> String{
        match list{
            &Nil => String::from_str("<[]>"),
            &Cons(_, _) => String::from_str("<[").append(_repr_inner(list).as_slice())
        }
    }

    fn _repr_inner(list: &List) -> String{
        match list{
            &Nil => String::from_str("]>"),
            &Cons(number, box ref tail) if match tail{
                &Nil => true,
                _ => false,
            }=> number.to_str().append("]>"),
            &Cons(number, box ref tail) => number.to_str().append(", ").append(_repr_inner(tail).as_slice())
        }
    }

    pub fn equal(l1: &List, l2: &List) -> bool{
        match (l1, l2){
            (&Nil, &Nil) => true,
            (&Cons(n1, box ref tail1), &Cons(n2, box ref tail2)) if n1 == n2 => {
                equal(tail1, tail2)
            },
            _ => false,
        }
    }
}
<commit_msg>fix for rustc 0.12.0-pre-nightly<commit_after>mod linkedlist_test;
mod linkedlist{

    pub enum List{
        Cons(int, Box<List>),
        Nil
    }

    pub fn visual_compare(l1: &List, l2: &List) -> String{
        let equality = match equal(l1, l2){
            true  => "",
            false => "not ",
        };
        format!("{} and {} are {}equal", repr(l1), repr(l2), equality)
    }

    pub fn repr(list: &List) -> String{
        match list{
            &Nil => String::from_str("<[]>"),
            &Cons(_, _) => String::from_str("<[").append(_repr_inner(list).as_slice())
        }
    }

    fn _repr_inner(list: &List) -> String{
        match list{
            &Nil => String::from_str("]>"),
            &Cons(number, box ref tail) if match tail{
                &Nil => true,
                _ => false,
            }=> number.to_string().append("]>"),
            &Cons(number, box ref tail) => number.to_string().append(", ").append(_repr_inner(tail).as_slice())
        }
    }

    pub fn equal(l1: &List, l2: &List) -> bool{
        match (l1, l2){
            (&Nil, &Nil) => true,
            (&Cons(n1, box ref tail1), &Cons(n2, box ref tail2)) if n1 == n2 => {
                equal(tail1, tail2)
            },
            _ => false,
        }
    }
}
<|endoftext|>


<commit_before>use std::intrinsics::TypeId;
use std::cell::RefCell;
use std::rc::{Rc, Weak};
use std::fmt::{Formatter, Show, Result};
use std::collections::hashmap::HashMap;
use std::any::{Any, AnyRefExt, AnyMutRefExt};
use std::mem;
use uuid::Uuid;

/// Toplevel container of the entity component system.
pub struct World<T> {
    data: Rc<RefCell<WorldData<T>>>,
}

impl<T> Clone for World<T> {
    fn clone(&self) -> World<T> {
        World { data: self.data.clone() }
    }
}

impl<T: System> World<T> {
    /// Create a world coupled with an application specific system object.
    pub fn new(master_system: T) -> World<T> {
        let ret = World {
            data: Rc::new(RefCell::new(WorldData::new(master_system))),
        };
        ret.data.borrow_mut().master_system.register(&ret);
        ret
    }

    /// Wrap an EntityId struct into an entity handle that has a backreference
    /// to the world object.
    fn wrap(&self, id: EntityId) -> Entity<T> {
        Entity {
            world: self.data.downgrade(),
            id: id
        }
    }

    /// Create a new entity bound to this world.
    pub fn new_entity(&mut self) -> Entity<T> {
        let id = EntityId {
            idx: self.data.borrow_mut().get_idx(),
            uuid: Uuid::new_v4(),
        };
        self.data.borrow_mut().register_new_entity(id);
        let ret = self.wrap(id);
        self.data.borrow_mut().master_system.added(&ret);
        ret
    }

    pub fn system<'a>(&'a self) -> &'a T {
        unsafe { mem::transmute(&self.data.borrow().master_system) }
    }

    pub fn system_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { mem::transmute(&self.data.borrow_mut().master_system) }
    }

    pub fn find_entity(&self, uuid: &Uuid) -> Option<Entity<T>> {
        match self.data.borrow().uuids.find(uuid) {
            Some(idx) => Some(self.wrap(EntityId { uuid: *uuid, idx: *idx })),
            None => None
        }
    }

    pub fn entities(&self) -> Vec<Entity<T>> {
        // XXX: Inefficient
        self.data.borrow().uuids.iter()
            .map(|(&uuid, &idx)| self.wrap(EntityId { uuid: uuid, idx: idx }))
            .collect()
    }
}

/// Callback interface for application data connected to the component system
/// world.
pub trait System {
    /// Callback for initially attaching the system to a world.
    fn register(&mut self, world: &World<Self>);
    /// Callback for adding a new entity to world.
    fn added(&mut self, e: &Entity<Self>);
    /// Callback for a component being added or removed in an entity. Note that
    /// this is not called when the data of an existing component is written
    /// to, only if the component is replaced or removed.
    fn changed<C>(&mut self, e: &Entity<Self>, component: Option<&C>);
    /// Callback for an entity being deleted.
    fn deleted(&mut self, e: &Entity<Self>);
}

pub struct Entity<T> {
    world: Weak<RefCell<WorldData<T>>>,
    id: EntityId,
}

impl<T> Clone for Entity<T> {
    fn clone(&self) -> Entity<T> {
        Entity { world: self.world.clone(), id: self.id }
    }
}

impl<T> Show for Entity<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.id)
    }
}

impl<T: System> Entity<T> {
    /// Add or reset a component in the entity. Causes a "changed" call to the
    /// world system.
    pub fn set_component<C: 'static+Clone>(&mut self, comp: C) {
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .set_component(self, Some(comp));
    }

    /// Remove a component from the entity. Causes a "changed" call to the
    /// world system.
    pub fn remove_component<C: 'static+Clone>(&mut self) {
        let comp : Option<C> = None;
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .set_component(self, comp);
    }

    /// Delete the entity from the world. Causes a "deleted" call to the world
    /// system.
    pub fn delete(&mut self) {
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .delete_entity(self);
    }

    /// Query whether the entity has a type of component.
    pub fn has<'a, C: 'static>(&self) -> bool {
        self.world.upgrade().unwrap().borrow()
            .comp_ref::<'a, C>(self.id).is_some()
    }

    /// Get an access proxy to the entity's component if the entity has that
    /// component.
    pub fn into<C: 'static>(&self) -> Option<CompProxyMut<T, C>> {
        if self.has::<C>() {
            Some(CompProxyMut {
                world: self.world.clone(),
                id: self.id
            })
        } else {
            None
        }
    }

    /// Return unique identifier for this entity.
    pub fn uuid(&self) -> Uuid {
        self.id.uuid
    }

    /// Return a handle to the world.
    pub fn world(&self) -> World<T> {
        World { data: self.world.upgrade().unwrap() }
    }
}

/// Access proxy to entity components. The implementation RefCell (mutable)
/// borrow internally, so using this carelessly may lead to runtime borrow
/// errors. You should generally keep access to the concrete entity data short
/// in scope and low in the call stack to prevent unexpected borrow failures.
pub struct CompProxyMut<T, C> {
    world: Weak<RefCell<WorldData<T>>>,
    id: EntityId,
}

impl<T: System, C: 'static> Deref<C> for CompProxyMut<T, C> {
    fn deref<'a>(&'a self) -> &'a C {
        self.world.upgrade().unwrap().borrow()
            .comp_ref::<'a, C>(self.id).unwrap()
    }
}

/*
impl<T: System, C: 'static> DerefMut<C> for CompProxyMut<T, C> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut C {
        self.world.upgrade().unwrap().borrow_mut()
            .comp_ref_mut::<'a, C>(self.id).unwrap()
    }
}
*/

#[deriving(PartialEq, Clone, Show)]
struct EntityId {
    uuid: Uuid,
    idx: uint,
}

struct WorldData<T> {
    // XXX: This is much less efficient than it could be. A serious
    // implementation would use unboxed vecs for the components and would
    // provide lookup methods faster than a HashMap find to access the
    // components
    components: HashMap<TypeId, Vec<Option<Box<Any>>>>,

    next_idx: uint,
    reusable_idxs: Vec<uint>,
    uuids: HashMap<Uuid, uint>,

    master_system: T,
}

impl<T: System> WorldData<T> {
    fn new(master_system: T) -> WorldData<T> {
        WorldData {
            components: HashMap::new(),
            next_idx: 0,
            reusable_idxs: vec!(),
            uuids: HashMap::new(),
            master_system: master_system,
        }
    }

    fn register_new_entity(&mut self, id: EntityId) {
        assert!(!self.uuids.contains_key(&id.uuid),
            "New entity clobbering existing one");
        self.uuids.insert(id.uuid, id.idx);
    }

    fn delete_entity(&mut self, e: &Entity<T>) {
        self.uuids.remove(&e.id.uuid);

        for (_, c) in self.components.mut_iter() {
            if c.len() > e.id.idx {
                c.as_mut_slice()[e.id.idx] = None;
            }
        }

        self.reusable_idxs.push(e.id.idx);

        self.master_system.deleted(e);
    }

    /// Return the next unused reusable entity id.
    fn get_idx(&mut self) -> uint {
        match self.reusable_idxs.pop() {
            None => {
                let ret = self.next_idx;
                self.next_idx += 1;
                ret
            }
            Some(idx) => idx
        }
    }

    fn set_component<C: 'static+Clone>(&mut self, e: &Entity<T>, comp: Option<C>) {
        let type_id = TypeId::of::<C>();
        // We haven't seen this kind of component yet.
        if !self.components.contains_key(&type_id) {
            self.components.insert(type_id, vec!());
        }

        let bin = self.components.find_mut(&type_id).unwrap();

        // XXX: grow_set didn't work.
        while bin.len() <= e.id.idx { bin.push(None); }
        bin.as_mut_slice()[e.id.idx] = match comp {
            None => None,
            Some(c) => Some(box c as Box<Any>),
        };

        match bin.as_mut_slice()[e.id.idx] {
            None => self.master_system.changed::<C>(e, None),
            Some(ref c) => self.master_system.changed(e, Some(&c)),
        };
    }

    fn comp_ref<'a, C: 'static>(
        &self, id: EntityId) -> Option<&'a C> {
        let type_id = TypeId::of::<C>();
        match self.components.find(&type_id) {
            None => { None }
            Some(bin) => {
                if id.idx < bin.len() {
                    match bin.get(id.idx) {
                        &Some(ref c) => { unsafe { Some(mem::transmute(c.as_ref::<C>().unwrap())) } }
                        &None => None
                    }
                } else {
                    None
                }
            }
        }
    }

    /*
    fn comp_ref_mut<'a, C: 'static>(
        &mut self, id: EntityId) -> Option<&'a mut C> {
        let type_id = TypeId::of::<C>();
        match self.components.find_mut(&type_id) {
            None => { None }
            Some(bin) => {
                if id.idx < bin.len() {
                    match bin.get_mut(id.idx) {
                        &Some(ref mut c) => {
                            unsafe { Some(mem::transmute(c.as_mut::<C>().unwrap())) }
                        }
                        &None => None
                    }
                } else {
                    None
                }
            }
        }
    }
    */
}

<commit_msg>Hash and Eq for entities<commit_after>use std::intrinsics::TypeId;
use std::cell::RefCell;
use std::rc::{Rc, Weak};
use std::fmt::{Formatter, Show, Result};
use std::collections::hashmap::HashMap;
use std::any::{Any, AnyRefExt, AnyMutRefExt};
use std::hash::Hash;
use std::hash::sip::SipState;
use std::mem;
use uuid::Uuid;

/// Toplevel container of the entity component system.
pub struct World<T> {
    data: Rc<RefCell<WorldData<T>>>,
}

impl<T> Clone for World<T> {
    fn clone(&self) -> World<T> {
        World { data: self.data.clone() }
    }
}

impl<T: System> World<T> {
    /// Create a world coupled with an application specific system object.
    pub fn new(master_system: T) -> World<T> {
        let ret = World {
            data: Rc::new(RefCell::new(WorldData::new(master_system))),
        };
        ret.data.borrow_mut().master_system.register(&ret);
        ret
    }

    /// Wrap an EntityId struct into an entity handle that has a backreference
    /// to the world object.
    fn wrap(&self, id: EntityId) -> Entity<T> {
        Entity {
            world: self.data.downgrade(),
            id: id
        }
    }

    /// Create a new entity bound to this world.
    pub fn new_entity(&mut self) -> Entity<T> {
        let id = EntityId {
            idx: self.data.borrow_mut().get_idx(),
            uuid: Uuid::new_v4(),
        };
        self.data.borrow_mut().register_new_entity(id);
        let ret = self.wrap(id);
        self.data.borrow_mut().master_system.added(&ret);
        ret
    }

    pub fn system<'a>(&'a self) -> &'a T {
        unsafe { mem::transmute(&self.data.borrow().master_system) }
    }

    pub fn system_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { mem::transmute(&self.data.borrow_mut().master_system) }
    }

    pub fn find_entity(&self, uuid: &Uuid) -> Option<Entity<T>> {
        match self.data.borrow().uuids.find(uuid) {
            Some(idx) => Some(self.wrap(EntityId { uuid: *uuid, idx: *idx })),
            None => None
        }
    }

    pub fn entities(&self) -> Vec<Entity<T>> {
        // XXX: Inefficient
        self.data.borrow().uuids.iter()
            .map(|(&uuid, &idx)| self.wrap(EntityId { uuid: uuid, idx: idx }))
            .collect()
    }
}

/// Callback interface for application data connected to the component system
/// world.
pub trait System {
    /// Callback for initially attaching the system to a world.
    fn register(&mut self, world: &World<Self>);
    /// Callback for adding a new entity to world.
    fn added(&mut self, e: &Entity<Self>);
    /// Callback for a component being added or removed in an entity. Note that
    /// this is not called when the data of an existing component is written
    /// to, only if the component is replaced or removed.
    fn changed<C>(&mut self, e: &Entity<Self>, component: Option<&C>);
    /// Callback for an entity being deleted.
    fn deleted(&mut self, e: &Entity<Self>);
}

pub struct Entity<T> {
    world: Weak<RefCell<WorldData<T>>>,
    id: EntityId,
}

impl <T> Hash for Entity<T> {
    fn hash(&self, state: &mut SipState) {
        self.id.hash(state);
    }
}

impl <T> PartialEq for Entity<T> {
    fn eq(&self, other: &Entity<T>) -> bool {
        self.id.eq(&other.id)
    }
}

impl <T> Eq for Entity<T> {}

impl<T> Clone for Entity<T> {
    fn clone(&self) -> Entity<T> {
        Entity { world: self.world.clone(), id: self.id }
    }
}

impl<T> Show for Entity<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.id)
    }
}

impl<T: System> Entity<T> {
    /// Add or reset a component in the entity. Causes a "changed" call to the
    /// world system.
    pub fn set_component<C: 'static+Clone>(&mut self, comp: C) {
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .set_component(self, Some(comp));
    }

    /// Remove a component from the entity. Causes a "changed" call to the
    /// world system.
    pub fn remove_component<C: 'static+Clone>(&mut self) {
        let comp : Option<C> = None;
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .set_component(self, comp);
    }

    /// Delete the entity from the world. Causes a "deleted" call to the world
    /// system.
    pub fn delete(&mut self) {
        self.world.upgrade().unwrap().borrow_mut().deref_mut()
            .delete_entity(self);
    }

    /// Query whether the entity has a type of component.
    pub fn has<'a, C: 'static>(&self) -> bool {
        self.world.upgrade().unwrap().borrow()
            .comp_ref::<'a, C>(self.id).is_some()
    }

    /// Get an access proxy to the entity's component if the entity has that
    /// component.
    pub fn into<C: 'static>(&self) -> Option<CompProxyMut<T, C>> {
        if self.has::<C>() {
            Some(CompProxyMut {
                world: self.world.clone(),
                id: self.id
            })
        } else {
            None
        }
    }

    /// Return unique identifier for this entity.
    pub fn uuid(&self) -> Uuid {
        self.id.uuid
    }

    /// Return a handle to the world.
    pub fn world(&self) -> World<T> {
        World { data: self.world.upgrade().unwrap() }
    }
}

/// Access proxy to entity components. The implementation RefCell (mutable)
/// borrow internally, so using this carelessly may lead to runtime borrow
/// errors. You should generally keep access to the concrete entity data short
/// in scope and low in the call stack to prevent unexpected borrow failures.
pub struct CompProxyMut<T, C> {
    world: Weak<RefCell<WorldData<T>>>,
    id: EntityId,
}

impl<T: System, C: 'static> Deref<C> for CompProxyMut<T, C> {
    fn deref<'a>(&'a self) -> &'a C {
        self.world.upgrade().unwrap().borrow()
            .comp_ref::<'a, C>(self.id).unwrap()
    }
}

/*
impl<T: System, C: 'static> DerefMut<C> for CompProxyMut<T, C> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut C {
        self.world.upgrade().unwrap().borrow_mut()
            .comp_ref_mut::<'a, C>(self.id).unwrap()
    }
}
*/

#[deriving(PartialEq, Clone, Hash, Show)]
struct EntityId {
    uuid: Uuid,
    idx: uint,
}

struct WorldData<T> {
    // XXX: This is much less efficient than it could be. A serious
    // implementation would use unboxed vecs for the components and would
    // provide lookup methods faster than a HashMap find to access the
    // components
    components: HashMap<TypeId, Vec<Option<Box<Any>>>>,

    next_idx: uint,
    reusable_idxs: Vec<uint>,
    uuids: HashMap<Uuid, uint>,

    master_system: T,
}

impl<T: System> WorldData<T> {
    fn new(master_system: T) -> WorldData<T> {
        WorldData {
            components: HashMap::new(),
            next_idx: 0,
            reusable_idxs: vec!(),
            uuids: HashMap::new(),
            master_system: master_system,
        }
    }

    fn register_new_entity(&mut self, id: EntityId) {
        assert!(!self.uuids.contains_key(&id.uuid),
            "New entity clobbering existing one");
        self.uuids.insert(id.uuid, id.idx);
    }

    fn delete_entity(&mut self, e: &Entity<T>) {
        self.uuids.remove(&e.id.uuid);

        for (_, c) in self.components.mut_iter() {
            if c.len() > e.id.idx {
                c.as_mut_slice()[e.id.idx] = None;
            }
        }

        self.reusable_idxs.push(e.id.idx);

        self.master_system.deleted(e);
    }

    /// Return the next unused reusable entity id.
    fn get_idx(&mut self) -> uint {
        match self.reusable_idxs.pop() {
            None => {
                let ret = self.next_idx;
                self.next_idx += 1;
                ret
            }
            Some(idx) => idx
        }
    }

    fn set_component<C: 'static+Clone>(&mut self, e: &Entity<T>, comp: Option<C>) {
        let type_id = TypeId::of::<C>();
        // We haven't seen this kind of component yet.
        if !self.components.contains_key(&type_id) {
            self.components.insert(type_id, vec!());
        }

        let bin = self.components.find_mut(&type_id).unwrap();

        // XXX: grow_set didn't work.
        while bin.len() <= e.id.idx { bin.push(None); }
        bin.as_mut_slice()[e.id.idx] = match comp {
            None => None,
            Some(c) => Some(box c as Box<Any>),
        };

        match bin.as_mut_slice()[e.id.idx] {
            None => self.master_system.changed::<C>(e, None),
            Some(ref c) => self.master_system.changed(e, Some(&c)),
        };
    }

    fn comp_ref<'a, C: 'static>(
        &self, id: EntityId) -> Option<&'a C> {
        let type_id = TypeId::of::<C>();
        match self.components.find(&type_id) {
            None => { None }
            Some(bin) => {
                if id.idx < bin.len() {
                    match bin.get(id.idx) {
                        &Some(ref c) => { unsafe { Some(mem::transmute(c.as_ref::<C>().unwrap())) } }
                        &None => None
                    }
                } else {
                    None
                }
            }
        }
    }

    /*
    fn comp_ref_mut<'a, C: 'static>(
        &mut self, id: EntityId) -> Option<&'a mut C> {
        let type_id = TypeId::of::<C>();
        match self.components.find_mut(&type_id) {
            None => { None }
            Some(bin) => {
                if id.idx < bin.len() {
                    match bin.get_mut(id.idx) {
                        &Some(ref mut c) => {
                            unsafe { Some(mem::transmute(c.as_mut::<C>().unwrap())) }
                        }
                        &None => None
                    }
                } else {
                    None
                }
            }
        }
    }
    */
}

<|endoftext|>