<commit_before>extern crate unidecode;
use unidecode::unidecode;

// Tests that every character outputted by the unidecode() function is valid
// ASCII.
#[test]
fn test_all_ascii() {
    use std::char;

    let valid_unicode = (0x0..0xD7FF + 1).chain(0x0E000..0x10FFFF + 1);
    for i in valid_unicode {
        match char::from_u32(i) {
            Some(ch) => {
                for ascii_ch in unidecode(&ch.to_string()).chars() {
                    let x = ascii_ch as u32;
                    if x > 127 {
                        panic!(
                            "Data contains non-ASCII character (Dec: {})",
                            x
                        );
                    }
                }
            },
            None => panic!("Test written incorrectly; invalid Unicode")
        }
    }
}

// These tests were ported directly from the original `Text::Unidecode` Perl
// module.
#[test]
fn test_conversion() {
    assert_eq!(unidecode("Æneid"), "AEneid");
    assert_eq!(unidecode("étude"), "etude");
    assert_eq!(unidecode("北亰"), "Bei Jing ");
    assert_eq!(unidecode("ᔕᓇᓇ"), "shanana");
    assert_eq!(unidecode("ᏔᎵᏆ"), "taliqua");
    assert_eq!(unidecode("ܦܛܽܐܺ"), "ptu'i");
    assert_eq!(unidecode("अभिजीत"), "abhijiit");
    assert_eq!(unidecode("অভিজীত"), "abhijiit");
    assert_eq!(unidecode("അഭിജീത"), "abhijiit");
    assert_eq!(unidecode("മലയാലമ്"), "mlyaalm");
    assert_eq!(unidecode("げんまい茶"), "genmaiCha ");
}
<commit_msg>added test<commit_after>extern crate unidecode;
use unidecode::{unidecode, unidecode_char};

// Tests that every character outputted by the unidecode() function is valid
// ASCII.
#[test]
fn test_all_ascii() {
    use std::char;

    let valid_unicode = (0x0..0xD7FF + 1).chain(0x0E000..0x10FFFF + 1);
    for i in valid_unicode {
        match char::from_u32(i) {
            Some(ch) => {
                for ascii_ch in unidecode(&ch.to_string()).chars() {
                    let x = ascii_ch as u32;
                    if x > 127 {
                        panic!(
                            "Data contains non-ASCII character (Dec: {})",
                            x
                        );
                    }
                }
            },
            None => panic!("Test written incorrectly; invalid Unicode")
        }
    }
}

// These tests were ported directly from the original `Text::Unidecode` Perl
// module.
#[test]
fn test_conversion() {
    assert_eq!(unidecode("Æneid"), "AEneid");
    assert_eq!(unidecode("étude"), "etude");
    assert_eq!(unidecode("北亰"), "Bei Jing ");
    assert_eq!(unidecode("ᔕᓇᓇ"), "shanana");
    assert_eq!(unidecode("ᏔᎵᏆ"), "taliqua");
    assert_eq!(unidecode("ܦܛܽܐܺ"), "ptu'i");
    assert_eq!(unidecode("अभिजीत"), "abhijiit");
    assert_eq!(unidecode("অভিজীত"), "abhijiit");
    assert_eq!(unidecode("അഭിജീത"), "abhijiit");
    assert_eq!(unidecode("മലയാലമ്"), "mlyaalm");
    assert_eq!(unidecode("げんまい茶"), "genmaiCha ");
}

#[test]
fn test_unidecode_char() {
    assert_eq!(unidecode_char('Æ'), "AE");
    assert_eq!(unidecode_char('北'), "Bei ");
    assert_eq!(unidecode_char('亰'), "Jing ");
    assert_eq!(unidecode_char('ᔕ'), "sha");
}
<|endoftext|>


<commit_before>extern crate mio;

use client::GameClient;

//use mio::{TryRead, TryWrite};
use mio::tcp::*;
use mio::util::Slab;
use mio::Token;
use mio::{EventLoop, EventSet, PollOpt, Handler};
//use bytes::{Buf, Take};
//use std::mem;
use std::net::SocketAddr;
//use std::io::Cursor;
//use std::thread;
//use std::sync::mpsc;
use std::sync::{Arc, RwLock};
//use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::atomic::AtomicUsize;
//use std::collections::HashMap;

const SERVER_TOKEN: mio::Token = mio::Token(1);

#[derive(Clone)]
pub struct AuthoritativeServerState{
    clients: Arc<RwLock<Slab<GameClient>>>,
    token_counter: Arc<AtomicUsize>
}

impl AuthoritativeServerState{
    pub fn new() -> AuthoritativeServerState{
        AuthoritativeServerState{
            token_counter: Arc::new(AtomicUsize::new(1)),
            // Max 128 connections
            clients: Arc::new(RwLock::new(Slab::new_starting_at(Token(2), 128)))
        }
    }
}

pub struct AuthoritativeServer{
    // The socket on which this server is listening
    socket: TcpListener,

    // The token assigned to this server's own connection
    token: Token,

    // Current state for the server
    state: AuthoritativeServerState
}

impl AuthoritativeServer{
    pub fn new(address: SocketAddr) -> AuthoritativeServer{
        let server_state = AuthoritativeServerState::new();
        let server_state_clone = server_state.clone();

        println!("Starting authoritative server");
        let server_socket = TcpListener::bind(&address).expect("Failed to start socket listener!");

        let mut server = AuthoritativeServer{
            socket: server_socket,
            token: SERVER_TOKEN,
            state: server_state_clone
        };

        let mut event_loop = EventLoop::new().expect("Failed to create server event loop!");

        event_loop.register(&server.socket,
                            SERVER_TOKEN,
                            EventSet::readable(),
                            PollOpt::edge()).expect("Failed to register server with event loop!");

        println!("Running event loop...");
        event_loop.run(&mut server).expect("Failed to run event loop!");

        return server;
    }

    fn start_accept_loop(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>){
        println!("Beginning server accept loop");

        loop{
            let socket = match self.socket.accept(){
                Ok(s) => {
                    match s{
                        Some((socket,_)) => socket,
                        None => {
                            println!("Accept loop encountered WouldBlock");
                            return;
                        }
                    }
                },
                Err(e) => {
                    println!("Failed to accept new socket. Error: {:?}", e);
                    return;
                }
            };

            if let Ok(ref mut clients) = self.state.clients.write(){
                match &clients.insert_with(|token| {
                    println!("Inserting new connection from {:?}", token);
                    GameClient::new(socket, token)
                }) {
                    &Some(token) => {
                        println!("Insertion successful!");
                        let ref mut client: GameClient = clients[token];
                        match client.register(event_loop){
                            Ok(_) => { println!("Registration successful!"); },
                            Err(e) => {
                                println!("Failed to register connection {:?} with event loop, error: {:?}", token, e);
                                //clients.remove(token);
                            }
                        }
                    },
                    &None => {
                        println!("Failed to insert!");
                    }
                }
            };
        }
    }

    fn get_client_mut<'a, F>(&'a mut self, token: Token, mut action: F) -> Result<(), String>
        where F: FnMut(&mut GameClient) {
        if let Ok(mut clients) = self.state.clients.write(){
            if clients.contains(token){
                let ref mut client = clients.get_mut(token).unwrap();

                action(client);

                return Ok(());
            }
        }
        Err(String::from(format!("No client exists with token {:?}", token)))
    }

    fn get_client<'a, F>(&'a mut self, token: Token, action: F) -> Result<(), String>
        where F: Fn(&GameClient) {
        if let Ok(mut clients) = self.state.clients.read(){
            if clients.contains(token){
                let ref mut client = clients.get(token).expect("Clients contains token, but was unable to access client!");

                action(client);

                return Ok(());
            }
        }
        Err(String::from(format!("No client exists with token {:?}", token)))
    }
}

impl Handler for AuthoritativeServer{
    type Timeout = ();
    type Message = ();

    fn tick(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>) {
        println!("Begin server tick!");

        if let Ok(mut clients) = self.state.clients.write(){
            for client in clients.iter_mut(){
                client.reregister(event_loop).ok();
            }
        }

        println!("End server tick!");
    }

    fn ready(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>, token: Token, events: EventSet) {
        assert!(token != Token(0), "We're not supposed to get a Token(0)!");

        if events.is_error(){
            println!("Error event for token {:?}", token);
            //Reset token?
            return;
        }

        if events.is_hup(){
            println!("OH FUCK NO, {:?} DID NOT JUST FUCKING HANG UP ON ME!", token);
            println!("I'M GOING TO FUCKING MURDER YOU FUCKER");
            //Reset?
            return;
        }

        if events.is_writable(){
            println!("Oh shit, motherfucking {:?} is writable! Look at this guy!", token);

            //fucking write some shit
        }
        else{
            println!("[{:?} silence intensifies]", token);
        }

        if events.is_readable(){
            println!("GOT SHIT TO READ FROM MY BRAH {:?} HELLLL YEAH", token);

            if self.token == token{
                self.start_accept_loop(event_loop);
            }
            else{
                self.get_client_mut(token, |client|{
                    if client.read().is_ok(){
                        client.reregister(event_loop).expect("Failed to reregister!");
                    }
                }).ok();
            }
        }
    }
}
<commit_msg>added removal of clients upon hangup<commit_after>extern crate mio;

use client::GameClient;

//use mio::{TryRead, TryWrite};
use mio::tcp::*;
use mio::util::Slab;
use mio::Token;
use mio::{EventLoop, EventSet, PollOpt, Handler};
//use bytes::{Buf, Take};
//use std::mem;
use std::net::SocketAddr;
//use std::io::Cursor;
//use std::thread;
//use std::sync::mpsc;
use std::sync::{Arc, RwLock};
//use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::atomic::AtomicUsize;
//use std::collections::HashMap;

const SERVER_TOKEN: mio::Token = mio::Token(1);

#[derive(Clone)]
pub struct AuthoritativeServerState{
    clients: Arc<RwLock<Slab<GameClient>>>,
    token_counter: Arc<AtomicUsize>
}

impl AuthoritativeServerState{
    pub fn new() -> AuthoritativeServerState{
        AuthoritativeServerState{
            token_counter: Arc::new(AtomicUsize::new(1)),
            // Max 128 connections
            clients: Arc::new(RwLock::new(Slab::new_starting_at(Token(2), 128)))
        }
    }
}

pub struct AuthoritativeServer{
    // The socket on which this server is listening
    socket: TcpListener,

    // The token assigned to this server's own connection
    token: Token,

    // Current state for the server
    state: AuthoritativeServerState
}

impl AuthoritativeServer{
    pub fn new(address: SocketAddr) -> AuthoritativeServer{
        let server_state = AuthoritativeServerState::new();
        let server_state_clone = server_state.clone();

        println!("Starting authoritative server");
        let server_socket = TcpListener::bind(&address).expect("Failed to start socket listener!");

        let mut server = AuthoritativeServer{
            socket: server_socket,
            token: SERVER_TOKEN,
            state: server_state_clone
        };

        let mut event_loop = EventLoop::new().expect("Failed to create server event loop!");

        event_loop.register(&server.socket,
                            SERVER_TOKEN,
                            EventSet::readable(),
                            PollOpt::edge()).expect("Failed to register server with event loop!");

        println!("Running event loop...");
        event_loop.run(&mut server).expect("Failed to run event loop!");

        return server;
    }

    fn start_accept_loop(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>){
        println!("Beginning server accept loop");

        loop{
            let socket = match self.socket.accept(){
                Ok(s) => {
                    match s{
                        Some((socket,_)) => socket,
                        None => {
                            println!("Accept loop encountered WouldBlock");
                            return;
                        }
                    }
                },
                Err(e) => {
                    println!("Failed to accept new socket. Error: {:?}", e);
                    return;
                }
            };

            if let Ok(ref mut clients) = self.state.clients.write(){
                match &clients.insert_with(|token| {
                    println!("Inserting new connection from {:?}", token);
                    GameClient::new(socket, token)
                }) {
                    &Some(token) => {
                        println!("Insertion successful!");
                        let ref mut client: GameClient = clients[token];
                        match client.register(event_loop){
                            Ok(_) => { println!("Registration successful!"); },
                            Err(e) => {
                                println!("Failed to register connection {:?} with event loop, error: {:?}", token, e);
                                //clients.remove(token);
                            }
                        }
                    },
                    &None => {
                        println!("Failed to insert!");
                    }
                }
            };
        }
    }

    fn get_client_mut<'a, F>(&'a mut self, token: Token, mut action: F) -> Result<(), String>
        where F: FnMut(&mut GameClient) {
        if let Ok(mut clients) = self.state.clients.write(){
            if clients.contains(token){
                let ref mut client = clients.get_mut(token).unwrap();

                action(client);

                return Ok(());
            }
        }
        Err(String::from(format!("No client exists with token {:?}", token)))
    }

    fn get_client<'a, F>(&'a mut self, token: Token, action: F) -> Result<(), String>
        where F: Fn(&GameClient) {
        if let Ok(mut clients) = self.state.clients.read(){
            if clients.contains(token){
                let ref mut client = clients.get(token).expect("Clients contains token, but was unable to access client!");

                action(client);

                return Ok(());
            }
        }
        Err(String::from(format!("No client exists with token {:?}", token)))
    }
}

impl Handler for AuthoritativeServer{
    type Timeout = ();
    type Message = ();

    fn tick(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>) {
        println!("Begin server tick!");

        if let Ok(mut clients) = self.state.clients.write(){
            for client in clients.iter_mut(){
                client.reregister(event_loop).ok();
            }
        }

        println!("End server tick!");
    }

    fn ready(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>, token: Token, events: EventSet) {
        assert!(token != Token(0), "We're not supposed to get a Token(0)!");

        if events.is_error(){
            println!("Error event for token {:?}", token);
            //Reset token?
            return;
        }

        if events.is_hup(){
            println!("OH FUCK NO, {:?} DID NOT JUST FUCKING HANG UP ON ME!", token);
            println!("I'M GOING TO FUCKING MURDER YOU FUCKER");

            if let Ok(mut clients) = self.state.clients.write(){
                &clients.remove(token);
            }
            //Reset?
            return;
        }

        if events.is_writable(){
            println!("Oh shit, motherfucking {:?} is writable! Look at this guy!", token);

            //fucking write some shit
        }
        else{
            println!("[{:?} silence intensifies]", token);
        }

        if events.is_readable(){
            println!("GOT SHIT TO READ FROM MY BRAH {:?} HELLLL YEAH", token);

            if self.token == token{
                self.start_accept_loop(event_loop);
            }
            else{
                self.get_client_mut(token, |client|{
                    if client.read().is_ok(){
                        client.reregister(event_loop).expect("Failed to reregister!");
                    }
                }).ok();
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

#[macro_use]
extern crate log;
extern crate osmpbfreader;
extern crate rustc_serialize;
extern crate docopt;
extern crate mimir;
extern crate rs_es;

use std::collections::HashSet;
use std::collections::HashMap;
use mimirsbrunn::rubber::Rubber;
use mimirsbrunn::objects::{Polygon, MultiPolygon};

pub type AdminsVec = Vec<mimir::Admin>;
pub type StreetsVec = Vec<mimir::Street>;
pub type ParsedPbf = osmpbfreader::OsmPbfReader<std::fs::File>;

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_level: Vec<u32>,
    flag_connection_string: String,
}

static USAGE: &'static str = "
Usage:
    osm2mimir --help
    osm2mimir --input=<file> [--connection-string=<connection-string>] --level=<level>...

Options:
    -h, --help            Show this message.
    -i, --input=<file>    OSM PBF file.
    -l, --level=<level>   Admin levels to keep.
    -c, --connection-string=<connection-string>
                          Elasticsearch parameters, [default: http://localhost:9200/munin]
";

#[derive(Debug)]
struct AdminMatcher {
    admin_levels: HashSet<u32>,
}
impl AdminMatcher {
    pub fn new(levels: HashSet<u32>) -> AdminMatcher {
        AdminMatcher { admin_levels: levels }
    }

    pub fn is_admin(&self, obj: &osmpbfreader::OsmObj) -> bool {
        match *obj {
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("boundary").map_or(false, |v| v == "administrative") &&
                rel.tags.get("admin_level").map_or(false, |lvl| {
                    self.admin_levels.contains(&lvl.parse::<u32>().unwrap_or(0))
                })
            }
            _ => false,
        }
    }
}

struct BoundaryPart {
    nodes: Vec<osmpbfreader::Node>,
}

impl BoundaryPart {
    pub fn new(nodes: Vec<osmpbfreader::Node>) -> BoundaryPart {
        BoundaryPart { nodes: nodes }
    }
    pub fn first(&self) -> i64 {
        self.nodes.first().unwrap().id
    }
    pub fn last(&self) -> i64 {
        self.nodes.last().unwrap().id
    }
}

fn get_nodes(way: &osmpbfreader::Way,
             objects: &HashMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>)
             -> Vec<osmpbfreader::Node> {
    way.nodes
       .iter()
       .filter_map(|node_id| objects.get(&osmpbfreader::OsmId::Node(*node_id)))
       .filter_map(|node_obj| if let &osmpbfreader::OsmObj::Node(ref node) = node_obj {
           Some(node.clone())
       } else {
           None
       })
       .collect()
}

fn build_boundary(relation: &osmpbfreader::Relation,
                  objects: &HashMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>)
                  -> Option<MultiPolygon> {
    let mut boundary_parts: Vec<BoundaryPart> =
        relation.refs
                .iter()
                .filter(|rf| rf.role == "outer" || rf.role == "" || rf.role == "enclave")
                .filter_map(|refe| {
                    objects.get(&refe.member).or_else(|| {
                        warn!("missing element for relation {}", relation.id);
                        None
                    })
                })
                .filter_map(|way_obj| if let &osmpbfreader::OsmObj::Way(ref way) = way_obj {
                    Some(way)
                } else {
                    None
                })
                .map(|way| get_nodes(&way, objects))
                .filter(|nodes| nodes.len() > 1)
                .map(|nodes| BoundaryPart::new(nodes))
                .collect();
    let mut multipoly = MultiPolygon { polygons: Vec::new() };
    // we want to try build a polygon for a least each way
    while !boundary_parts.is_empty() {
        let mut current = -1;
        let mut first = 0;
        let mut nb_try = 0;

        let mut outer: Vec<osmpbfreader::Node> = Vec::new();
        // we try to close the polygon, if we can't we want to at least have tried one time per
        // way. We could improve that latter by trying to attach the way to both side of the
        // polygon
        let max_try = boundary_parts.len();
        while current != first && nb_try < max_try {
            let mut i = 0;
            while i < boundary_parts.len() {
                if outer.is_empty() {
                    // our polygon is empty, we initialise it with the current way
                    first = boundary_parts[i].first();
                    current = boundary_parts[i].last();
                    outer.append(&mut boundary_parts[i].nodes);
                    // this way has been used, we remove it from the pool
                    boundary_parts.remove(i);
                    continue;
                }
                if current == boundary_parts[i].first() {
                    // the start of current way touch the polygon, we add it and remove it from the
                    // pool
                    current = boundary_parts[i].last();
                    outer.append(&mut boundary_parts[i].nodes);
                    boundary_parts.remove(i);
                } else if current == boundary_parts[i].last() {
                    // the end of the current way touch the polygon, we reverse the way and add it
                    current = boundary_parts[i].first();
                    boundary_parts[i].nodes.reverse();
                    outer.append(&mut boundary_parts[i].nodes);
                    boundary_parts.remove(i);
                } else {
                    i += 1;
                    // didnt do anything, we want to explore the next way, if we had do something we
                    // will have removed the current way and there will be no need to increment
                }
                if current == first {
                    // our polygon is closed, we create it and add it to the multipolygon
                    let polygon = Polygon::new(outer.iter()
                                                    .map(|n| {
                                                        mimir::Coord {
                                                            lat: n.lat,
                                                            lon: n.lon,
                                                        }
                                                    })
                                                    .collect());
                    multipoly.polygons.push(polygon);
                    break;
                }
            }
            nb_try += 1;
        }
    }
    debug!("polygon for relation {};{}", relation.id, multipoly.to_wkt());
    if multipoly.polygons.is_empty() {
        None
    } else {
        Some(multipoly)
    }
}

fn parse_osm_pbf(path: &String) -> ParsedPbf {
    let path = std::path::Path::new(&path);
    osmpbfreader::OsmPbfReader::new(std::fs::File::open(&path).unwrap())
}

fn administrative_regions(pbf: &mut ParsedPbf, levels: HashSet<u32>) -> AdminsVec {
    let mut administrative_regions = AdminsVec::new();
    let matcher = AdminMatcher::new(levels);
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_admin(o)).unwrap();
    // load administratives regions
    for (_, obj) in &objects {
        if !matcher.is_admin(&obj) {
            continue;
        }
        if let &osmpbfreader::OsmObj::Relation(ref relation) = obj {
            let level = relation.tags
                                .get("admin_level")
                                .and_then(|s| s.parse().ok());
            let level = match level {
                None => {
                    info!("invalid admin_level for relation {}: admin_level {:?}",
                          relation.id,
                          relation.tags.get("admin_level"));
                    continue;
                }
                Some(l) => l,
            };
            // administrative region with name ?
            let name = match relation.tags.get("name") {
                Some(val) => val,
                None => {
                    warn!("adminstrative region without name for relation {}:  admin_level {} \
                           ignored.",
                          relation.id,
                          level);
                    continue;
                }
            };
            // admininstrative region without coordinates
            let coord_centre = relation.refs
                                       .iter()
                                       .find(|rf| rf.role == "admin_centre")
                                       .and_then(|r| {
                                           objects.get(&r.member).and_then(|value| {
                                               match value {
                                                   &osmpbfreader::OsmObj::Node(ref node) => {
                                                       Some(mimir::Coord {
                                                           lat: node.lat,
                                                           lon: node.lon,
                                                       })
                                                   }
                                                   _ => None,
                                               }
                                           })
                                       });

            let admin_id = match relation.tags.get("ref:INSEE") {
                Some(val) => format!("admin:fr:{}", val.trim_left_matches('0')),
                None => format!("admin:osm:{}", relation.id),
            };
            let zip_code = match relation.tags.get("addr:postcode") {
                Some(val) => &val[..],
                None => "",
            };
            let boundary = build_boundary(&relation, &objects);
            let admin = mimir::Admin {
                id: admin_id,
                level: level,
                name: name.to_string(),
                zip_code: zip_code.to_string(),
                // TODO weight value ?
                weight: 1,
                coord: coord_centre,
                boundary: boundary,
            };
            administrative_regions.push(admin);
        }
    }
    return administrative_regions;
}

fn streets(pbf: &mut ParsedPbf) -> StreetsVec {

    let is_valid_street = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                way.tags.get("highway").map_or(false, |x: &String| !x.is_empty()) &&
                way.tags.get("name").map_or(false, |x: &String| !x.is_empty())
            }
            _ => false,
        }
    };

    let is_associated_street_relation = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("type").map_or(false, |v| v == "associatedStreet")
            }
            _ => false,
        }
    };

    let mut street_map = osmpbfreader::get_objs_and_deps(pbf, is_valid_street).unwrap();
    let relation_map = osmpbfreader::get_objs_and_deps(pbf, is_associated_street_relation).unwrap();

    // Sometimes, streets can be devided into several "way"s that still have the same street name.
    // The reason why a street is devided may be that a part of the street become a bridge/tunne/etc.
    // In this case, a "relation" tagged with (type = associatedStreet) is used to group all these "way"s.
    // In order not to have doublons in autocompleion, we should keep only one "way" in the relation
    // and remove all the rest way whose street name is the same.
    for (_, rel_obj) in &relation_map {
        if let &osmpbfreader::OsmObj::Relation(ref rel) = rel_obj {
            let mut found = false;
            for ref_obj in &rel.refs {
                if let &osmpbfreader::OsmId::Way(_) = &ref_obj.member {
                    if !found {
                        found = true;
                        continue;
                    };
                    street_map.remove(&ref_obj.member);
                };
            }
        };
    }

    street_map.iter()
              .filter_map(|(osm_id, obj)| {
                  if let &osmpbfreader::OsmObj::Way(ref way) = obj {
                      if let &osmpbfreader::OsmId::Way(ref way_id) = osm_id {
                          way.tags.get("name").and_then(|way_name| {
                              Some(mimirsbrunn::Street {
                                  id: way_id.to_string(),
                                  street_name: way_name.to_string(),
                                  name: way_name.to_string(),
                                  weight: 1,
                                  administrative_region: None,
                              })
                          })
                      } else {
                          None
                      }
                  } else {
                      None
                  }
              })
              .collect()

}

fn index_osm(es_cnx_string: &str, admins: &AdminsVec, streets: &StreetsVec) {
    let mut rubber = Rubber::new(es_cnx_string);
    rubber.create_index();
    match rubber.clean_db_by_doc_type(&["admin", "street"]) {
        Err(e) => panic!("failed to clean data by document type: {}", e),
        Ok(nb) => info!("clean data by document type : {}", nb),
    }
    info!("Add data in elasticsearch db.");
    match rubber.bulk_index(admins.iter()) {
        Err(e) => panic!("failed to index admins of osm because: {}", e),
        Ok(nb) => info!("Nb of indexed adminstrative regions: {}", nb),
    }

    match rubber.bulk_index(streets.iter()) {
        Err(e) => panic!("failed to index streets of osm because: {}", e),
        Ok(nb) => info!("Nb of indexed streets: {}", nb),
    }
}

fn main() {
    mimir::logger_init().unwrap();
    debug!("importing adminstrative region into Mimir");
    let args: Args = docopt::Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    let levels = args.flag_level.iter().cloned().collect();
    let mut parsed_pbf = parse_osm_pbf(&args.flag_input);
    let admins = administrative_regions(&mut parsed_pbf, levels);
    let streets = streets(&mut parsed_pbf);
    index_osm(&args.flag_connection_string, &admins, &streets);
}
<commit_msg>deactivate index street<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

#[macro_use]
extern crate log;
extern crate osmpbfreader;
extern crate rustc_serialize;
extern crate docopt;
extern crate mimir;
extern crate rs_es;

use std::collections::HashSet;
use std::collections::HashMap;
use mimirsbrunn::rubber::Rubber;
use mimirsbrunn::objects::{Polygon, MultiPolygon};

pub type AdminsVec = Vec<mimir::Admin>;
pub type StreetsVec = Vec<mimir::Street>;
pub type ParsedPbf = osmpbfreader::OsmPbfReader<std::fs::File>;

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_level: Vec<u32>,
    flag_connection_string: String,
}

static USAGE: &'static str = "
Usage:
    osm2mimir --help
    osm2mimir --input=<file> [--connection-string=<connection-string>] --level=<level>...

Options:
    -h, --help            Show this message.
    -i, --input=<file>    OSM PBF file.
    -l, --level=<level>   Admin levels to keep.
    -c, --connection-string=<connection-string>
                          Elasticsearch parameters, [default: http://localhost:9200/munin]
";

#[derive(Debug)]
struct AdminMatcher {
    admin_levels: HashSet<u32>,
}
impl AdminMatcher {
    pub fn new(levels: HashSet<u32>) -> AdminMatcher {
        AdminMatcher { admin_levels: levels }
    }

    pub fn is_admin(&self, obj: &osmpbfreader::OsmObj) -> bool {
        match *obj {
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("boundary").map_or(false, |v| v == "administrative") &&
                rel.tags.get("admin_level").map_or(false, |lvl| {
                    self.admin_levels.contains(&lvl.parse::<u32>().unwrap_or(0))
                })
            }
            _ => false,
        }
    }
}

struct BoundaryPart {
    nodes: Vec<osmpbfreader::Node>,
}

impl BoundaryPart {
    pub fn new(nodes: Vec<osmpbfreader::Node>) -> BoundaryPart {
        BoundaryPart { nodes: nodes }
    }
    pub fn first(&self) -> i64 {
        self.nodes.first().unwrap().id
    }
    pub fn last(&self) -> i64 {
        self.nodes.last().unwrap().id
    }
}

fn get_nodes(way: &osmpbfreader::Way,
             objects: &HashMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>)
             -> Vec<osmpbfreader::Node> {
    way.nodes
       .iter()
       .filter_map(|node_id| objects.get(&osmpbfreader::OsmId::Node(*node_id)))
       .filter_map(|node_obj| if let &osmpbfreader::OsmObj::Node(ref node) = node_obj {
           Some(node.clone())
       } else {
           None
       })
       .collect()
}

fn build_boundary(relation: &osmpbfreader::Relation,
                  objects: &HashMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>)
                  -> Option<MultiPolygon> {
    let mut boundary_parts: Vec<BoundaryPart> =
        relation.refs
                .iter()
                .filter(|rf| rf.role == "outer" || rf.role == "" || rf.role == "enclave")
                .filter_map(|refe| {
                    objects.get(&refe.member).or_else(|| {
                        warn!("missing element for relation {}", relation.id);
                        None
                    })
                })
                .filter_map(|way_obj| if let &osmpbfreader::OsmObj::Way(ref way) = way_obj {
                    Some(way)
                } else {
                    None
                })
                .map(|way| get_nodes(&way, objects))
                .filter(|nodes| nodes.len() > 1)
                .map(|nodes| BoundaryPart::new(nodes))
                .collect();
    let mut multipoly = MultiPolygon { polygons: Vec::new() };
    // we want to try build a polygon for a least each way
    while !boundary_parts.is_empty() {
        let mut current = -1;
        let mut first = 0;
        let mut nb_try = 0;

        let mut outer: Vec<osmpbfreader::Node> = Vec::new();
        // we try to close the polygon, if we can't we want to at least have tried one time per
        // way. We could improve that latter by trying to attach the way to both side of the
        // polygon
        let max_try = boundary_parts.len();
        while current != first && nb_try < max_try {
            let mut i = 0;
            while i < boundary_parts.len() {
                if outer.is_empty() {
                    // our polygon is empty, we initialise it with the current way
                    first = boundary_parts[i].first();
                    current = boundary_parts[i].last();
                    outer.append(&mut boundary_parts[i].nodes);
                    // this way has been used, we remove it from the pool
                    boundary_parts.remove(i);
                    continue;
                }
                if current == boundary_parts[i].first() {
                    // the start of current way touch the polygon, we add it and remove it from the
                    // pool
                    current = boundary_parts[i].last();
                    outer.append(&mut boundary_parts[i].nodes);
                    boundary_parts.remove(i);
                } else if current == boundary_parts[i].last() {
                    // the end of the current way touch the polygon, we reverse the way and add it
                    current = boundary_parts[i].first();
                    boundary_parts[i].nodes.reverse();
                    outer.append(&mut boundary_parts[i].nodes);
                    boundary_parts.remove(i);
                } else {
                    i += 1;
                    // didnt do anything, we want to explore the next way, if we had do something we
                    // will have removed the current way and there will be no need to increment
                }
                if current == first {
                    // our polygon is closed, we create it and add it to the multipolygon
                    let polygon = Polygon::new(outer.iter()
                                                    .map(|n| {
                                                        mimir::Coord {
                                                            lat: n.lat,
                                                            lon: n.lon,
                                                        }
                                                    })
                                                    .collect());
                    multipoly.polygons.push(polygon);
                    break;
                }
            }
            nb_try += 1;
        }
    }
    debug!("polygon for relation {};{}", relation.id, multipoly.to_wkt());
    if multipoly.polygons.is_empty() {
        None
    } else {
        Some(multipoly)
    }
}

fn parse_osm_pbf(path: &String) -> ParsedPbf {
    let path = std::path::Path::new(&path);
    osmpbfreader::OsmPbfReader::new(std::fs::File::open(&path).unwrap())
}

fn administrative_regions(pbf: &mut ParsedPbf, levels: HashSet<u32>) -> AdminsVec {
    let mut administrative_regions = AdminsVec::new();
    let matcher = AdminMatcher::new(levels);
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_admin(o)).unwrap();
    // load administratives regions
    for (_, obj) in &objects {
        if !matcher.is_admin(&obj) {
            continue;
        }
        if let &osmpbfreader::OsmObj::Relation(ref relation) = obj {
            let level = relation.tags
                                .get("admin_level")
                                .and_then(|s| s.parse().ok());
            let level = match level {
                None => {
                    info!("invalid admin_level for relation {}: admin_level {:?}",
                          relation.id,
                          relation.tags.get("admin_level"));
                    continue;
                }
                Some(l) => l,
            };
            // administrative region with name ?
            let name = match relation.tags.get("name") {
                Some(val) => val,
                None => {
                    warn!("adminstrative region without name for relation {}:  admin_level {} \
                           ignored.",
                          relation.id,
                          level);
                    continue;
                }
            };
            // admininstrative region without coordinates
            let coord_centre = relation.refs
                                       .iter()
                                       .find(|rf| rf.role == "admin_centre")
                                       .and_then(|r| {
                                           objects.get(&r.member).and_then(|value| {
                                               match value {
                                                   &osmpbfreader::OsmObj::Node(ref node) => {
                                                       Some(mimir::Coord {
                                                           lat: node.lat,
                                                           lon: node.lon,
                                                       })
                                                   }
                                                   _ => None,
                                               }
                                           })
                                       });

            let admin_id = match relation.tags.get("ref:INSEE") {
                Some(val) => format!("admin:fr:{}", val.trim_left_matches('0')),
                None => format!("admin:osm:{}", relation.id),
            };
            let zip_code = match relation.tags.get("addr:postcode") {
                Some(val) => &val[..],
                None => "",
            };
            let boundary = build_boundary(&relation, &objects);
            let admin = mimir::Admin {
                id: admin_id,
                level: level,
                name: name.to_string(),
                zip_code: zip_code.to_string(),
                // TODO weight value ?
                weight: 1,
                coord: coord_centre,
                boundary: boundary,
            };
            administrative_regions.push(admin);
        }
    }
    return administrative_regions;
}

fn streets(pbf: &mut ParsedPbf) -> StreetsVec {

    let is_valid_street = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                way.tags.get("highway").map_or(false, |x: &String| !x.is_empty()) &&
                way.tags.get("name").map_or(false, |x: &String| !x.is_empty())
            }
            _ => false,
        }
    };

    let is_associated_street_relation = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("type").map_or(false, |v| v == "associatedStreet")
            }
            _ => false,
        }
    };

    let mut street_map = osmpbfreader::get_objs_and_deps(pbf, is_valid_street).unwrap();
    let relation_map = osmpbfreader::get_objs_and_deps(pbf, is_associated_street_relation).unwrap();

    // Sometimes, streets can be devided into several "way"s that still have the same street name.
    // The reason why a street is devided may be that a part of the street become a bridge/tunne/etc.
    // In this case, a "relation" tagged with (type = associatedStreet) is used to group all these "way"s.
    // In order not to have doublons in autocompleion, we should keep only one "way" in the relation
    // and remove all the rest way whose street name is the same.
    for (_, rel_obj) in &relation_map {
        if let &osmpbfreader::OsmObj::Relation(ref rel) = rel_obj {
            let mut found = false;
            for ref_obj in &rel.refs {
                if let &osmpbfreader::OsmId::Way(_) = &ref_obj.member {
                    if !found {
                        found = true;
                        continue;
                    };
                    street_map.remove(&ref_obj.member);
                };
            }
        };
    }

    street_map.iter()
              .filter_map(|(osm_id, obj)| {
                  if let &osmpbfreader::OsmObj::Way(ref way) = obj {
                      if let &osmpbfreader::OsmId::Way(ref way_id) = osm_id {
                          way.tags.get("name").and_then(|way_name| {
                              Some(mimirsbrunn::Street {
                                  id: way_id.to_string(),
                                  street_name: way_name.to_string(),
                                  name: way_name.to_string(),
                                  weight: 1,
                                  administrative_region: None,
                              })
                          })
                      } else {
                          None
                      }
                  } else {
                      None
                  }
              })
              .collect()

}

fn index_osm(es_cnx_string: &str, admins: &AdminsVec, streets: &StreetsVec) {
    let mut rubber = Rubber::new(es_cnx_string);
    rubber.create_index();
    match rubber.clean_db_by_doc_type(&["admin", "street"]) {
        Err(e) => panic!("failed to clean data by document type: {}", e),
        Ok(nb) => info!("clean data by document type : {}", nb),
    }
    info!("Add data in elasticsearch db.");
    match rubber.bulk_index(admins.iter()) {
        Err(e) => panic!("failed to index admins of osm because: {}", e),
        Ok(nb) => info!("Nb of indexed adminstrative regions: {}", nb),
    }

    // TODO: make it (de)activable from command line
    if false {
        match rubber.bulk_index(streets.iter()) {
            Err(e) => panic!("failed to index streets of osm because: {}", e),
            Ok(nb) => info!("Nb of indexed streets: {}", nb),
        }
    }
}

fn main() {
    mimir::logger_init().unwrap();
    debug!("importing adminstrative region into Mimir");
    let args: Args = docopt::Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    let levels = args.flag_level.iter().cloned().collect();
    let mut parsed_pbf = parse_osm_pbf(&args.flag_input);
    let admins = administrative_regions(&mut parsed_pbf, levels);
    let streets = streets(&mut parsed_pbf);
    index_osm(&args.flag_connection_string, &admins, &streets);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! Different objects protected by the same lock

use crate::str::{CssString, CssStringWriter};
use crate::stylesheets::Origin;
#[cfg(feature = "gecko")]
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
#[cfg(feature = "servo")]
use parking_lot::RwLock;
use servo_arc::Arc;
use std::cell::UnsafeCell;
use std::fmt;
#[cfg(feature = "servo")]
use std::mem;
#[cfg(feature = "gecko")]
use std::ptr;

/// A shared read/write lock that can protect multiple objects.
///
/// In Gecko builds, we don't need the blocking behavior, just the safety. As
/// such we implement this with an AtomicRefCell instead in Gecko builds,
/// which is ~2x as fast, and panics (rather than deadlocking) when things go
/// wrong (which is much easier to debug on CI).
///
/// Servo needs the blocking behavior for its unsynchronized animation setup,
/// but that may not be web-compatible and may need to be changed (at which
/// point Servo could use AtomicRefCell too).
#[derive(Clone)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
pub struct SharedRwLock {
    #[cfg(feature = "servo")]
    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
    arc: Arc<RwLock<()>>,

    #[cfg(feature = "gecko")]
    cell: Arc<AtomicRefCell<SomethingZeroSizedButTyped>>,
}

#[cfg(feature = "gecko")]
struct SomethingZeroSizedButTyped;

impl fmt::Debug for SharedRwLock {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("SharedRwLock")
    }
}

impl SharedRwLock {
    /// Create a new shared lock (servo).
    #[cfg(feature = "servo")]
    pub fn new() -> Self {
        SharedRwLock {
            arc: Arc::new(RwLock::new(())),
        }
    }

    /// Create a new shared lock (gecko).
    #[cfg(feature = "gecko")]
    pub fn new() -> Self {
        SharedRwLock {
            cell: Arc::new(AtomicRefCell::new(SomethingZeroSizedButTyped)),
        }
    }

    /// Wrap the given data to make its access protected by this lock.
    pub fn wrap<T>(&self, data: T) -> Locked<T> {
        Locked {
            shared_lock: self.clone(),
            data: UnsafeCell::new(data),
        }
    }

    /// Obtain the lock for reading (servo).
    #[cfg(feature = "servo")]
    pub fn read(&self) -> SharedRwLockReadGuard {
        mem::forget(self.arc.read());
        SharedRwLockReadGuard(self)
    }

    /// Obtain the lock for reading (gecko).
    #[cfg(feature = "gecko")]
    pub fn read(&self) -> SharedRwLockReadGuard {
        SharedRwLockReadGuard(self.cell.borrow())
    }

    /// Obtain the lock for writing (servo).
    #[cfg(feature = "servo")]
    pub fn write(&self) -> SharedRwLockWriteGuard {
        mem::forget(self.arc.write());
        SharedRwLockWriteGuard(self)
    }

    /// Obtain the lock for writing (gecko).
    #[cfg(feature = "gecko")]
    pub fn write(&self) -> SharedRwLockWriteGuard {
        SharedRwLockWriteGuard(self.cell.borrow_mut())
    }
}

/// Proof that a shared lock was obtained for reading (servo).
#[cfg(feature = "servo")]
pub struct SharedRwLockReadGuard<'a>(&'a SharedRwLock);
/// Proof that a shared lock was obtained for writing (gecko).
#[cfg(feature = "gecko")]
pub struct SharedRwLockReadGuard<'a>(AtomicRef<'a, SomethingZeroSizedButTyped>);
#[cfg(feature = "servo")]
impl<'a> Drop for SharedRwLockReadGuard<'a> {
    fn drop(&mut self) {
        // Unsafe: self.lock is private to this module, only ever set after `read()`,
        // and never copied or cloned (see `compile_time_assert` below).
        unsafe { self.0.arc.force_unlock_read() }
    }
}

/// Proof that a shared lock was obtained for writing (servo).
#[cfg(feature = "servo")]
pub struct SharedRwLockWriteGuard<'a>(&'a SharedRwLock);
/// Proof that a shared lock was obtained for writing (gecko).
#[cfg(feature = "gecko")]
pub struct SharedRwLockWriteGuard<'a>(AtomicRefMut<'a, SomethingZeroSizedButTyped>);
#[cfg(feature = "servo")]
impl<'a> Drop for SharedRwLockWriteGuard<'a> {
    fn drop(&mut self) {
        // Unsafe: self.lock is private to this module, only ever set after `write()`,
        // and never copied or cloned (see `compile_time_assert` below).
        unsafe { self.0.arc.force_unlock_write() }
    }
}

/// Data protect by a shared lock.
pub struct Locked<T> {
    shared_lock: SharedRwLock,
    data: UnsafeCell<T>,
}

// Unsafe: the data inside `UnsafeCell` is only accessed in `read_with` and `write_with`,
// where guards ensure synchronization.
unsafe impl<T: Send> Send for Locked<T> {}
unsafe impl<T: Send + Sync> Sync for Locked<T> {}

impl<T: fmt::Debug> fmt::Debug for Locked<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let guard = self.shared_lock.read();
        self.read_with(&guard).fmt(f)
    }
}

impl<T> Locked<T> {
    #[cfg(feature = "servo")]
    fn same_lock_as(&self, lock: &SharedRwLock) -> bool {
        Arc::ptr_eq(&self.shared_lock.arc, &lock.arc)
    }

    #[cfg(feature = "gecko")]
    fn same_lock_as(&self, derefed_guard: &SomethingZeroSizedButTyped) -> bool {
        ptr::eq(self.shared_lock.cell.as_ptr(), derefed_guard)
    }

    /// Access the data for reading.
    pub fn read_with<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a T {
        assert!(
            self.same_lock_as(&guard.0),
            "Locked::read_with called with a guard from an unrelated SharedRwLock"
        );
        let ptr = self.data.get();

        // Unsafe:
        //
        // * The guard guarantees that the lock is taken for reading,
        //   and we’ve checked that it’s the correct lock.
        // * The returned reference borrows *both* the data and the guard,
        //   so that it can outlive neither.
        unsafe { &*ptr }
    }

    /// Access the data for reading without verifying the lock. Use with caution.
    #[cfg(feature = "gecko")]
    pub unsafe fn read_unchecked<'a>(&'a self) -> &'a T {
        let ptr = self.data.get();
        &*ptr
    }

    /// Access the data for writing.
    pub fn write_with<'a>(&'a self, guard: &'a mut SharedRwLockWriteGuard) -> &'a mut T {
        assert!(
            self.same_lock_as(&guard.0),
            "Locked::write_with called with a guard from an unrelated SharedRwLock"
        );
        let ptr = self.data.get();

        // Unsafe:
        //
        // * The guard guarantees that the lock is taken for writing,
        //   and we’ve checked that it’s the correct lock.
        // * The returned reference borrows *both* the data and the guard,
        //   so that it can outlive neither.
        // * We require a mutable borrow of the guard,
        //   so that one write guard can only be used once at a time.
        unsafe { &mut *ptr }
    }
}

#[allow(dead_code)]
mod compile_time_assert {
    use super::{SharedRwLockReadGuard, SharedRwLockWriteGuard};

    trait Marker1 {}
    impl<T: Clone> Marker1 for T {}
    impl<'a> Marker1 for SharedRwLockReadGuard<'a> {} // Assert SharedRwLockReadGuard: !Clone
    impl<'a> Marker1 for SharedRwLockWriteGuard<'a> {} // Assert SharedRwLockWriteGuard: !Clone

    trait Marker2 {}
    impl<T: Copy> Marker2 for T {}
    impl<'a> Marker2 for SharedRwLockReadGuard<'a> {} // Assert SharedRwLockReadGuard: !Copy
    impl<'a> Marker2 for SharedRwLockWriteGuard<'a> {} // Assert SharedRwLockWriteGuard: !Copy
}

/// Like ToCss, but with a lock guard given by the caller, and with the writer specified
/// concretely rather than with a parameter.
pub trait ToCssWithGuard {
    /// Serialize `self` in CSS syntax, writing to `dest`, using the given lock guard.
    fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result;

    /// Serialize `self` in CSS syntax using the given lock guard and return a string.
    ///
    /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
    #[inline]
    fn to_css_string(&self, guard: &SharedRwLockReadGuard) -> CssString {
        let mut s = CssString::new();
        self.to_css(guard, &mut s).unwrap();
        s
    }
}

/// Parameters needed for deep clones.
#[cfg(feature = "gecko")]
pub struct DeepCloneParams {
    /// The new sheet we're cloning rules into.
    pub reference_sheet: *const crate::gecko_bindings::structs::StyleSheet,
}

/// Parameters needed for deep clones.
#[cfg(feature = "servo")]
pub struct DeepCloneParams;

/// A trait to do a deep clone of a given CSS type. Gets a lock and a read
/// guard, in order to be able to read and clone nested structures.
pub trait DeepCloneWithLock: Sized {
    /// Deep clones this object.
    fn deep_clone_with_lock(
        &self,
        lock: &SharedRwLock,
        guard: &SharedRwLockReadGuard,
        params: &DeepCloneParams,
    ) -> Self;
}

/// Guards for a document
#[derive(Clone)]
pub struct StylesheetGuards<'a> {
    /// For author-origin stylesheets.
    pub author: &'a SharedRwLockReadGuard<'a>,

    /// For user-agent-origin and user-origin stylesheets
    pub ua_or_user: &'a SharedRwLockReadGuard<'a>,
}

impl<'a> StylesheetGuards<'a> {
    /// Get the guard for a given stylesheet origin.
    pub fn for_origin(&self, origin: Origin) -> &SharedRwLockReadGuard<'a> {
        match origin {
            Origin::Author => &self.author,
            _ => &self.ua_or_user,
        }
    }

    /// Same guard for all origins
    pub fn same(guard: &'a SharedRwLockReadGuard<'a>) -> Self {
        StylesheetGuards {
            author: guard,
            ua_or_user: guard,
        }
    }
}
<commit_msg>style: Add support for read only SharedRwLocks, which don't need any locking.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! Different objects protected by the same lock

use crate::str::{CssString, CssStringWriter};
use crate::stylesheets::Origin;
#[cfg(feature = "gecko")]
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
#[cfg(feature = "servo")]
use parking_lot::RwLock;
use servo_arc::Arc;
use std::cell::UnsafeCell;
use std::fmt;
#[cfg(feature = "servo")]
use std::mem;
#[cfg(feature = "gecko")]
use std::ptr;

/// A shared read/write lock that can protect multiple objects.
///
/// In Gecko builds, we don't need the blocking behavior, just the safety. As
/// such we implement this with an AtomicRefCell instead in Gecko builds,
/// which is ~2x as fast, and panics (rather than deadlocking) when things go
/// wrong (which is much easier to debug on CI).
///
/// Servo needs the blocking behavior for its unsynchronized animation setup,
/// but that may not be web-compatible and may need to be changed (at which
/// point Servo could use AtomicRefCell too).
///
/// Gecko also needs the ability to have "read only" SharedRwLocks, which are
/// used for objects stored in (read only) shared memory. Attempting to acquire
/// write access to objects protected by a read only SharedRwLock will panic.
#[derive(Clone)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
pub struct SharedRwLock {
    #[cfg(feature = "servo")]
    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
    arc: Arc<RwLock<()>>,

    #[cfg(feature = "gecko")]
    cell: Option<Arc<AtomicRefCell<SomethingZeroSizedButTyped>>>,
}

#[cfg(feature = "gecko")]
struct SomethingZeroSizedButTyped;

impl fmt::Debug for SharedRwLock {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("SharedRwLock")
    }
}

impl SharedRwLock {
    /// Create a new shared lock (servo).
    #[cfg(feature = "servo")]
    pub fn new() -> Self {
        SharedRwLock {
            arc: Arc::new(RwLock::new(())),
        }
    }

    /// Create a new shared lock (gecko).
    #[cfg(feature = "gecko")]
    pub fn new() -> Self {
        SharedRwLock {
            cell: Some(Arc::new(AtomicRefCell::new(SomethingZeroSizedButTyped))),
        }
    }

    /// Create a new read-only shared lock (gecko).
    #[cfg(feature = "gecko")]
    pub fn read_only() -> Self {
        SharedRwLock { cell: None }
    }

    /// Wrap the given data to make its access protected by this lock.
    pub fn wrap<T>(&self, data: T) -> Locked<T> {
        Locked {
            shared_lock: self.clone(),
            data: UnsafeCell::new(data),
        }
    }

    /// Obtain the lock for reading (servo).
    #[cfg(feature = "servo")]
    pub fn read(&self) -> SharedRwLockReadGuard {
        mem::forget(self.arc.read());
        SharedRwLockReadGuard(self)
    }

    /// Obtain the lock for reading (gecko).
    #[cfg(feature = "gecko")]
    pub fn read(&self) -> SharedRwLockReadGuard {
        SharedRwLockReadGuard(self.cell.as_ref().map(|cell| cell.borrow()))
    }

    /// Obtain the lock for writing (servo).
    #[cfg(feature = "servo")]
    pub fn write(&self) -> SharedRwLockWriteGuard {
        mem::forget(self.arc.write());
        SharedRwLockWriteGuard(self)
    }

    /// Obtain the lock for writing (gecko).
    #[cfg(feature = "gecko")]
    pub fn write(&self) -> SharedRwLockWriteGuard {
        SharedRwLockWriteGuard(self.cell.as_ref().unwrap().borrow_mut())
    }
}

/// Proof that a shared lock was obtained for reading (servo).
#[cfg(feature = "servo")]
pub struct SharedRwLockReadGuard<'a>(&'a SharedRwLock);
/// Proof that a shared lock was obtained for reading (gecko).
#[cfg(feature = "gecko")]
pub struct SharedRwLockReadGuard<'a>(Option<AtomicRef<'a, SomethingZeroSizedButTyped>>);
#[cfg(feature = "servo")]
impl<'a> Drop for SharedRwLockReadGuard<'a> {
    fn drop(&mut self) {
        // Unsafe: self.lock is private to this module, only ever set after `read()`,
        // and never copied or cloned (see `compile_time_assert` below).
        if let Some(arc) = self.0.arc {
            unsafe {
                arc.force_unlock_read();
            }
        }
    }
}

/// Proof that a shared lock was obtained for writing (servo).
#[cfg(feature = "servo")]
pub struct SharedRwLockWriteGuard<'a>(&'a SharedRwLock);
/// Proof that a shared lock was obtained for writing (gecko).
#[cfg(feature = "gecko")]
pub struct SharedRwLockWriteGuard<'a>(AtomicRefMut<'a, SomethingZeroSizedButTyped>);
#[cfg(feature = "servo")]
impl<'a> Drop for SharedRwLockWriteGuard<'a> {
    fn drop(&mut self) {
        // Unsafe: self.lock is private to this module, only ever set after `write()`,
        // and never copied or cloned (see `compile_time_assert` below).
        unsafe { self.0.arc.force_unlock_write() }
    }
}

/// Data protect by a shared lock.
pub struct Locked<T> {
    shared_lock: SharedRwLock,
    data: UnsafeCell<T>,
}

// Unsafe: the data inside `UnsafeCell` is only accessed in `read_with` and `write_with`,
// where guards ensure synchronization.
unsafe impl<T: Send> Send for Locked<T> {}
unsafe impl<T: Send + Sync> Sync for Locked<T> {}

impl<T: fmt::Debug> fmt::Debug for Locked<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let guard = self.shared_lock.read();
        self.read_with(&guard).fmt(f)
    }
}

impl<T> Locked<T> {
    #[cfg(feature = "servo")]
    #[inline]
    fn is_read_only_lock(&self) -> bool {
        false
    }

    #[cfg(feature = "gecko")]
    #[inline]
    fn is_read_only_lock(&self) -> bool {
        self.shared_lock.cell.is_none()
    }

    #[cfg(feature = "servo")]
    fn same_lock_as(&self, lock: &SharedRwLock) -> bool {
        Arc::ptr_eq(&self.shared_lock.arc, &lock.arc)
    }

    #[cfg(feature = "gecko")]
    fn same_lock_as(&self, derefed_guard: Option<&SomethingZeroSizedButTyped>) -> bool {
        ptr::eq(
            self.shared_lock
                .cell
                .as_ref()
                .map(|cell| cell.as_ptr())
                .unwrap_or(ptr::null_mut()),
            derefed_guard
                .map(|guard| guard as *const _ as *mut _)
                .unwrap_or(ptr::null_mut()),
        )
    }

    /// Access the data for reading.
    pub fn read_with<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a T {
        assert!(
            self.is_read_only_lock() || self.same_lock_as(guard.0.as_ref().map(|r| &**r)),
            "Locked::read_with called with a guard from an unrelated SharedRwLock"
        );
        let ptr = self.data.get();

        // Unsafe:
        //
        // * The guard guarantees that the lock is taken for reading,
        //   and we’ve checked that it’s the correct lock.
        // * The returned reference borrows *both* the data and the guard,
        //   so that it can outlive neither.
        unsafe { &*ptr }
    }

    /// Access the data for reading without verifying the lock. Use with caution.
    #[cfg(feature = "gecko")]
    pub unsafe fn read_unchecked<'a>(&'a self) -> &'a T {
        let ptr = self.data.get();
        &*ptr
    }

    /// Access the data for writing.
    pub fn write_with<'a>(&'a self, guard: &'a mut SharedRwLockWriteGuard) -> &'a mut T {
        assert!(
            !self.is_read_only_lock() && self.same_lock_as(Some(&guard.0)),
            "Locked::write_with called with a guard from a read only or unrelated SharedRwLock"
        );
        let ptr = self.data.get();

        // Unsafe:
        //
        // * The guard guarantees that the lock is taken for writing,
        //   and we’ve checked that it’s the correct lock.
        // * The returned reference borrows *both* the data and the guard,
        //   so that it can outlive neither.
        // * We require a mutable borrow of the guard,
        //   so that one write guard can only be used once at a time.
        unsafe { &mut *ptr }
    }
}

#[allow(dead_code)]
mod compile_time_assert {
    use super::{SharedRwLockReadGuard, SharedRwLockWriteGuard};

    trait Marker1 {}
    impl<T: Clone> Marker1 for T {}
    impl<'a> Marker1 for SharedRwLockReadGuard<'a> {} // Assert SharedRwLockReadGuard: !Clone
    impl<'a> Marker1 for SharedRwLockWriteGuard<'a> {} // Assert SharedRwLockWriteGuard: !Clone

    trait Marker2 {}
    impl<T: Copy> Marker2 for T {}
    impl<'a> Marker2 for SharedRwLockReadGuard<'a> {} // Assert SharedRwLockReadGuard: !Copy
    impl<'a> Marker2 for SharedRwLockWriteGuard<'a> {} // Assert SharedRwLockWriteGuard: !Copy
}

/// Like ToCss, but with a lock guard given by the caller, and with the writer specified
/// concretely rather than with a parameter.
pub trait ToCssWithGuard {
    /// Serialize `self` in CSS syntax, writing to `dest`, using the given lock guard.
    fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result;

    /// Serialize `self` in CSS syntax using the given lock guard and return a string.
    ///
    /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
    #[inline]
    fn to_css_string(&self, guard: &SharedRwLockReadGuard) -> CssString {
        let mut s = CssString::new();
        self.to_css(guard, &mut s).unwrap();
        s
    }
}

/// Parameters needed for deep clones.
#[cfg(feature = "gecko")]
pub struct DeepCloneParams {
    /// The new sheet we're cloning rules into.
    pub reference_sheet: *const crate::gecko_bindings::structs::StyleSheet,
}

/// Parameters needed for deep clones.
#[cfg(feature = "servo")]
pub struct DeepCloneParams;

/// A trait to do a deep clone of a given CSS type. Gets a lock and a read
/// guard, in order to be able to read and clone nested structures.
pub trait DeepCloneWithLock: Sized {
    /// Deep clones this object.
    fn deep_clone_with_lock(
        &self,
        lock: &SharedRwLock,
        guard: &SharedRwLockReadGuard,
        params: &DeepCloneParams,
    ) -> Self;
}

/// Guards for a document
#[derive(Clone)]
pub struct StylesheetGuards<'a> {
    /// For author-origin stylesheets.
    pub author: &'a SharedRwLockReadGuard<'a>,

    /// For user-agent-origin and user-origin stylesheets
    pub ua_or_user: &'a SharedRwLockReadGuard<'a>,
}

impl<'a> StylesheetGuards<'a> {
    /// Get the guard for a given stylesheet origin.
    pub fn for_origin(&self, origin: Origin) -> &SharedRwLockReadGuard<'a> {
        match origin {
            Origin::Author => &self.author,
            _ => &self.ua_or_user,
        }
    }

    /// Same guard for all origins
    pub fn same(guard: &'a SharedRwLockReadGuard<'a>) -> Self {
        StylesheetGuards {
            author: guard,
            ua_or_user: guard,
        }
    }
}
<|endoftext|>


<commit_before>use std::old_io::{File, Open, Read};
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    path: Option<Path>,
    pub cursor: Position,
}

impl Buffer {
    /// Returns the contents of the buffer as a string.
    ///
    /// # Examples
    ///
    /// ```
    /// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
    /// assert_eq!(buffer.data(), "it works!\n");
    /// ```
    pub fn data(&self) -> String {
        self.data.to_string()
    }
}

/// Creates a new empty buffer. The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::new();
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn new() -> Buffer {
    let data = gap_buffer::new(String::new());
    let cursor = Position{ line: 0, offset: 0 };

    Buffer{ data: data, path: None, cursor: cursor }
}

/// Creates a new buffer by reading the UTF-8 interpreted file contents of the specified path.
/// The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
/// assert_eq!(buffer.data(), "it works!\n");
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, Read) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);
    let cursor = Position{ line: 0, offset: 0 };

    // Create a new buffer using the loaded data, path, and other defaults.
    Ok(Buffer{ data: data, path: Some(path.clone()), cursor: cursor })
}
<commit_msg>Implement buffer insert method.<commit_after>use std::old_io::{File, Open, Read};
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    path: Option<Path>,
    pub cursor: Position,
}

impl Buffer {
    /// Returns the contents of the buffer as a string.
    ///
    /// # Examples
    ///
    /// ```
    /// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
    /// assert_eq!(buffer.data(), "it works!\n");
    /// ```
    pub fn data(&self) -> String {
        self.data.to_string()
    }

    /// Inserts `data` into the buffer at the cursor position.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// assert_eq!(buffer.data(), "scribe");
    /// ```
    pub fn insert(&mut self, data: &str) {
        self.data.insert(data, &self.cursor);
    }
}

/// Creates a new empty buffer. The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::new();
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn new() -> Buffer {
    let data = gap_buffer::new(String::new());
    let cursor = Position{ line: 0, offset: 0 };

    Buffer{ data: data, path: None, cursor: cursor }
}

/// Creates a new buffer by reading the UTF-8 interpreted file contents of the specified path.
/// The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
/// assert_eq!(buffer.data(), "it works!\n");
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, Read) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);
    let cursor = Position{ line: 0, offset: 0 };

    // Create a new buffer using the loaded data, path, and other defaults.
    Ok(Buffer{ data: data, path: Some(path.clone()), cursor: cursor })
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use extra::json;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;

fn build_hex_mesh(&geom: &Geom) -> ~[Vec3<GLfloat>] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new() {
    let pos3d = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      vertex_data.push(pos3d + vertex);
      vertex_data.push(pos3d + next_vertex);
      vertex_data.push(pos3d + Vec3::zero());
    }
  }
  vertex_data
}

fn build_hex_tex_coord() -> ~[Vec2<GLfloat>] {
  let mut vertex_data = ~[];
  for _ in TileIterator::new() {
    for _ in range(0, 6) {
      vertex_data.push(Vec2{x: 0.0, y: 0.0});
      vertex_data.push(Vec2{x: 1.0, y: 0.0});
      vertex_data.push(Vec2{x: 0.5, y: 0.5});
    }
  }
  vertex_data
}

pub struct Visualizer {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: Option<glfw::Window>,
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
  unit_texture_id: GLuint,
  floor_texture_id: GLuint,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "Marauder",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

#[deriving(Decodable)]
struct Size2<T> {
  x: T,
  y: T,
}

fn read_win_size(config_path: &str) -> Vec2<int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<int> = Decodable::decode(&mut decoder);
  Vec2{x: size.x, y: size.y}
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: Some(win),
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
      unit_texture_id: 0,
      floor_texture_id: 0,
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_models();
    vis.init_textures();
    vis
  }

  fn init_textures(&mut self) {
    self.unit_texture_id = glh::load_texture(~"data/tank.png");
    self.floor_texture_id = glh::load_texture(~"data/floor.png");
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let position_attr = glh::get_attr(self.program, "position");
    gl::EnableVertexAttribArray(position_attr);
    glh::vertex_attrib_pointer(position_attr, 3);
    let vt_attr = glh::get_attr(self.program, "vt");
    gl::EnableVertexAttribArray(vt_attr);
    glh::vertex_attrib_pointer(vt_attr, 3);
    let map_vertex_data = build_hex_mesh(&self.geom);
    self.map_mesh.init(map_vertex_data);
    self.map_mesh.set_vt(build_hex_tex_coord());
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.init(unit_obj.build());
    self.unit_mesh.set_vt(unit_obj.build_tex_coord());
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
    gl::Enable(gl::DEPTH_TEST);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_unit_at(&self, pos: Vec2<i32>) {
    let world_pos = self.geom.map_pos_to_world_pos(pos);
    let m = glh::tr(self.camera.mat(), world_pos);
    glh::uniform_mat4f(self.mat_id, &m);
    self.unit_mesh.draw(self.program);
  }

  fn draw_units(&self) {
    gl::UseProgram(self.program);
    let basic_texture_loc = glh::get_uniform(self.program, "basic_texture!");
    gl::Uniform1ui(basic_texture_loc, 0);
    gl::ActiveTexture(gl::TEXTURE0);
    gl::BindTexture(gl::TEXTURE_2D, self.unit_texture_id);
    self.draw_unit_at(Vec2{x: 0, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 0});
    self.draw_unit_at(Vec2{x: 2, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 1});
    if !self.selected_tile_pos.is_none() {
      let p = self.selected_tile_pos.unwrap();
      self.draw_unit_at(p);
    }
  }

  fn draw_map(&self) {
    let basic_texture_loc = glh::get_uniform(self.program, "basic_texture!");
    gl::Uniform1ui(basic_texture_loc, 0);
    gl::ActiveTexture(gl::TEXTURE0);
    gl::BindTexture(gl::TEXTURE_2D, self.floor_texture_id);
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      glfw::KeyMinus => self.camera.zoom += 1.0,
      glfw::KeyEqual => self.camera.zoom -= 1.0,
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Vec2<f32>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += (self.mouse_pos.x - pos.x) / 2.0;
      self.camera.x_angle += (self.mouse_pos.y - pos.y) / 2.0;
    }
    self.mouse_pos = pos;
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent]{
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as f32, y: y as f32};
        self.handle_cursor_pos_event(p);
      },
      glfw::SizeEvent(w, h) => {
        gl::Viewport(0, 0, w, h);
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Visualizer: ...<commit_after>// See LICENSE file for copyright and license details.

use extra::json;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;

fn build_hex_mesh(&geom: &Geom) -> ~[Vec3<GLfloat>] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new() {
    let pos3d = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      vertex_data.push(pos3d + vertex);
      vertex_data.push(pos3d + next_vertex);
      vertex_data.push(pos3d + Vec3::zero());
    }
  }
  vertex_data
}

fn build_hex_tex_coord() -> ~[Vec2<GLfloat>] {
  let mut vertex_data = ~[];
  for _ in TileIterator::new() {
    for _ in range(0, 6) {
      vertex_data.push(Vec2{x: 0.0, y: 0.0});
      vertex_data.push(Vec2{x: 1.0, y: 0.0});
      vertex_data.push(Vec2{x: 0.5, y: 0.5});
    }
  }
  vertex_data
}

pub struct Visualizer {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: Option<glfw::Window>,
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
  unit_texture_id: GLuint,
  floor_texture_id: GLuint,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "Marauder",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

#[deriving(Decodable)]
struct Size2<T> {
  x: T,
  y: T,
}

fn read_win_size(config_path: &str) -> Vec2<int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<int> = Decodable::decode(&mut decoder);
  Vec2{x: size.x, y: size.y}
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: Some(win),
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
      unit_texture_id: 0,
      floor_texture_id: 0,
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_models();
    vis.init_textures();
    vis
  }

  fn init_textures(&mut self) {
    self.unit_texture_id = glh::load_texture(~"data/tank.png");
    self.floor_texture_id = glh::load_texture(~"data/floor.png");
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let position_attr = glh::get_attr(self.program, "position");
    gl::EnableVertexAttribArray(position_attr);
    glh::vertex_attrib_pointer(position_attr, 3);
    let vt_attr = glh::get_attr(self.program, "vt");
    gl::EnableVertexAttribArray(vt_attr);
    glh::vertex_attrib_pointer(vt_attr, 3);
    let map_vertex_data = build_hex_mesh(&self.geom);
    self.map_mesh.init(map_vertex_data);
    self.map_mesh.set_vt(build_hex_tex_coord());
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.init(unit_obj.build());
    self.unit_mesh.set_vt(unit_obj.build_tex_coord());
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
    gl::Enable(gl::DEPTH_TEST);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_unit_at(&self, pos: Vec2<i32>) {
    let world_pos = self.geom.map_pos_to_world_pos(pos);
    let m = glh::tr(self.camera.mat(), world_pos);
    glh::uniform_mat4f(self.mat_id, &m);
    self.unit_mesh.draw(self.program);
  }

  fn draw_units(&self) {
    gl::UseProgram(self.program);
    let basic_texture_loc = glh::get_uniform(self.program, "basic_texture");
    gl::Uniform1ui(basic_texture_loc, 0);
    gl::ActiveTexture(gl::TEXTURE0);
    gl::BindTexture(gl::TEXTURE_2D, self.unit_texture_id);
    self.draw_unit_at(Vec2{x: 0, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 0});
    self.draw_unit_at(Vec2{x: 2, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 1});
    if !self.selected_tile_pos.is_none() {
      let p = self.selected_tile_pos.unwrap();
      self.draw_unit_at(p);
    }
  }

  fn draw_map(&self) {
    let basic_texture_loc = glh::get_uniform(self.program, "basic_texture");
    gl::Uniform1ui(basic_texture_loc, 0);
    gl::ActiveTexture(gl::TEXTURE0);
    gl::BindTexture(gl::TEXTURE_2D, self.floor_texture_id);
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      glfw::KeyMinus => self.camera.zoom += 1.0,
      glfw::KeyEqual => self.camera.zoom -= 1.0,
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Vec2<f32>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += (self.mouse_pos.x - pos.x) / 2.0;
      self.camera.x_angle += (self.mouse_pos.y - pos.y) / 2.0;
    }
    self.mouse_pos = pos;
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent]{
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as f32, y: y as f32};
        self.handle_cursor_pos_event(p);
      },
      glfw::SizeEvent(w, h) => {
        gl::Viewport(0, 0, w, h);
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>use cudart::Memory;
use cublas::ffi;
use std::ptr;

pub struct Cublas {
    handle: ffi::Handle
}

impl Drop for Cublas {
    fn drop(&mut self) {
        unsafe { ffi::cublasDestroy_v2(self.handle) };
    }
}

impl Cublas {
    pub fn new() -> Result<Cublas, &'static str> {
        let mut handle: ffi::Handle = ptr::null_mut();
        match unsafe { ffi::cublasCreate_v2(&mut handle) } {
            ffi::Status::Success => Ok(Cublas { handle : handle }),
            e => Err(e.to_str())
        }
    }

    pub fn s_gemv(&self,
                  m: i32,
                  n: i32,
                  a: &Memory<f32>,
                  x: &Memory<f32>,
                  y: &mut Memory<f32>)
                  -> Result<(), &'static str> {
        match unsafe { ffi::cublasSgemv_v2(self.handle,
                                           ffi::Operation::T,
                                           m, n,
                                           *&[1.0f32].as_ptr() as *const ::libc::c_float,
                                           a.data as *const f32, m,
                                           x.data as *const f32, 1,
                                           *&[1.0f32].as_ptr() as *const ::libc::c_float,
                                           y.data as *const f32, 1) } {
            ffi::Status::Success => Ok(()),
            e => Err(e.to_str())
        }
    }
}

#[test]
fn test_s_gemv() {
    let x = Memory::<f32>::new(2).unwrap();
    let x_data = vec![3f32, 4f32];
    x.write(&x_data).unwrap();
    let mut y = Memory::<f32>::new(3).unwrap();
    let mut y_data = vec![0f32, 0f32, 0f32];
    y.write(&y_data).unwrap();
    let a = Memory::<f32>::new(2 * 3).unwrap();
    let a_data = vec![1f32, 0f32, 0f32, 1f32, 2f32, 3f32];
    a.write(&a_data).unwrap();
    let cublas = Cublas::new().unwrap();
    cublas.s_gemv(2, 3, &a, &x, &mut y).unwrap();
    y.read(&mut y_data).unwrap();
    assert_eq!(y_data[0], 3f32);
    assert_eq!(y_data[1], 4f32);
    assert_eq!(y_data[2], 18f32);
}
<commit_msg>bugfix: target vector must be ignored<commit_after>use cudart::Memory;
use cublas::ffi;
use std::ptr;

pub struct Cublas {
    handle: ffi::Handle
}

impl Drop for Cublas {
    fn drop(&mut self) {
        unsafe { ffi::cublasDestroy_v2(self.handle) };
    }
}

impl Cublas {
    pub fn new() -> Result<Cublas, &'static str> {
        let mut handle: ffi::Handle = ptr::null_mut();
        match unsafe { ffi::cublasCreate_v2(&mut handle) } {
            ffi::Status::Success => Ok(Cublas { handle : handle }),
            e => Err(e.to_str())
        }
    }

    pub fn s_gemv(&self,
                  m: i32,
                  n: i32,
                  a: &Memory<f32>,
                  x: &Memory<f32>,
                  y: &mut Memory<f32>)
                  -> Result<(), &'static str> {
        match unsafe { ffi::cublasSgemv_v2(self.handle,
                                           ffi::Operation::T,
                                           m, n,
                                           *&[1.0f32].as_ptr() as *const ::libc::c_float,
                                           a.data as *const f32, m,
                                           x.data as *const f32, 1,
                                           *&[0.0f32].as_ptr() as *const ::libc::c_float,
                                           y.data as *const f32, 1) } {
            ffi::Status::Success => Ok(()),
            e => Err(e.to_str())
        }
    }
}

#[test]
fn test_s_gemv() {
    let x = Memory::<f32>::new(2).unwrap();
    let x_data = vec![3f32, 4f32];
    x.write(&x_data).unwrap();
    let mut y = Memory::<f32>::new(3).unwrap();
    let mut y_data = vec![0f32, 0f32, 0f32];
    y.write(&y_data).unwrap();
    let a = Memory::<f32>::new(2 * 3).unwrap();
    let a_data = vec![1f32, 0f32, 0f32, 1f32, 2f32, 3f32];
    a.write(&a_data).unwrap();
    let cublas = Cublas::new().unwrap();
    cublas.s_gemv(2, 3, &a, &x, &mut y).unwrap();
    y.read(&mut y_data).unwrap();
    assert_eq!(y_data[0], 3f32);
    assert_eq!(y_data[1], 4f32);
    assert_eq!(y_data[2], 18f32);
}
<|endoftext|>


<commit_before>//! Information and types for Falcon's supported architectures.

use analysis::calling_convention::{CallingConvention, CallingConventionType};
use il;
use std::fmt::Debug;
use translator;

/// An architecture's endanness.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum Endian {
    Big,
    Little
}

/// Necessary functions for analysis over architectures.
pub trait Architecture: Debug + Send + Sync {
    /// Get the endianness of this architecture.
    fn endian(&self) -> Endian;
    /// Get this architecture's translator.
    fn translator(&self) -> Box<translator::Translator>;
    /// Get the _default_ calling convention for this architecture.
    fn calling_convention(&self) -> CallingConvention;
    /// Get the scalar used to represent the stack pointer by this
    /// architecture's translator.
    fn stack_pointer(&self) -> il::Scalar;
    /// Get the size of a natural word for this architecture in bits.
    fn word_size(&self) -> usize;
    /// Clone into a boxed `Architecture`
    fn box_clone(&self) -> Box<Architecture>;
}

/// The 64-bit X86 Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Amd64 {}

impl Amd64 {
    pub fn new() -> Amd64 { Amd64 {} }
}

impl Architecture for Amd64 {
    fn endian(&self) -> Endian { Endian::Little }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::x86::Amd64::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::Amd64SystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("rsp", 64) }
    fn word_size(&self) -> usize { 64 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit Mips Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Mips {}

impl Mips {
    pub fn new() -> Mips { Mips {} }
}

impl Architecture for Mips {
    fn endian(&self) -> Endian { Endian::Big }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::mips::Mips::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::MipsSystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("$sp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit Mipsel Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Mipsel {}

impl Mipsel {
    pub fn new() -> Mipsel { Mipsel {} }
}

impl Architecture for Mipsel {
    fn endian(&self) -> Endian { Endian::Big }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::mips::Mipsel::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::MipsSystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("$sp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit X86 Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct X86 {}

impl X86 {
    pub fn new() -> X86 { X86 {} }
}

impl Architecture for X86 {
    fn endian(&self) -> Endian { Endian::Little }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::x86::X86::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::Cdecl)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("esp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}<commit_msg>Architectures take a name field<commit_after>//! Information and types for Falcon's supported architectures.

use analysis::calling_convention::{CallingConvention, CallingConventionType};
use il;
use std::fmt::Debug;
use translator;

/// An architecture's endanness.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum Endian {
    Big,
    Little
}

/// Necessary functions for analysis over architectures.
pub trait Architecture: Debug + Send + Sync {
    /// Get the name of this architecture
    fn name(&self) -> &str;
    /// Get the endianness of this architecture.
    fn endian(&self) -> Endian;
    /// Get this architecture's translator.
    fn translator(&self) -> Box<translator::Translator>;
    /// Get the _default_ calling convention for this architecture.
    fn calling_convention(&self) -> CallingConvention;
    /// Get the scalar used to represent the stack pointer by this
    /// architecture's translator.
    fn stack_pointer(&self) -> il::Scalar;
    /// Get the size of a natural word for this architecture in bits.
    fn word_size(&self) -> usize;
    /// Clone into a boxed `Architecture`
    fn box_clone(&self) -> Box<Architecture>;
}

/// The 64-bit X86 Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Amd64 {}

impl Amd64 {
    pub fn new() -> Amd64 { Amd64 {} }
}

impl Architecture for Amd64 {
    fn name(&self) -> &str { &"amd64" }
    fn endian(&self) -> Endian { Endian::Little }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::x86::Amd64::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::Amd64SystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("rsp", 64) }
    fn word_size(&self) -> usize { 64 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit Mips Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Mips {}

impl Mips {
    pub fn new() -> Mips { Mips {} }
}

impl Architecture for Mips {
    fn name(&self) -> &str { &"mips" }
    fn endian(&self) -> Endian { Endian::Big }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::mips::Mips::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::MipsSystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("$sp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit Mipsel Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Mipsel {}

impl Mipsel {
    pub fn new() -> Mipsel { Mipsel {} }
}

impl Architecture for Mipsel {
    fn name(&self) -> &str { &"mipsel" }
    fn endian(&self) -> Endian { Endian::Big }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::mips::Mipsel::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::MipsSystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("$sp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit X86 Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct X86 {}

impl X86 {
    pub fn new() -> X86 { X86 {} }
}

impl Architecture for X86 {
    fn name(&self) -> &str { &"x86" }
    fn endian(&self) -> Endian { Endian::Little }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::x86::X86::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::Cdecl)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("esp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}<|endoftext|>