<commit_before>use irc;
use matrix;
use irc::protocol::{Command,Message};
use mio;
use mio::{EventLoop,Handler,Token,EventSet,PollOpt,Sender};
use std::thread;
use std::collections::HashMap;

const CLIENT: Token = Token(0);

#[derive(Debug)]
pub enum Event {
    EndPoll,
    Matrix(matrix::events::Event)
}

pub struct Bridge {
    client: irc::streams::Client,
    matrix: matrix::client::Client,
    rooms: HashMap<matrix::events::RoomID, Room>,
    seen_events: Vec<matrix::events::EventID>,
}

impl Handler for Bridge {
    type Timeout = ();
    type Message = Event;

    fn ready(&mut self, event_loop: &mut EventLoop<Bridge>, token: Token, _: EventSet) {
        match token {
            CLIENT =>
                self.handle_client(event_loop),
            _ => unreachable!()
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Bridge>, msg: Self::Message) {
        match msg {
            Event::EndPoll => {
                self.poll_matrix(event_loop.channel());
            },
            Event::Matrix(e) =>
                self.handle_matrix(e)
        };
    }
}

unsafe impl Sync for Bridge{}

struct Room {
    id: matrix::events::RoomID,
    canonical_alias: Option<String>,
    join_rules: Option<String>,
    members: Vec<matrix::events::UserID>,
    pending_events: Vec<matrix::events::RoomEvent>
}

impl Room {
    fn new(id: matrix::events::RoomID) -> Self {
        Room {
            id: id,
            canonical_alias: None,
            join_rules: None,
            members: vec![],
            pending_events: vec![]
        }
    }

    fn run_pending<F>(&mut self, mut callback: &mut F)
            where F: FnMut(irc::protocol::Message) {
        while let Some(evt) = self.pending_events.pop() {
            self.handle_with_alias(evt, callback);
        }
    }

    fn handle_with_alias<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: &mut F)
            where F: FnMut(irc::protocol::Message) {
        if self.canonical_alias != None {
            match evt {
                matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Join) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Join,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                    self.members.push(user);
                },
                matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Leave) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Part,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                    self.members.push(user);
                },
                matrix::events::RoomEvent::Membership(_, _) => (),
                matrix::events::RoomEvent::Message(user, text) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Privmsg,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: Some(text)
                    });
                },
                matrix::events::RoomEvent::Topic(user, topic) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Topic,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: Some(topic.clone())
                    });
                },
                matrix::events::RoomEvent::CanonicalAlias(_) => unreachable!(),
                _ => {
                    warn!("Unhandled event {:?}", evt)
                }
            }
        } else {
            self.pending_events.push(evt);
        }
    }

    fn handle_event<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: F)
            where F: FnMut(irc::protocol::Message) {
        match evt {
            matrix::events::RoomEvent::CanonicalAlias(name) => {
                let was_empty = self.canonical_alias == None;
                self.canonical_alias = Some(name.clone());
                if was_empty {
                    self.run_pending(&mut callback);
                }
            },
            matrix::events::RoomEvent::JoinRules(rules) =>
                self.join_rules = Some(rules.clone()),
            matrix::events::RoomEvent::Create => (),
            matrix::events::RoomEvent::Aliases(aliases) => {
                let is_empty = self.canonical_alias == None;
                if is_empty {
                    self.canonical_alias = Some(aliases[0].clone());
                    self.run_pending(&mut callback);
                }
            },
            matrix::events::RoomEvent::PowerLevels => (),
            matrix::events::RoomEvent::HistoryVisibility(_) => (),
            matrix::events::RoomEvent::Name(_, _) => (),
            matrix::events::RoomEvent::Avatar(_, _) => (),
            matrix::events::RoomEvent::Unknown(unknown_type, json) => {
                warn!("Unknown room event {}", unknown_type);
                trace!("raw event: {:?}", json);
            }
            _ => self.handle_with_alias(evt, &mut callback)
        };
    }
}

impl Bridge {
    pub fn room_from_matrix(&mut self, id: &matrix::events::RoomID) -> &mut Room {
        if !self.rooms.contains_key(id) {
            self.rooms.insert(id.clone(), Room::new(id.clone()));
        }
        match self.rooms.get_mut(id) {
            Some(room) => room,
            None => unreachable!()
        }
    }

    pub fn room_from_irc(&mut self, id: &String) -> &mut Room {
        let mut room_id: Option<matrix::events::RoomID> = None;
        for (_, r) in self.rooms.iter_mut() {
            if let Some(ref alias) = r.canonical_alias {
                if alias == id {
                    room_id = Some(r.id.clone())
                }
            }
        }
        self.room_from_matrix(&room_id.unwrap())
    }

    pub fn new(client: irc::streams::Client, url: &str) -> Self {
        Bridge {
            client: client,
            matrix: matrix::client::Client::new(url),
            rooms: HashMap::new(),
            seen_events: vec![]
        }
    }

    pub fn run(&mut self) {
        let mut events = EventLoop::new().unwrap();
        events.register(self.client.stream().get_ref(), CLIENT, EventSet::all(), PollOpt::edge()).unwrap();
        events.run(self).unwrap();
    }

    fn handle_matrix(&mut self, evt: matrix::events::Event) {
        let duplicate = match evt.id {
            Some(ref id) =>
                self.seen_events.contains(id),
            _ => false
        };
        if !duplicate {
            let mut messages: Vec<irc::protocol::Message> = vec![];
            {
                let append_msg = |msg: irc::protocol::Message| {
                    messages.push(msg);
                };
                match evt.data {
                    matrix::events::EventData::Room(room_id, room_event) => {
                        self.room_from_matrix(&room_id).handle_event(room_event, append_msg);
                    },
                    matrix::events::EventData::Typing(_) => (),
                    _ => warn!("Unhandled {}", evt.data.type_str())
                }
            }
            match evt.id {
                Some(id) =>
                    self.seen_events.push(id),
                None => ()
            };
            for ref msg in messages {
                self.client.send(msg).unwrap();
            }
        }
    }

    fn poll_matrix(&mut self, channel: mio::Sender<Event>) ->
        thread::JoinHandle<matrix::client::Result> {
        let poll = self.matrix.poll_async();
        thread::spawn(move|| {
            poll.send().and_then(|evts| {
                for evt in evts {
                    channel.send(Event::Matrix(evt)).unwrap();
                };
                channel.send(Event::EndPoll).unwrap();
                Ok(())
            })
        })
    }

    fn start_matrix(&mut self, channel: mio::Sender<Event>) ->
        matrix::client::Result {
        let mut events: Vec<matrix::events::Event> = vec![];
        self.matrix.sync().and_then(|events| {
            for e in events {
                self.handle_matrix(e);
            }
            self.poll_matrix(channel);
            Ok(())
        })
    }

    fn handle_client(&mut self, events: &mut EventLoop<Bridge>) {
        loop {
            match self.client.read_message() {
                None => return,
                Some(message) => {
                    match message.command {
                        Command::Pass => {
                            self.client.auth.set_password(message.args[0].clone())
                        }
                        Command::Nick => {
                            self.client.set_nickname(message.args[0].clone());
                        },
                        Command::User => {
                            self.client.auth.set_username(message.args[0].clone());
                            let auth = self.client.auth.consume();
                            match (auth.username, auth.password) {
                                (Some(username), Some(password)) => {
                                    self.matrix.login(username.trim(), password.trim())
                                        .and(self.start_matrix(events.channel()))
                                        .and_then(|_| {
                                            self.client.welcome(username.trim()).unwrap();
                                            debug!("Logged in a user");
                                            Ok(())
                                        }).expect("Could not login!");
                                },
                                _ => panic!("Username and/or password missing")
                            };
                        },
                        Command::Join => {
                            self.client.join(&message.args[0]).expect("Could not send JOIN");
                        },
                        Command::Ping => {
                            self.client.pong().expect("Could not send PONG");
                        },
                        Command::Quit => {
                            // FIXME: Logout of matrix and exit thread
                            return;
                        },
                        Command::Privmsg => {
                            let evt = {
                                let id = self.matrix.uid.clone().unwrap();
                                let room = self.room_from_irc(&message.args[0]);
                                matrix::events::EventData::Room(
                                    room.id.clone(),
                                    matrix::events::RoomEvent::Message(
                                        id, message.suffix.unwrap()))
                            };
                            self.seen_events.push(self.matrix.send(evt).expect("Could not send event"));
                        },
                        _ =>
                            warn!("unhandled {:?}", message)
                    }
                }
            }
        }
    }
}

<commit_msg>warning--<commit_after>use irc;
use matrix;
use irc::protocol::{Command,Message};
use mio;
use mio::{EventLoop,Handler,Token,EventSet,PollOpt,Sender};
use std::thread;
use std::collections::HashMap;

const CLIENT: Token = Token(0);

#[derive(Debug)]
pub enum Event {
    EndPoll,
    Matrix(matrix::events::Event)
}

pub struct Bridge {
    client: irc::streams::Client,
    matrix: matrix::client::Client,
    rooms: HashMap<matrix::events::RoomID, Room>,
    seen_events: Vec<matrix::events::EventID>,
}

impl Handler for Bridge {
    type Timeout = ();
    type Message = Event;

    fn ready(&mut self, event_loop: &mut EventLoop<Bridge>, token: Token, _: EventSet) {
        match token {
            CLIENT =>
                self.handle_client(event_loop),
            _ => unreachable!()
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Bridge>, msg: Self::Message) {
        match msg {
            Event::EndPoll => {
                self.poll_matrix(event_loop.channel());
            },
            Event::Matrix(e) =>
                self.handle_matrix(e)
        };
    }
}

unsafe impl Sync for Bridge{}

struct Room {
    id: matrix::events::RoomID,
    canonical_alias: Option<String>,
    join_rules: Option<String>,
    members: Vec<matrix::events::UserID>,
    pending_events: Vec<matrix::events::RoomEvent>
}

impl Room {
    fn new(id: matrix::events::RoomID) -> Self {
        Room {
            id: id,
            canonical_alias: None,
            join_rules: None,
            members: vec![],
            pending_events: vec![]
        }
    }

    fn run_pending<F>(&mut self, mut callback: &mut F)
            where F: FnMut(irc::protocol::Message) {
        while let Some(evt) = self.pending_events.pop() {
            self.handle_with_alias(evt, callback);
        }
    }

    fn handle_with_alias<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: &mut F)
            where F: FnMut(irc::protocol::Message) {
        if self.canonical_alias != None {
            match evt {
                matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Join) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Join,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                    self.members.push(user);
                },
                matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Leave) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Part,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                    self.members.push(user);
                },
                matrix::events::RoomEvent::Membership(_, _) => (),
                matrix::events::RoomEvent::Message(user, text) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Privmsg,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: Some(text)
                    });
                },
                matrix::events::RoomEvent::Topic(user, topic) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Topic,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: Some(topic.clone())
                    });
                },
                matrix::events::RoomEvent::CanonicalAlias(_) => unreachable!(),
                _ => {
                    warn!("Unhandled event {:?}", evt)
                }
            }
        } else {
            self.pending_events.push(evt);
        }
    }

    fn handle_event<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: F)
            where F: FnMut(irc::protocol::Message) {
        match evt {
            matrix::events::RoomEvent::CanonicalAlias(name) => {
                let was_empty = self.canonical_alias == None;
                self.canonical_alias = Some(name.clone());
                if was_empty {
                    self.run_pending(&mut callback);
                }
            },
            matrix::events::RoomEvent::JoinRules(rules) =>
                self.join_rules = Some(rules.clone()),
            matrix::events::RoomEvent::Create => (),
            matrix::events::RoomEvent::Aliases(aliases) => {
                let is_empty = self.canonical_alias == None;
                if is_empty {
                    self.canonical_alias = Some(aliases[0].clone());
                    self.run_pending(&mut callback);
                }
            },
            matrix::events::RoomEvent::PowerLevels => (),
            matrix::events::RoomEvent::HistoryVisibility(_) => (),
            matrix::events::RoomEvent::Name(_, _) => (),
            matrix::events::RoomEvent::Avatar(_, _) => (),
            matrix::events::RoomEvent::Unknown(unknown_type, json) => {
                warn!("Unknown room event {}", unknown_type);
                trace!("raw event: {:?}", json);
            }
            _ => self.handle_with_alias(evt, &mut callback)
        };
    }
}

impl Bridge {
    pub fn room_from_matrix(&mut self, id: &matrix::events::RoomID) -> &mut Room {
        if !self.rooms.contains_key(id) {
            self.rooms.insert(id.clone(), Room::new(id.clone()));
        }
        match self.rooms.get_mut(id) {
            Some(room) => room,
            None => unreachable!()
        }
    }

    pub fn room_from_irc(&mut self, id: &String) -> &mut Room {
        let mut room_id: Option<matrix::events::RoomID> = None;
        for (_, r) in self.rooms.iter_mut() {
            if let Some(ref alias) = r.canonical_alias {
                if alias == id {
                    room_id = Some(r.id.clone())
                }
            }
        }
        self.room_from_matrix(&room_id.unwrap())
    }

    pub fn new(client: irc::streams::Client, url: &str) -> Self {
        Bridge {
            client: client,
            matrix: matrix::client::Client::new(url),
            rooms: HashMap::new(),
            seen_events: vec![]
        }
    }

    pub fn run(&mut self) {
        let mut events = EventLoop::new().unwrap();
        events.register(self.client.stream().get_ref(), CLIENT, EventSet::all(), PollOpt::edge()).unwrap();
        events.run(self).unwrap();
    }

    fn handle_matrix(&mut self, evt: matrix::events::Event) {
        let duplicate = match evt.id {
            Some(ref id) =>
                self.seen_events.contains(id),
            _ => false
        };
        if !duplicate {
            let mut messages: Vec<irc::protocol::Message> = vec![];
            {
                let append_msg = |msg: irc::protocol::Message| {
                    messages.push(msg);
                };
                match evt.data {
                    matrix::events::EventData::Room(room_id, room_event) => {
                        self.room_from_matrix(&room_id).handle_event(room_event, append_msg);
                    },
                    matrix::events::EventData::Typing(_) => (),
                    _ => warn!("Unhandled {}", evt.data.type_str())
                }
            }
            match evt.id {
                Some(id) =>
                    self.seen_events.push(id),
                None => ()
            };
            for ref msg in messages {
                self.client.send(msg).unwrap();
            }
        }
    }

    fn poll_matrix(&mut self, channel: mio::Sender<Event>) ->
        thread::JoinHandle<matrix::client::Result> {
        let poll = self.matrix.poll_async();
        thread::spawn(move|| {
            poll.send().and_then(|evts| {
                for evt in evts {
                    channel.send(Event::Matrix(evt)).unwrap();
                };
                channel.send(Event::EndPoll).unwrap();
                Ok(())
            })
        })
    }

    fn start_matrix(&mut self, channel: mio::Sender<Event>) ->
        matrix::client::Result {
        self.matrix.sync().and_then(|events| {
            for e in events {
                self.handle_matrix(e);
            }
            self.poll_matrix(channel);
            Ok(())
        })
    }

    fn handle_client(&mut self, events: &mut EventLoop<Bridge>) {
        loop {
            match self.client.read_message() {
                None => return,
                Some(message) => {
                    match message.command {
                        Command::Pass => {
                            self.client.auth.set_password(message.args[0].clone())
                        }
                        Command::Nick => {
                            self.client.set_nickname(message.args[0].clone());
                        },
                        Command::User => {
                            self.client.auth.set_username(message.args[0].clone());
                            let auth = self.client.auth.consume();
                            match (auth.username, auth.password) {
                                (Some(username), Some(password)) => {
                                    self.matrix.login(username.trim(), password.trim())
                                        .and(self.start_matrix(events.channel()))
                                        .and_then(|_| {
                                            self.client.welcome(username.trim()).unwrap();
                                            debug!("Logged in a user");
                                            Ok(())
                                        }).expect("Could not login!");
                                },
                                _ => panic!("Username and/or password missing")
                            };
                        },
                        Command::Join => {
                            self.client.join(&message.args[0]).expect("Could not send JOIN");
                        },
                        Command::Ping => {
                            self.client.pong().expect("Could not send PONG");
                        },
                        Command::Quit => {
                            // FIXME: Logout of matrix and exit thread
                            return;
                        },
                        Command::Privmsg => {
                            let evt = {
                                let id = self.matrix.uid.clone().unwrap();
                                let room = self.room_from_irc(&message.args[0]);
                                matrix::events::EventData::Room(
                                    room.id.clone(),
                                    matrix::events::RoomEvent::Message(
                                        id, message.suffix.unwrap()))
                            };
                            self.seen_events.push(self.matrix.send(evt).expect("Could not send event"));
                        },
                        _ =>
                            warn!("unhandled {:?}", message)
                    }
                }
            }
        }
    }
}

<|endoftext|>


<commit_before>extern crate serialize;
use std::io::File;
use std::str;
use serialize::json;

#[deriving(Decodable, Encodable)]
pub struct Coordinate {
  x: f64,
  y: f64,
  z: f64
}

#[deriving(Decodable, Encodable)]
pub struct TestStruct  {
  coordinates: Vec<Coordinate>
}

fn main() {
  let bytes = File::open(&Path::new("./1.json".as_slice())).read_to_end().unwrap();
  let text = str::from_utf8(bytes.as_slice()).unwrap();
  let jobj: TestStruct = json::decode(text).unwrap();

  let len = jobj.coordinates.len() as f64;
  let mut x = 0_f64;
  let mut y = 0_f64;
  let mut z = 0_f64;

  for coord in jobj.coordinates.iter() {
    x += coord.x;
    y += coord.y;
    z += coord.z;
  }

  println!("{}", x / len);
  println!("{}", y / len);
  println!("{}", z / len);
}
<commit_msg>remove old file<commit_after><|endoftext|>


<commit_before>use cgmath::prelude::*;

use math::*;
use ray::Ray;

#[derive(Clone, Copy)]
pub struct Camera {
    position: Point,
    direction: Vector,
    fov: f32,

    // Order: top left, top right, bottom left.
    screen_corners: (Point, Point, Point),
}

impl Camera {
    pub fn new(position: Point, direction: Vector, fov: f32) -> Camera {
        let center = position + direction * (1.0 / (0.5 * fov).tan());
        let left = direction.cross(Vector::unit_y()).normalize();
        let up = direction.cross(left).normalize();

        Camera {
            position: position,
            direction: direction,
            fov: fov,

            screen_corners: (center + up + left, center + up - left, center - up + left),
        }
    }

    pub fn position(&self) -> Point {
        self.position
    }

    pub fn screen_corners(&self) -> (Point, Point, Point) {
        self.screen_corners
    }

    /// Given coordinates on the screen plane, create a ray passing
    /// through those coordinates from the camera's origin.
    pub fn primary_ray(&self, (u, v): (f32, f32)) -> Vector {
        let (top_left, top_right, bottom_left) = self.screen_corners();
        let basis_x = top_right - top_left;
        let basis_y = bottom_left - top_left;
        let direction = (top_left + u * basis_x + v * basis_y - self.position()).normalize();

        Ray::new(self.position, direction)
    }
}
<commit_msg>Fix incorrect signature of `Camera::primary_ray`<commit_after>use cgmath::prelude::*;

use math::*;
use ray::Ray;

#[derive(Clone, Copy)]
pub struct Camera {
    position: Point,
    direction: Vector,
    fov: f32,

    // Order: top left, top right, bottom left.
    screen_corners: (Point, Point, Point),
}

impl Camera {
    pub fn new(position: Point, direction: Vector, fov: f32) -> Camera {
        let center = position + direction * (1.0 / (0.5 * fov).tan());
        let left = direction.cross(Vector::unit_y()).normalize();
        let up = direction.cross(left).normalize();

        Camera {
            position: position,
            direction: direction,
            fov: fov,

            screen_corners: (center + up + left, center + up - left, center - up + left),
        }
    }

    pub fn position(&self) -> Point {
        self.position
    }

    pub fn screen_corners(&self) -> (Point, Point, Point) {
        self.screen_corners
    }

    /// Given coordinates on the screen plane, create a ray passing
    /// through those coordinates from the camera's origin.
    pub fn primary_ray(&self, (u, v): (f32, f32)) -> Ray {
        let (top_left, top_right, bottom_left) = self.screen_corners();
        let basis_x = top_right - top_left;
        let basis_y = bottom_left - top_left;
        let direction = (top_left + u * basis_x + v * basis_y - self.position()).normalize();

        Ray::new(self.position, direction)
    }
}
<|endoftext|>


<commit_before>//! A camera object for ggez.
//! Currently ggez has no actual global camera state to use,
//! so this really just does the coordinate transforms for you.
//!
//! Basically it translates ggez's integer-valued coordinate
//! system with the origin at the top-left and Y increasing
//! downward, to a float-valued coordinate system with the
//! origin at the center of the screen and Y increasing upward.
//!
//! Because that makes sense, darn it.

use ggez;
use ggez::GameResult;
use ggez::graphics;
use ggez::graphics::Drawable;
use na;
use super::{Point2, Vector2};

// Hmm.  Could, instead, use a 2d transformation
// matrix, or create one of such.
pub struct Camera {
    screen_width: u32,
    screen_height: u32,
    view_width: f64,
    view_height: f64,
    view_center: Vector2,
}

impl Camera {
    pub fn new(screen_width: u32, screen_height: u32, view_width: f64, view_height: f64) -> Self {
        Camera {
            screen_width: screen_width,
            screen_height: screen_height,
            view_width: view_width,
            view_height: view_height,
            view_center: na::zero(),
        }
    }

    pub fn move_by(&mut self, by: Vector2) {
        self.view_center += by;
    }

    pub fn move_to(&mut self, to: Vector2) {
        self.view_center = to;
    }

    /// Translates a point in world-space to a point in
    /// screen-space.
    ///
    /// Does not do any clipping or anything, since it does
    /// not know how large the thing that might be drawn is;
    /// that's not its job.
    pub fn world_to_screen_coords(&self, from: Vector2) -> (i32, i32) {
        let sw = self.screen_width as f64;
        let sh = self.screen_height as f64;
        let pixels_per_unit_x = sw / self.view_width;
        let pixels_per_unit_y = sh / self.view_height;
        let scale_vec = Vector2::new(pixels_per_unit_x, pixels_per_unit_y);

        let view_offset = from - self.view_center;
        let view_scale = view_offset * scale_vec;

        let x = view_scale.x + sw / 2.0;
        let y = sh - (view_scale.y + sh / 2.0);
        (x as i32, y as i32)

        // let x = from.x + sw / 2.0;
        // let y = sh - (from.y + sh / 2.0);
        // (x as i32, y as i32)
    }

    pub fn screen_to_world_coords(&self, from: (i32, i32)) -> Vector2 {
        let (sx, sy) = from;
        na::zero()
    }

    pub fn location(&self) -> Vector2 {
        self.view_center
    }

    fn calculate_dest_rect(&self, location: Vector2, dst_size: (u32, u32)) -> graphics::Rect {
        let (sx, sy) = self.world_to_screen_coords(location);
        let (sw, sh) = dst_size;
        graphics::Rect::new(sx, sy, sw, sh)
    }
}

pub trait CameraDraw
    where Self: graphics::Drawable
{
    fn draw_ex_camera(&mut self,
                      camera: &Camera,
                      location: Vector2,
                      context: &mut ggez::Context,
                      src: Option<graphics::Rect>,
                      dst_size: (u32, u32),
                      angle: f64,
                      center: Option<graphics::Point>,
                      flip_horizontal: bool,
                      flip_vertical: bool)
                      -> GameResult<()> {
        let dest_rect = camera.calculate_dest_rect(location, dst_size);
        self.draw_ex(context,
                     src,
                     Some(dest_rect),
                     angle,
                     center,
                     flip_horizontal,
                     flip_vertical)
    }

    fn draw_camera(&mut self,
                   camera: &Camera,
                   location: Vector2,
                   context: &mut ggez::Context,
                   src: Option<graphics::Rect>,
                   dst_size: (u32, u32))
                   -> GameResult<()> {

        let dest_rect = camera.calculate_dest_rect(location, dst_size);
        self.draw(context, src, Some(dest_rect))
    }
}

impl<T> CameraDraw for T where T: graphics::Drawable {}
<commit_msg>Camera now uses all shiny vector code<commit_after>//! A camera object for ggez.
//! Currently ggez has no actual global camera state to use,
//! so this really just does the coordinate transforms for you.
//!
//! Basically it translates ggez's integer-valued coordinate
//! system with the origin at the top-left and Y increasing
//! downward, to a float-valued coordinate system with the
//! origin at the center of the screen and Y increasing upward.
//!
//! Because that makes sense, darn it.

use ggez;
use ggez::GameResult;
use ggez::graphics;
use ggez::graphics::Drawable;
use na;
use super::{Point2, Vector2};

// Hmm.  Could, instead, use a 2d transformation
// matrix, or create one of such.
pub struct Camera {
    screen_size: Vector2,
    view_size: Vector2,
    view_center: Vector2,
}

impl Camera {
    pub fn new(screen_width: u32, screen_height: u32, view_width: f64, view_height: f64) -> Self {
        let screen_size = Vector2::new(screen_width as f64, screen_height as f64);
        let view_size = Vector2::new(view_width, view_height);
        Camera {
            screen_size: screen_size,
            view_size: view_size,
            view_center: na::zero(),
        }
    }

    pub fn move_by(&mut self, by: Vector2) {
        self.view_center += by;
    }

    pub fn move_to(&mut self, to: Vector2) {
        self.view_center = to;
    }

    /// Translates a point in world-space to a point in
    /// screen-space.
    ///
    /// Does not do any clipping or anything, since it does
    /// not know how large the thing that might be drawn is;
    /// that's not its job.
    pub fn world_to_screen_coords(&self, from: Vector2) -> (i32, i32) {
        let pixels_per_unit = self.screen_size / self.view_size;
        let view_offset = from - self.view_center;
        let view_scale = view_offset * pixels_per_unit;

        let x = view_scale.x + self.screen_size.x / 2.0;
        let y = self.screen_size.y - (view_scale.y + self.screen_size.y / 2.0);
        (x as i32, y as i32)
    }

    pub fn screen_to_world_coords(&self, from: (i32, i32)) -> Vector2 {
        let (sx, sy) = from;
        na::zero()
    }

    pub fn location(&self) -> Vector2 {
        self.view_center
    }

    fn calculate_dest_rect(&self, location: Vector2, dst_size: (u32, u32)) -> graphics::Rect {
        let (sx, sy) = self.world_to_screen_coords(location);
        let (sw, sh) = dst_size;
        graphics::Rect::new(sx, sy, sw, sh)
    }
}

pub trait CameraDraw
    where Self: graphics::Drawable
{
    fn draw_ex_camera(&mut self,
                      camera: &Camera,
                      location: Vector2,
                      context: &mut ggez::Context,
                      src: Option<graphics::Rect>,
                      dst_size: (u32, u32),
                      angle: f64,
                      center: Option<graphics::Point>,
                      flip_horizontal: bool,
                      flip_vertical: bool)
                      -> GameResult<()> {
        let dest_rect = camera.calculate_dest_rect(location, dst_size);
        self.draw_ex(context,
                     src,
                     Some(dest_rect),
                     angle,
                     center,
                     flip_horizontal,
                     flip_vertical)
    }

    fn draw_camera(&mut self,
                   camera: &Camera,
                   location: Vector2,
                   context: &mut ggez::Context,
                   src: Option<graphics::Rect>,
                   dst_size: (u32, u32))
                   -> GameResult<()> {

        let dest_rect = camera.calculate_dest_rect(location, dst_size);
        self.draw(context, src, Some(dest_rect))
    }
}

impl<T> CameraDraw for T where T: graphics::Drawable {}
<|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 http://mozilla.org/MPL/2.0/.

extern crate cc3200_sys;

use core;
use core::result::Result;

use self::cc3200_sys::{board_init, GPIO_IF_LedConfigure, GPIO_IF_LedOn, GPIO_IF_LedOff,
                       MAP_UtilsDelay, I2C_IF_Open, I2C_IF_Close, I2C_IF_Write, I2C_IF_Read,
                       I2C_IF_ReadFrom};
use self::cc3200_sys::simplelink::*;
use logger::SimpleLogger;
use rtc::RTC;

#[allow(non_camel_case_types, dead_code)]
pub enum LedName {
    NO_LED_IND = 0,
    MCU_SENDING_DATA_IND,
    MCU_ASSOCIATED_IND, // Device associated to an AP
    MCU_IP_ALLOC_IND, // Device acquired an IP
    MCU_SERVER_INIT_IND, // Device connected to remote server
    MCU_CLIENT_CONNECTED_IND, // Any client connects to device
    MCU_ON_IND, // Device SLHost invoked successfully
    MCU_EXECUTE_SUCCESS_IND, // Task executed sucessfully
    MCU_EXECUTE_FAIL_IND, // Task execution failed
    MCU_RED_LED_GPIO, // GP09 for LED RED as per LP 3.0
    MCU_ORANGE_LED_GPIO, // GP10 for LED ORANGE as per LP 3.0
    MCU_GREEN_LED_GPIO, // GP11 for LED GREEN as per LP 3.0
    MCU_ALL_LED_IND,
}

#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub enum LedEnum {
    NO_LED = 0x0,
    LED1 = 0x1, // RED LED D7/GP9/Pin64
    LED2 = 0x2, // ORANGE LED D6/GP10/Pin1
    LED3 = 0x4, // GREEN LED D5/GP11/Pin2
}

pub struct Board { }

impl Board {
    pub fn init() {
        unsafe {
            board_init();
        }
        SimpleLogger::init().unwrap();
        RTC::init();
    }

    pub fn test() {
        unsafe {
            cc3200_sys::board_test();
        }
    }

    pub fn led_configure(leds: &[LedEnum]) {
        let mut val = LedEnum::NO_LED as u8;
        for led in leds {
            val |= *led as u8;
        }
        unsafe {
            GPIO_IF_LedConfigure(val);
        }
    }

    pub fn led_off(led: LedName) {
        unsafe {
            GPIO_IF_LedOff(led as i8);
        }
    }

    pub fn led_on(led: LedName) {
        unsafe {
            GPIO_IF_LedOn(led as i8);
        }
    }

    pub fn start_scheduler() {
        unsafe {
            cc3200_sys::vTaskStartScheduler();
        }
    }

    pub fn disable_irq() {
        unsafe {
            asm!("cpsid i");
        }
    }

    pub fn reset() {
        unsafe {
            cc3200_sys::reset();
        }
    }
}

pub struct Console { }

impl Console {
    pub fn clear_term() {
        unsafe {
            cc3200_sys::ClearTerm();
        }
    }

    pub fn init_term() {
        unsafe {
            cc3200_sys::InitTerm();
        }
    }

    pub fn message(msg: &str) {
        for char in msg.chars() {
            // Lossy converstion from unicode to ASCII
            let ascii_char = {
                if char > '\x7f' { '?' } else { char }
            };
            unsafe {
                cc3200_sys::console_putchar(ascii_char as i8);
            }
        }
    }
}

impl core::fmt::Write for Console {
    fn write_str(&mut self, s: &str) -> core::fmt::Result {
        Console::message(s);
        Ok(())
    }
}

pub enum I2COpenMode {
    MasterModeStd = 0,
    MasterModeFst = 1,
}

static mut I2C_IS_OPEN: bool = false;
static I2C_SUCCESS: i32 = 0;

#[derive(Clone, Copy)]
pub struct I2C { }

impl I2C {
    pub fn open(mode: I2COpenMode) -> Option<Self> {
        unsafe {
            // Only allow one instance to be created in a given open mode.
            if I2C_IS_OPEN || I2C_IF_Open(mode as u32) != I2C_SUCCESS {
                return None;
            }
            I2C_IS_OPEN = true;
        }
        return Some(I2C {});
    }

    pub fn close(&self) {
        unsafe {
            // TODO: decide what to do if we never called I2C_IF_Open
            I2C_IF_Close();
            I2C_IS_OPEN = false;
        }
    }

    pub fn write(&self, addr: u8, data: &[u8], stop: u8) -> Result<(), ()> {
        if data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_Write(addr, data.as_ptr() as *mut u8, data.len() as u8, stop) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read(&self, addr: u8, data: &mut [u8]) -> Result<(), ()> {
        if data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_Read(addr, data.as_ptr() as *mut u8, data.len() as u8) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read_from_with_length(&self,
                                 addr: u8,
                                 wr_data: &[u8],
                                 rd_data: &mut [u8],
                                 rd_len: u8)
                                 -> Result<(), ()> {
        if wr_data.len() > 255 || rd_data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_ReadFrom(addr,
                               wr_data.as_ptr() as *mut u8,
                               wr_data.len() as u8,
                               rd_data.as_ptr() as *mut u8,
                               rd_len) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read_from(&self, addr: u8, wr_data: &[u8], rd_data: &mut [u8]) -> Result<(), ()> {
        let len = rd_data.len() as u8;
        self.read_from_with_length(addr, wr_data, rd_data, len)
    }
}

pub struct Update { }

impl Update {

    /// Sets the application to test mode
    pub fn test() -> bool {
        let res = unsafe {
            sl_extlib_FlcTest(FLC_TEST_RESET_MCU |
                              FLC_TEST_RESET_MCU_WITH_APP)
        };
        Update::reset_is_required(res)
    }

    /// Returns true if the application runs in testing mode, false otherwise
    pub fn is_testing() -> bool {
        let res = unsafe {
            sl_extlib_FlcIsPendingCommit()
        };
        res != 0
    }

    /// Commits all changes, moving the application state from 'testing' to 'stable'
    pub fn commit() -> bool {
        let res = unsafe {
            sl_extlib_FlcCommit(FLC_COMMITED)
        };
        Update::reset_is_required(res)
    }

    /// Aborts the update
    pub fn abort() -> bool {
        let res = unsafe {
            sl_extlib_FlcCommit(FLC_NOT_COMMITED)
        };
        Update::reset_is_required(res)
    }

    fn reset_is_required(flags: i32) -> bool {
        (flags & (FLC_TEST_RESET_MCU | FLC_TEST_RESET_NWP)) != 0
    }
}

pub struct Utils { }

impl Utils {
    pub fn delay(loops: u32) {
        unsafe {
            MAP_UtilsDelay(loops);
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn abort() {
    unimplemented!();
}
<commit_msg>Support reading and writing boot-info file<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 http://mozilla.org/MPL/2.0/.

extern crate cc3200_sys;

use core;
use core::result::Result;

use self::cc3200_sys::{board_init, GPIO_IF_LedConfigure, GPIO_IF_LedOn, GPIO_IF_LedOff,
                       MAP_UtilsDelay, I2C_IF_Open, I2C_IF_Close, I2C_IF_Write, I2C_IF_Read,
                       I2C_IF_ReadFrom};
use self::cc3200_sys::simplelink::*;
use logger::SimpleLogger;
use rtc::RTC;
use io::{File, Read, Write};

#[allow(non_camel_case_types, dead_code)]
pub enum LedName {
    NO_LED_IND = 0,
    MCU_SENDING_DATA_IND,
    MCU_ASSOCIATED_IND, // Device associated to an AP
    MCU_IP_ALLOC_IND, // Device acquired an IP
    MCU_SERVER_INIT_IND, // Device connected to remote server
    MCU_CLIENT_CONNECTED_IND, // Any client connects to device
    MCU_ON_IND, // Device SLHost invoked successfully
    MCU_EXECUTE_SUCCESS_IND, // Task executed sucessfully
    MCU_EXECUTE_FAIL_IND, // Task execution failed
    MCU_RED_LED_GPIO, // GP09 for LED RED as per LP 3.0
    MCU_ORANGE_LED_GPIO, // GP10 for LED ORANGE as per LP 3.0
    MCU_GREEN_LED_GPIO, // GP11 for LED GREEN as per LP 3.0
    MCU_ALL_LED_IND,
}

#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub enum LedEnum {
    NO_LED = 0x0,
    LED1 = 0x1, // RED LED D7/GP9/Pin64
    LED2 = 0x2, // ORANGE LED D6/GP10/Pin1
    LED3 = 0x4, // GREEN LED D5/GP11/Pin2
}

pub struct Board { }

impl Board {
    pub fn init() {
        unsafe {
            board_init();
        }
        SimpleLogger::init().unwrap();
        RTC::init();
    }

    pub fn test() {
        unsafe {
            cc3200_sys::board_test();
        }
    }

    pub fn led_configure(leds: &[LedEnum]) {
        let mut val = LedEnum::NO_LED as u8;
        for led in leds {
            val |= *led as u8;
        }
        unsafe {
            GPIO_IF_LedConfigure(val);
        }
    }

    pub fn led_off(led: LedName) {
        unsafe {
            GPIO_IF_LedOff(led as i8);
        }
    }

    pub fn led_on(led: LedName) {
        unsafe {
            GPIO_IF_LedOn(led as i8);
        }
    }

    pub fn start_scheduler() {
        unsafe {
            cc3200_sys::vTaskStartScheduler();
        }
    }

    pub fn disable_irq() {
        unsafe {
            asm!("cpsid i");
        }
    }

    pub fn reset() {
        unsafe {
            cc3200_sys::reset();
        }
    }
}

pub struct Console { }

impl Console {
    pub fn clear_term() {
        unsafe {
            cc3200_sys::ClearTerm();
        }
    }

    pub fn init_term() {
        unsafe {
            cc3200_sys::InitTerm();
        }
    }

    pub fn message(msg: &str) {
        for char in msg.chars() {
            // Lossy converstion from unicode to ASCII
            let ascii_char = {
                if char > '\x7f' { '?' } else { char }
            };
            unsafe {
                cc3200_sys::console_putchar(ascii_char as i8);
            }
        }
    }
}

impl core::fmt::Write for Console {
    fn write_str(&mut self, s: &str) -> core::fmt::Result {
        Console::message(s);
        Ok(())
    }
}

pub enum I2COpenMode {
    MasterModeStd = 0,
    MasterModeFst = 1,
}

static mut I2C_IS_OPEN: bool = false;
static I2C_SUCCESS: i32 = 0;

#[derive(Clone, Copy)]
pub struct I2C { }

impl I2C {
    pub fn open(mode: I2COpenMode) -> Option<Self> {
        unsafe {
            // Only allow one instance to be created in a given open mode.
            if I2C_IS_OPEN || I2C_IF_Open(mode as u32) != I2C_SUCCESS {
                return None;
            }
            I2C_IS_OPEN = true;
        }
        return Some(I2C {});
    }

    pub fn close(&self) {
        unsafe {
            // TODO: decide what to do if we never called I2C_IF_Open
            I2C_IF_Close();
            I2C_IS_OPEN = false;
        }
    }

    pub fn write(&self, addr: u8, data: &[u8], stop: u8) -> Result<(), ()> {
        if data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_Write(addr, data.as_ptr() as *mut u8, data.len() as u8, stop) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read(&self, addr: u8, data: &mut [u8]) -> Result<(), ()> {
        if data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_Read(addr, data.as_ptr() as *mut u8, data.len() as u8) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read_from_with_length(&self,
                                 addr: u8,
                                 wr_data: &[u8],
                                 rd_data: &mut [u8],
                                 rd_len: u8)
                                 -> Result<(), ()> {
        if wr_data.len() > 255 || rd_data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_ReadFrom(addr,
                               wr_data.as_ptr() as *mut u8,
                               wr_data.len() as u8,
                               rd_data.as_ptr() as *mut u8,
                               rd_len) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read_from(&self, addr: u8, wr_data: &[u8], rd_data: &mut [u8]) -> Result<(), ()> {
        let len = rd_data.len() as u8;
        self.read_from_with_length(addr, wr_data, rd_data, len)
    }
}

//
// Image updates
//

#[derive(Copy, Clone)]
pub enum ImageStatus {
    TESTING,
    TESTREADY,
    NOTEST
}

impl ImageStatus {
    pub fn from_u32(value: u32) -> Result<ImageStatus, ()> {
        let image_status = match value {
            IMG_STATUS_TESTING   => ImageStatus::TESTING,
            IMG_STATUS_TESTREADY => ImageStatus::TESTREADY,
            IMG_STATUS_NOTEST    => ImageStatus::NOTEST,
            value => {
                println!("unknwon image status {}", value);
                return Err(());
            }
        };
        Ok(image_status)
    }
    pub fn to_u32(image_status: ImageStatus) -> Result<u32, ()> {
        let value = match image_status {
            ImageStatus::NOTEST    => IMG_STATUS_NOTEST,
            ImageStatus::TESTREADY => IMG_STATUS_TESTREADY,
            ImageStatus::TESTING   => IMG_STATUS_TESTING
        };
        Ok(value)
    }
}

pub struct BootInfo {
    pub active_image: u8,
    pub image_status: ImageStatus,
}

impl BootInfo {

    /// Create a BootInfo structure
    pub fn new(active_image: u8, image_status: ImageStatus) -> BootInfo {
        BootInfo { active_image: active_image,
                   image_status: image_status }
    }

    /// Create a BootInfo structure the represents the factory reset
    pub fn factory_reset() -> BootInfo {
        BootInfo::new(0, ImageStatus::NOTEST)
    }
}

pub struct Update { }

impl Update {

    /// Sets the application to test mode
    pub fn test() -> bool {
        let res = unsafe {
            sl_extlib_FlcTest(FLC_TEST_RESET_MCU |
                              FLC_TEST_RESET_MCU_WITH_APP)
        };
        Update::reset_is_required(res)
    }

    /// Returns true if the application runs in testing mode, false otherwise
    pub fn is_testing() -> bool {
        let res = unsafe {
            sl_extlib_FlcIsPendingCommit()
        };
        res != 0
    }

    /// Commits all changes, moving the application state from 'testing' to 'stable'
    pub fn commit() -> bool {
        let res = unsafe {
            sl_extlib_FlcCommit(FLC_COMMITED)
        };
        Update::reset_is_required(res)
    }

    /// Aborts the update
    pub fn abort() -> bool {
        let res = unsafe {
            sl_extlib_FlcCommit(FLC_NOT_COMMITED)
        };
        Update::reset_is_required(res)
    }

    /// Reads or creates the device's boot-info structure
    pub fn get_boot_info() -> Result<BootInfo, ()> {
        let boot_info = match Update::read_boot_info() {
            Ok(boot_info) => boot_info,
            Err(_) => {
                let boot_info = BootInfo::factory_reset();
                match Update::write_boot_info(&boot_info) {
                    Ok(_)  => { },
                    Err(_) => { return Err(()); }
                };
                boot_info
            }
        };
        Ok(boot_info)
    }

    fn reset_is_required(flags: i32) -> bool {
        (flags & (FLC_TEST_RESET_MCU | FLC_TEST_RESET_NWP)) != 0
    }

    fn encode_boot_info(boot_info: &BootInfo) -> Result<[u8; 8], ()> {
        let active_image = boot_info.active_image;
        let image_status = ImageStatus::to_u32(boot_info.image_status)?;
        let mut buf: [u8; 8] = [0; 8];
        buf[0] = active_image;
        buf[4] = 0xff & (image_status) as u8;
        buf[5] = 0xff & (image_status >> 8) as u8;
        buf[6] = 0xff & (image_status >> 16) as u8;
        buf[7] = 0xff & (image_status >> 24) as u8;
        Ok(buf)
    }

    fn decode_boot_info(buf: [u8; 8]) -> Result<BootInfo, ()> {
        let active_image = buf[0];
        let image_status = ((buf[4] as u32)) |
                           ((buf[5] as u32) << 8) |
                           ((buf[6] as u32) << 16) |
                           ((buf[7] as u32) << 24);
        Ok(BootInfo::new(active_image, ImageStatus::from_u32(image_status)?))
    }

    fn write_boot_info(boot_info: &BootInfo) -> Result<(), ()> {

        let buf = Update::encode_boot_info(boot_info)?;

        let mut file = match File::create(IMG_BOOT_INFO, 8, false) {
            Ok(file) => file,
            Err(_)   => { return Err(()); }
        };
        match file.write(&buf[..]) {
            Ok(buflen) => {
                if buflen < buf.len() {
                    return Err(());
                }
            },
            Err(_) => { return Err(()); }
        }
        Ok(())
    }

    fn read_boot_info() -> Result<BootInfo, ()> {
        let mut buf: [u8; 8] = [0; 8];
        let mut file = match File::open(IMG_BOOT_INFO) {
            Ok(file) => file,
            Err(_)   => return Err(())
        };
        match file.read(&mut buf) {
            Ok(buflen) => {
                if buflen != buf.len() {
                    return Err(());
                }
            },
            Err(_) => { return Err(()); }
        };
        Update::decode_boot_info(buf)
    }
}

pub struct Utils { }

impl Utils {
    pub fn delay(loops: u32) {
        unsafe {
            MAP_UtilsDelay(loops);
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn abort() {
    unimplemented!();
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

use {WireError, tokio_proto as proto};
use bincode::serde::DeserializeError;
use futures::{self, Async, BoxFuture, Future};
use futures::stream::Empty;
use std::fmt;
use std::io;
use tokio_service::Service;
use util::Never;

/// A client `Service` that writes and reads bytes.
///
/// Typically, this would be combined with a serialization pre-processing step
/// and a deserialization post-processing step.
pub struct Client<Req, Resp, E> {
    inner: proto::Client<Req, WireResponse<Resp, E>, Empty<Never, io::Error>, io::Error>,
}

type WireResponse<Resp, E> = Result<Result<Resp, WireError<E>>, DeserializeError>;
type ResponseFuture<Resp, E> = futures::Map<BoxFuture<WireResponse<Resp, E>, io::Error>,
                                            fn(WireResponse<Resp, E>) -> Result<Resp, ::Error<E>>>;

impl<Req, Resp, E> Service for Client<Req, Resp, E>
    where Req: Send + 'static,
          Resp: Send + 'static,
          E: Send + 'static
{
    type Request = Req;
    type Response = Result<Resp, ::Error<E>>;
    type Error = io::Error;
    type Future = ResponseFuture<Resp, E>;

    fn poll_ready(&self) -> Async<()> {
        self.inner.poll_ready()
    }

    fn call(&self, request: Self::Request) -> Self::Future {
        self.inner
            .call(proto::Message::WithoutBody(request))
            .map(Self::map_err)
    }
}

impl<Req, Resp, E> Client<Req, Resp, E> {
    fn map_err(resp: WireResponse<Resp, E>) -> Result<Resp, ::Error<E>> {
        resp.map(|r| r.map_err(::Error::from))
            .map_err(::Error::ClientDeserialize)
            .and_then(|r| r)
    }
}

impl<Req, Resp, E> fmt::Debug for Client<Req, Resp, E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Client {{ .. }}")
    }
}

/// Exposes a trait for connecting asynchronously to servers.
pub mod future {
    use REMOTE;
    use futures::{self, Async, Future};
    use framed::Framed;
    use serde::{Deserialize, Serialize};
    use std::cell::RefCell;
    use std::io;
    use std::net::SocketAddr;
    use super::Client;
    use tokio_core::net::TcpStream;
    use tokio_proto::multiplex;

    /// Types that can connect to a server asynchronously.
    pub trait Connect: Sized {
        /// The type of the future returned when calling connect.
        type Fut: Future<Item = Self, Error = io::Error>;

        /// Connects to a server located at the given address.
        fn connect(addr: &SocketAddr) -> Self::Fut;
    }

    /// A future that resolves to a `Client` or an `io::Error`.
    pub struct ClientFuture<Req, Resp, E> {
        inner: futures::Oneshot<io::Result<Client<Req, Resp, E>>>,
    }

    impl<Req, Resp, E> Future for ClientFuture<Req, Resp, E> {
        type Item = Client<Req, Resp, E>;
        type Error = io::Error;

        fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
            match self.inner.poll().unwrap() {
                Async::Ready(Ok(client)) => Ok(Async::Ready(client)),
                Async::Ready(Err(err)) => Err(err),
                Async::NotReady => Ok(Async::NotReady),
            }
        }
    }

    impl<Req, Resp, E> Connect for Client<Req, Resp, E>
        where Req: Serialize + Send + 'static,
              Resp: Deserialize + Send + 'static,
              E: Deserialize + Send + 'static
    {
        type Fut = ClientFuture<Req, Resp, E>;

        /// Starts an event loop on a thread and registers a new client
        /// connected to the given address.
        fn connect(addr: &SocketAddr) -> ClientFuture<Req, Resp, E> {
            let addr = *addr;
            let (tx, rx) = futures::oneshot();
            REMOTE.spawn(move |handle| {
                let handle2 = handle.clone();
                TcpStream::connect(&addr, handle)
                    .and_then(move |tcp| {
                        let tcp = RefCell::new(Some(tcp));
                        let c =
                            multiplex::connect(move || {
                                                   Ok(Framed::new(tcp.borrow_mut().take().unwrap()))
                                               },
                                               &handle2);
                        Ok(Client { inner: c })
                    })
                    .then(|client| Ok(tx.complete(client)))
            });
            ClientFuture { inner: rx }
        }
    }
}

/// Exposes a trait for connecting synchronously to servers.
pub mod sync {
    use futures::Future;
    use serde::{Deserialize, Serialize};
    use std::io;
    use std::net::ToSocketAddrs;
    use super::Client;

    /// Types that can connect to a server synchronously.
    pub trait Connect: Sized {
        /// Connects to a server located at the given address.
        fn connect<A>(addr: A) -> Result<Self, io::Error> where A: ToSocketAddrs;
    }

    impl<Req, Resp, E> Connect for Client<Req, Resp, E>
        where Req: Serialize + Send + 'static,
              Resp: Deserialize + Send + 'static,
              E: Deserialize + Send + 'static
    {
        fn connect<A>(addr: A) -> Result<Self, io::Error>
            where A: ToSocketAddrs
        {
            let addr = if let Some(a) = try!(addr.to_socket_addrs()).next() {
                a
            } else {
                return Err(io::Error::new(io::ErrorKind::AddrNotAvailable,
                                          "`ToSocketAddrs::to_socket_addrs` returned an empty \
                                           iterator."));
            };
            <Self as super::future::Connect>::connect(&addr).wait()
        }
    }
}
<commit_msg>Complete ClientFuture on error.<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

use {WireError, tokio_proto as proto};
use bincode::serde::DeserializeError;
use futures::{self, Async, BoxFuture, Future};
use futures::stream::Empty;
use std::fmt;
use std::io;
use tokio_service::Service;
use util::Never;

/// A client `Service` that writes and reads bytes.
///
/// Typically, this would be combined with a serialization pre-processing step
/// and a deserialization post-processing step.
pub struct Client<Req, Resp, E> {
    inner: proto::Client<Req, WireResponse<Resp, E>, Empty<Never, io::Error>, io::Error>,
}

type WireResponse<Resp, E> = Result<Result<Resp, WireError<E>>, DeserializeError>;
type ResponseFuture<Resp, E> = futures::Map<BoxFuture<WireResponse<Resp, E>, io::Error>,
                                            fn(WireResponse<Resp, E>) -> Result<Resp, ::Error<E>>>;

impl<Req, Resp, E> Service for Client<Req, Resp, E>
    where Req: Send + 'static,
          Resp: Send + 'static,
          E: Send + 'static
{
    type Request = Req;
    type Response = Result<Resp, ::Error<E>>;
    type Error = io::Error;
    type Future = ResponseFuture<Resp, E>;

    fn poll_ready(&self) -> Async<()> {
        self.inner.poll_ready()
    }

    fn call(&self, request: Self::Request) -> Self::Future {
        self.inner
            .call(proto::Message::WithoutBody(request))
            .map(Self::map_err)
    }
}

impl<Req, Resp, E> Client<Req, Resp, E> {
    fn map_err(resp: WireResponse<Resp, E>) -> Result<Resp, ::Error<E>> {
        resp.map(|r| r.map_err(::Error::from))
            .map_err(::Error::ClientDeserialize)
            .and_then(|r| r)
    }
}

impl<Req, Resp, E> fmt::Debug for Client<Req, Resp, E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Client {{ .. }}")
    }
}

/// Exposes a trait for connecting asynchronously to servers.
pub mod future {
    use REMOTE;
    use futures::{self, Async, Future};
    use framed::Framed;
    use serde::{Deserialize, Serialize};
    use std::cell::RefCell;
    use std::io;
    use std::net::SocketAddr;
    use super::Client;
    use tokio_core::net::TcpStream;
    use tokio_proto::multiplex;

    /// Types that can connect to a server asynchronously.
    pub trait Connect: Sized {
        /// The type of the future returned when calling connect.
        type Fut: Future<Item = Self, Error = io::Error>;

        /// Connects to a server located at the given address.
        fn connect(addr: &SocketAddr) -> Self::Fut;
    }

    /// A future that resolves to a `Client` or an `io::Error`.
    pub struct ClientFuture<Req, Resp, E> {
        inner: futures::Oneshot<io::Result<Client<Req, Resp, E>>>,
    }

    impl<Req, Resp, E> Future for ClientFuture<Req, Resp, E> {
        type Item = Client<Req, Resp, E>;
        type Error = io::Error;

        fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
            match self.inner.poll().unwrap() {
                Async::Ready(Ok(client)) => Ok(Async::Ready(client)),
                Async::Ready(Err(err)) => Err(err),
                Async::NotReady => Ok(Async::NotReady),
            }
        }
    }

    impl<Req, Resp, E> Connect for Client<Req, Resp, E>
        where Req: Serialize + Send + 'static,
              Resp: Deserialize + Send + 'static,
              E: Deserialize + Send + 'static
    {
        type Fut = ClientFuture<Req, Resp, E>;

        /// Starts an event loop on a thread and registers a new client
        /// connected to the given address.
        fn connect(addr: &SocketAddr) -> ClientFuture<Req, Resp, E> {
            let addr = *addr;
            let (tx, rx) = futures::oneshot();
            REMOTE.spawn(move |handle| {
                let handle2 = handle.clone();
                TcpStream::connect(&addr, handle)
                    .then(move |tcp| {
                        match tcp {
                            Ok(tcp) => {
                                let tcp = RefCell::new(Some(tcp));
                                let c =
                                    multiplex::connect(move || {
                                                           Ok(Framed::new(tcp.borrow_mut().take().unwrap()))
                                                       },
                                                       &handle2);
                                tx.complete(Ok(Client { inner: c }));
                            }
                            Err(e) => {
                                tx.complete(Err(e));
                            }
                        }
                        Ok(())
                    })
            });
            ClientFuture { inner: rx }
        }
    }
}

/// Exposes a trait for connecting synchronously to servers.
pub mod sync {
    use futures::Future;
    use serde::{Deserialize, Serialize};
    use std::io;
    use std::net::ToSocketAddrs;
    use super::Client;

    /// Types that can connect to a server synchronously.
    pub trait Connect: Sized {
        /// Connects to a server located at the given address.
        fn connect<A>(addr: A) -> Result<Self, io::Error> where A: ToSocketAddrs;
    }

    impl<Req, Resp, E> Connect for Client<Req, Resp, E>
        where Req: Serialize + Send + 'static,
              Resp: Deserialize + Send + 'static,
              E: Deserialize + Send + 'static
    {
        fn connect<A>(addr: A) -> Result<Self, io::Error>
            where A: ToSocketAddrs
        {
            let addr = if let Some(a) = try!(addr.to_socket_addrs()).next() {
                a
            } else {
                return Err(io::Error::new(io::ErrorKind::AddrNotAvailable,
                                          "`ToSocketAddrs::to_socket_addrs` returned an empty \
                                           iterator."));
            };
            <Self as super::future::Connect>::connect(&addr).wait()
        }
    }
}
<|endoftext|>


<commit_before>use docopt::Docopt;
use docopt::Error as DocoptError;
use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter};
use std::fs::File;
use std::io::Error as IoError;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use toml;

use gobjects;
use version::Version;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WorkMode {
    Normal,     //generate widgets etc.
    Sys,        //generate -sys with ffi
}

impl Default for WorkMode {
    fn default() -> WorkMode { WorkMode::Normal }
}

impl FromStr for WorkMode {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(WorkMode::Normal),
            "sys" => Ok(WorkMode::Sys),
            _ => Err("Wrong work mode".into())
        }
    }
}

#[derive(Debug)]
pub enum Error {
    CommandLine(DocoptError),
    Io(IoError, PathBuf),
    Toml(String, PathBuf),
    Options(String, PathBuf),
}

impl StdError for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        match *self {
            CommandLine(ref e) => e.description(),
            Io(ref e, _) => e.description(),
            Toml(ref s, _) => s,
            Options(ref s, _) => s,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use self::Error::*;
        match *self {
            CommandLine(ref err) => err.fmt(f),
            Io(ref err, ref filename) => {
                try!(write!(f, "Failed to read config \"{}\": ", filename.display()));
                err.fmt(f)
            }
            Toml(ref err, ref filename) => {
                write!(f, "\"{}\": {}", filename.display(), err)
            }
            Options(ref err, ref filename) => {
                write!(f, "\"{}\": {}", filename.display(), err)
            }
        }
    }
}

impl<'a> From<DocoptError> for Error {
    fn from(e: DocoptError) -> Error {
        Error::CommandLine(e)
    }
}

impl<P: AsRef<Path>> From<(IoError, P)> for Error {
    fn from(e: (IoError, P)) -> Error {
        Error::Io(e.0, e.1.as_ref().into())
    }
}

impl<'a, P: AsRef<Path>> From<(&'a str, P)> for Error {
    fn from(e: (&'a str, P)) -> Error {
        Error::Options(e.0.into(), e.1.as_ref().into())
    }
}

impl<P: AsRef<Path>> From<(String, P)> for Error {
    fn from(e: (String, P)) -> Error {
        Error::Options(e.0, e.1.as_ref().into())
    }
}

trait TomlHelper where Self: Sized {
    fn lookup_str<'a, P: AsRef<Path>>(&'a self, option: &'a str, err: &str, config_file: P) -> Result<&'a str, Error>;
    fn as_result_str<'a, P: AsRef<Path>>(&'a self, option: &'a str, config_file: P) -> Result<&'a str, Error>;
    fn as_result_slice<'a, P: AsRef<Path>>(&'a self, option: &'a str, config_file: P) -> Result<&'a [Self], Error>;
}

impl TomlHelper for toml::Value {
    fn lookup_str<'a, P: AsRef<Path>>(&'a self, option: &'a str, err: &str, config_file: P) -> Result<&'a str, Error> {
        let value = try!(self.lookup(option).ok_or((err, &config_file)));
        value.as_result_str(option, config_file)
    }
    fn as_result_str<'a, P: AsRef<Path>>(&'a self, option: &'a str, config_file: P) -> Result<&'a str, Error> {
        self.as_str()
            .ok_or(Error::Options(format!("Invalid `{}` value, expected a string, found {}",
                                          option, self.type_str()),
                                  config_file.as_ref().into()))
    }
    fn as_result_slice<'a, P: AsRef<Path>>(&'a self, option: &'a str, config_file: P) -> Result<&'a [Self], Error> {
        self.as_slice()
            .ok_or(Error::Options(format!("Invalid `{}` value, expected a array, found {}",
                                          option, self.type_str()),
                                  config_file.as_ref().into()))
    }
}

static USAGE: &'static str = "
Usage: gir [options] [<library> <version>]
       gir --help

Options:
    -h, --help          Show this message.
    -c CONFIG           Config file path (default: Gir.toml)
    -d GIRSPATH         Directory for girs
    -m MODE             Work mode: normal or sys
    -o PATH             Target path
    -b, --make_backup   Make backup before generating
";

#[derive(Debug)]
pub struct Config {
    pub work_mode: WorkMode,
    pub girs_dir: PathBuf,
    pub library_name: String,
    pub library_version: String,
    pub target_path: PathBuf,
    pub external_libraries: Vec<String>,
    pub objects: gobjects::GObjects,
    pub min_cfg_version: Version,
    pub make_backup: bool,
}

impl Config {
    pub fn new() -> Result<Config, Error> {
        let args = try!(Docopt::new(USAGE)
            .and_then(|dopt| dopt.parse()));

        let config_file: PathBuf = match args.get_str("-c") {
            "" => "Gir.toml",
            a => a,
        }.into();

        //TODO: add check file existence when stable std::fs::PathExt
        let toml = try!(read_toml(&config_file));

        let work_mode_str = match args.get_str("-m") {
            "" => try!(toml.lookup_str("options.work_mode", "No options.work_mode in config", &config_file)),
            a => a,
        };
        let work_mode = WorkMode::from_str(work_mode_str)
            .unwrap_or_else(|e| panic!(e));

        let girs_dir: PathBuf = match args.get_str("-d") {
            "" => try!(toml.lookup_str("options.girs_dir", "No options.girs_dir in config", &config_file)),
            a => a
        }.into();

        let (library_name, library_version) =
            match (args.get_str("<library>"), args.get_str("<version>")) {
            ("", "") => (
                try!(toml.lookup_str("options.library", "No options.library in config", &config_file)),
                try!(toml.lookup_str("options.version", "No options.version in config", &config_file))
            ),
            ("", _) | (_, "") => try!(Err(("Library and version can not be specified separately", &config_file))),
            (a, b) => (a, b)
        };

        let target_path: PathBuf = match args.get_str("-o") {
            "" => try!(toml.lookup_str("options.target_path", "No target path specified", &config_file)),
            a => a
        }.into();

        let mut objects = toml.lookup("object").map(|t| gobjects::parse_toml(t))
            .unwrap_or_else(|| Default::default());
        gobjects::parse_status_shorthands(&mut objects, &toml);

        let external_libraries = match toml.lookup("options.external_libraries") {
            Some(a) => {
                try!(a.as_result_slice("options.external_libraries", &config_file))
                    .iter().filter_map(|v| v.as_str().map(String::from))
                    .collect()
            }
            None => Vec::new(),
        };

        let min_cfg_version = match toml.lookup("options.min_cfg_version") {
            Some(v) => {
                try!(
                    try!(v.as_result_str("options.min_cfg_version", &config_file))
                        .parse().map_err(|e: String| (e, config_file)))
            }
            None => Default::default(),
        };

        let make_backup = args.get_bool("-b");

        Ok(Config {
            work_mode: work_mode,
            girs_dir: girs_dir,
            library_name: library_name.into(),
            library_version: library_version.into(),
            target_path: target_path,
            external_libraries: external_libraries,
            objects: objects,
            min_cfg_version: min_cfg_version,
            make_backup: make_backup,
        })
    }

    pub fn library_full_name(&self) -> String {
        format!("{}-{}", self.library_name, self.library_version)
    }
}

fn read_toml<P: AsRef<Path>>(filename: P) -> Result<toml::Value, Error> {
    let mut input = String::new();
    try!(File::open(&filename)
         .and_then(|mut f| f.read_to_string(&mut input))
         .map_err(|e| (e, &filename)));

    let mut parser = toml::Parser::new(&input);
    match parser.parse() {
        Some(toml) => Ok(toml::Value::Table(toml)),
        None => {
            let err = &parser.errors[parser.errors.len() - 1];
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            let s = format!("{}:{}-{}:{} error: {}", loline, locol, hiline, hicol, err.desc);
            Err(Error::Toml(s, filename.as_ref().into()))
        }
    }
}
<commit_msg>Clarify conversion to PathBuf<commit_after>use docopt::Docopt;
use docopt::Error as DocoptError;
use std::error::Error as StdError;
use std::ffi::OsStr;
use std::fmt::{self, Display, Formatter};
use std::fs::File;
use std::io::Error as IoError;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use toml;

use gobjects;
use version::Version;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WorkMode {
    Normal,     //generate widgets etc.
    Sys,        //generate -sys with ffi
}

impl Default for WorkMode {
    fn default() -> WorkMode { WorkMode::Normal }
}

impl FromStr for WorkMode {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(WorkMode::Normal),
            "sys" => Ok(WorkMode::Sys),
            _ => Err("Wrong work mode".into())
        }
    }
}

#[derive(Debug)]
pub enum Error {
    CommandLine(DocoptError),
    Io(IoError, PathBuf),
    Toml(String, PathBuf),
    Options(String, PathBuf),
}

impl StdError for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        match *self {
            CommandLine(ref e) => e.description(),
            Io(ref e, _) => e.description(),
            Toml(ref s, _) => s,
            Options(ref s, _) => s,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use self::Error::*;
        match *self {
            CommandLine(ref err) => err.fmt(f),
            Io(ref err, ref filename) => {
                try!(write!(f, "Failed to read config \"{}\": ", filename.display()));
                err.fmt(f)
            }
            Toml(ref err, ref filename) => {
                write!(f, "\"{}\": {}", filename.display(), err)
            }
            Options(ref err, ref filename) => {
                write!(f, "\"{}\": {}", filename.display(), err)
            }
        }
    }
}

impl<'a> From<DocoptError> for Error {
    fn from(e: DocoptError) -> Error {
        Error::CommandLine(e)
    }
}

impl<P: AsRef<OsStr>> From<(IoError, P)> for Error {
    fn from(e: (IoError, P)) -> Error {
        Error::Io(e.0, PathBuf::from(&e.1))
    }
}

impl<'a, P: AsRef<OsStr>> From<(&'a str, P)> for Error {
    fn from(e: (&'a str, P)) -> Error {
        Error::Options(e.0.into(), PathBuf::from(&e.1))
    }
}

impl<P: AsRef<OsStr>> From<(String, P)> for Error {
    fn from(e: (String, P)) -> Error {
        Error::Options(e.0, PathBuf::from(&e.1))
    }
}

trait TomlHelper where Self: Sized {
    fn lookup_str<'a, P: AsRef<OsStr>>(&'a self, option: &'a str, err: &str, config_file: P) -> Result<&'a str, Error>;
    fn as_result_str<'a, P: AsRef<OsStr>>(&'a self, option: &'a str, config_file: P) -> Result<&'a str, Error>;
    fn as_result_slice<'a, P: AsRef<OsStr>>(&'a self, option: &'a str, config_file: P) -> Result<&'a [Self], Error>;
}

impl TomlHelper for toml::Value {
    fn lookup_str<'a, P: AsRef<OsStr>>(&'a self, option: &'a str, err: &str, config_file: P) -> Result<&'a str, Error> {
        let value = try!(self.lookup(option).ok_or((err, &config_file)));
        value.as_result_str(option, config_file)
    }
    fn as_result_str<'a, P: AsRef<OsStr>>(&'a self, option: &'a str, config_file: P) -> Result<&'a str, Error> {
        self.as_str()
            .ok_or(Error::Options(format!("Invalid `{}` value, expected a string, found {}",
                                          option, self.type_str()),
                                  PathBuf::from(&config_file)))
    }
    fn as_result_slice<'a, P: AsRef<OsStr>>(&'a self, option: &'a str, config_file: P) -> Result<&'a [Self], Error> {
        self.as_slice()
            .ok_or(Error::Options(format!("Invalid `{}` value, expected a array, found {}",
                                          option, self.type_str()),
                                  PathBuf::from(&config_file)))
    }
}

static USAGE: &'static str = "
Usage: gir [options] [<library> <version>]
       gir --help

Options:
    -h, --help          Show this message.
    -c CONFIG           Config file path (default: Gir.toml)
    -d GIRSPATH         Directory for girs
    -m MODE             Work mode: normal or sys
    -o PATH             Target path
    -b, --make_backup   Make backup before generating
";

#[derive(Debug)]
pub struct Config {
    pub work_mode: WorkMode,
    pub girs_dir: PathBuf,
    pub library_name: String,
    pub library_version: String,
    pub target_path: PathBuf,
    pub external_libraries: Vec<String>,
    pub objects: gobjects::GObjects,
    pub min_cfg_version: Version,
    pub make_backup: bool,
}

impl Config {
    pub fn new() -> Result<Config, Error> {
        let args = try!(Docopt::new(USAGE)
            .and_then(|dopt| dopt.parse()));

        let config_file: PathBuf = match args.get_str("-c") {
            "" => "Gir.toml",
            a => a,
        }.into();

        //TODO: add check file existence when stable std::fs::PathExt
        let toml = try!(read_toml(&config_file));

        let work_mode_str = match args.get_str("-m") {
            "" => try!(toml.lookup_str("options.work_mode", "No options.work_mode in config", &config_file)),
            a => a,
        };
        let work_mode = WorkMode::from_str(work_mode_str)
            .unwrap_or_else(|e| panic!(e));

        let girs_dir: PathBuf = match args.get_str("-d") {
            "" => try!(toml.lookup_str("options.girs_dir", "No options.girs_dir in config", &config_file)),
            a => a
        }.into();

        let (library_name, library_version) =
            match (args.get_str("<library>"), args.get_str("<version>")) {
            ("", "") => (
                try!(toml.lookup_str("options.library", "No options.library in config", &config_file)),
                try!(toml.lookup_str("options.version", "No options.version in config", &config_file))
            ),
            ("", _) | (_, "") => try!(Err(("Library and version can not be specified separately", &config_file))),
            (a, b) => (a, b)
        };

        let target_path: PathBuf = match args.get_str("-o") {
            "" => try!(toml.lookup_str("options.target_path", "No target path specified", &config_file)),
            a => a
        }.into();

        let mut objects = toml.lookup("object").map(|t| gobjects::parse_toml(t))
            .unwrap_or_else(|| Default::default());
        gobjects::parse_status_shorthands(&mut objects, &toml);

        let external_libraries = match toml.lookup("options.external_libraries") {
            Some(a) => {
                try!(a.as_result_slice("options.external_libraries", &config_file))
                    .iter().filter_map(|v| v.as_str().map(String::from))
                    .collect()
            }
            None => Vec::new(),
        };

        let min_cfg_version = match toml.lookup("options.min_cfg_version") {
            Some(v) => {
                try!(
                    try!(v.as_result_str("options.min_cfg_version", &config_file))
                        .parse().map_err(|e: String| (e, config_file)))
            }
            None => Default::default(),
        };

        let make_backup = args.get_bool("-b");

        Ok(Config {
            work_mode: work_mode,
            girs_dir: girs_dir,
            library_name: library_name.into(),
            library_version: library_version.into(),
            target_path: target_path,
            external_libraries: external_libraries,
            objects: objects,
            min_cfg_version: min_cfg_version,
            make_backup: make_backup,
        })
    }

    pub fn library_full_name(&self) -> String {
        format!("{}-{}", self.library_name, self.library_version)
    }
}

fn read_toml<P: AsRef<OsStr> + AsRef<Path>>(filename: P) -> Result<toml::Value, Error> {
    let mut input = String::new();
    try!(File::open(&filename)
         .and_then(|mut f| f.read_to_string(&mut input))
         .map_err(|e| (e, &filename)));

    let mut parser = toml::Parser::new(&input);
    match parser.parse() {
        Some(toml) => Ok(toml::Value::Table(toml)),
        None => {
            let err = &parser.errors[parser.errors.len() - 1];
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            let s = format!("{}:{}-{}:{} error: {}", loline, locol, hiline, hicol, err.desc);
            Err(Error::Toml(s, PathBuf::from(&filename)))
        }
    }
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::prelude::*;
use getopts::Options;
use toml::{self, Value};
use calx::backend::CanvasMagnify;
use calx::vorud::{Vorud, FromVorud};
use super::app_data_path;

thread_local!(pub static _CONFIG: Config = Default::default());

#[derive(Copy, Clone, Debug)]
pub struct Config {
    /// The player will move to the side when bumping against a wall.
    pub wall_sliding: bool,
    /// How to scale the graphics when making the window larger.
    pub magnify_mode: CanvasMagnify,
    /// Fixed world random number generator seed.
    pub rng_seed: Option<u32>,
    /// Start in fullscreen mode
    pub fullscreen: bool,
    /// Show FPS counter
    pub show_fps: bool,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            wall_sliding: true,
            magnify_mode: CanvasMagnify::PixelPerfect,
            rng_seed: None,
            fullscreen: false,
            show_fps: false,
        }
    }
}

impl Config {
    /// Parse command line options and apply them to the config object. Return
    /// an error containing a usage string if the parsing fails.
    ///
    /// Returning a string with Ok indicates that the string should be printed
    /// and the program should then exit.
    pub fn parse_args<T: Iterator<Item = String>>(&mut self,
                                                  args: T)
                                                  -> Result<Option<String>, String> {
        let mut opts = Options::new();
        opts.optflag("",
                     "no-wall-sliding",
                     "Don't move diagonally along obstacles when walking into them");
        opts.optflag("h", "help", "Display this message");
        opts.optflag("V", "version", "Print version info and exit");
        opts.optopt("",
                    "magnify-mode",
                    "How to filter magnified graphics. MODE = pixel | nearest | smooth",
                    "MODE");
        opts.optopt("", "seed", "World generation seed", "VORUD");
        opts.optflag("", "fullscreen", "Run in fullscreen mode");
        opts.optflag("", "fps", "Show FPS counter");

        let args: Vec<String> = args.collect();

        let parse = match opts.parse(&args[1..]) {
            Ok(m) => m,
            Err(f) => {
                return Err(usage_error(f.to_string(), &opts));
            }
        };

        if parse.opt_present("help") {
            return Ok(Some(format!("{}", opts.usage("Usage: magog [options]"))));
        }

        if parse.opt_present("version") {
            return Ok(Some(format!("Magog v{}", ::version())));
        }

        if parse.opt_present("no-wall-sliding") {
            self.wall_sliding = false;
        }

        if parse.opt_present("fullscreen") {
            self.fullscreen = true;
        }

        if parse.opt_present("fps") {
            self.show_fps = true;
        }

        if let Some(x) = parse.opt_str("magnify-mode") {
            match &x[..] {
                "pixel" => {
                    self.magnify_mode = CanvasMagnify::PixelPerfect;
                }
                "nearest" => {
                    self.magnify_mode = CanvasMagnify::Nearest;
                }
                "smooth" => {
                    self.magnify_mode = CanvasMagnify::Smooth;
                }
                err => {
                    return Err(usage_error(format!("Unknown magnify mode '{}'", err), &opts));
                }
            }
        }

        if let Some(seed) = parse.opt_str("seed") {
            // XXX: Could this be written to use the try! macro?
            let err = Err(usage_error(format!("Invalid seed value '{}'", seed), &opts));
            if let Ok(vorud) = Vorud::new(seed.clone()) {
                if let Ok(val) = FromVorud::from_vorud(&vorud) {
                    self.rng_seed = Some(val);
                } else {
                    return err;
                }
            } else {
                return err;
            }
        }

        return Ok(None);

        fn usage_error(msg: String, opts: &Options) -> String {
            format!("{}\n{}",
                    msg,
                    opts.usage("Usage:\n    magog [options]"))
        }
    }

    pub fn file_path(&self) -> PathBuf {
        let mut ret = app_data_path();
        ret.push("config.toml");
        ret
    }

    /// Output the default config file.
    pub fn default_file(&self) -> String {
        // TODO: Make this data-driven, have option metadata that specifies
        // the help string and what to print out.
        format!(r#"# Move diagonally along obstacles when walking into them
wall-sliding = true

# How to filter magnified graphics. pixel | nearest | smooth
magnify-mode = "pixel"

# Start the game in fullscreen instead of windowed mode
fullscreen = false

# Display FPS counter
fps = false
"#)
    }

    pub fn load<P: AsRef<Path>>(&mut self, path: P) -> Result<(), String> {
        // TODO: Error handling.

        // TODO: This should be data-driven somehow from a common config
        // metadata object instead of relying on the error-prone retyped
        // schema in the match segment.
        let mut file = File::open(path).unwrap();
        let mut toml = String::new();
        file.read_to_string(&mut toml).unwrap();

        let mut parser = toml::Parser::new(&toml);

        let settings = parser.parse();

        if settings.is_none() {
            let mut err = String::new();
            for e in parser.errors.iter() {
                err.push_str(&format!("{}", e));
            }
            return Err(err);
        }

        let settings = settings.unwrap();

        // TODO: Error message instead of silent no-op if the type of the
        // value isn't what we expect.
        if let Some(&Value::Boolean(b)) = settings.get("wall-sliding") {
            self.wall_sliding = b;
        }

        if let Some(&Value::String(ref mag)) = settings.get("magnify-mode") {
            match &mag[..] {
                "pixel" => {
                    self.magnify_mode = CanvasMagnify::PixelPerfect;
                }
                "nearest" => {
                    self.magnify_mode = CanvasMagnify::Nearest;
                }
                "smooth" => {
                    self.magnify_mode = CanvasMagnify::Smooth;
                }
                _ => {
                    return Err(format!("Bad magnify mode '{}'", mag));
                }
            };
        }

        if let Some(&Value::Boolean(b)) = settings.get("fullscreen") {
            self.fullscreen = b;
        }

        if let Some(&Value::Boolean(b)) = settings.get("fps") {
            self.show_fps = b;
        }

        Ok(())
    }
}
<commit_msg>Drop vorud stuff<commit_after>use std::default::Default;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::prelude::*;
use getopts::Options;
use toml::{self, Value};
use calx::backend::CanvasMagnify;
use super::app_data_path;

thread_local!(pub static _CONFIG: Config = Default::default());

#[derive(Copy, Clone, Debug)]
pub struct Config {
    /// The player will move to the side when bumping against a wall.
    pub wall_sliding: bool,
    /// How to scale the graphics when making the window larger.
    pub magnify_mode: CanvasMagnify,
    /// Fixed world random number generator seed.
    pub rng_seed: Option<u32>,
    /// Start in fullscreen mode
    pub fullscreen: bool,
    /// Show FPS counter
    pub show_fps: bool,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            wall_sliding: true,
            magnify_mode: CanvasMagnify::PixelPerfect,
            rng_seed: None,
            fullscreen: false,
            show_fps: false,
        }
    }
}

impl Config {
    /// Parse command line options and apply them to the config object. Return
    /// an error containing a usage string if the parsing fails.
    ///
    /// Returning a string with Ok indicates that the string should be printed
    /// and the program should then exit.
    pub fn parse_args<T: Iterator<Item = String>>(&mut self,
                                                  args: T)
                                                  -> Result<Option<String>, String> {
        let mut opts = Options::new();
        opts.optflag("",
                     "no-wall-sliding",
                     "Don't move diagonally along obstacles when walking into them");
        opts.optflag("h", "help", "Display this message");
        opts.optflag("V", "version", "Print version info and exit");
        opts.optopt("",
                    "magnify-mode",
                    "How to filter magnified graphics. MODE = pixel | nearest | smooth",
                    "MODE");
        opts.optopt("", "seed", "World generation seed number", "SEED");
        opts.optflag("", "fullscreen", "Run in fullscreen mode");
        opts.optflag("", "fps", "Show FPS counter");

        let args: Vec<String> = args.collect();

        let parse = match opts.parse(&args[1..]) {
            Ok(m) => m,
            Err(f) => {
                return Err(usage_error(f.to_string(), &opts));
            }
        };

        if parse.opt_present("help") {
            return Ok(Some(format!("{}", opts.usage("Usage: magog [options]"))));
        }

        if parse.opt_present("version") {
            return Ok(Some(format!("Magog v{}", ::version())));
        }

        if parse.opt_present("no-wall-sliding") {
            self.wall_sliding = false;
        }

        if parse.opt_present("fullscreen") {
            self.fullscreen = true;
        }

        if parse.opt_present("fps") {
            self.show_fps = true;
        }

        if let Some(x) = parse.opt_str("magnify-mode") {
            match &x[..] {
                "pixel" => {
                    self.magnify_mode = CanvasMagnify::PixelPerfect;
                }
                "nearest" => {
                    self.magnify_mode = CanvasMagnify::Nearest;
                }
                "smooth" => {
                    self.magnify_mode = CanvasMagnify::Smooth;
                }
                err => {
                    return Err(usage_error(format!("Unknown magnify mode '{}'", err), &opts));
                }
            }
        }

        if let Some(seed) = parse.opt_str("seed") {
            // XXX: Could this be written to use the try! macro?
            let err = Err(usage_error(format!("Invalid seed value '{}'", seed), &opts));
            if let Ok(val) = seed.parse::<u32>() {
                self.rng_seed = Some(val);
            } else {
                return err;
            }
        }

        return Ok(None);

        fn usage_error(msg: String, opts: &Options) -> String {
            format!("{}\n{}",
                    msg,
                    opts.usage("Usage:\n    magog [options]"))
        }
    }

    pub fn file_path(&self) -> PathBuf {
        let mut ret = app_data_path();
        ret.push("config.toml");
        ret
    }

    /// Output the default config file.
    pub fn default_file(&self) -> String {
        // TODO: Make this data-driven, have option metadata that specifies
        // the help string and what to print out.
        format!(r#"# Move diagonally along obstacles when walking into them
wall-sliding = true

# How to filter magnified graphics. pixel | nearest | smooth
magnify-mode = "pixel"

# Start the game in fullscreen instead of windowed mode
fullscreen = false

# Display FPS counter
fps = false
"#)
    }

    pub fn load<P: AsRef<Path>>(&mut self, path: P) -> Result<(), String> {
        // TODO: Error handling.

        // TODO: This should be data-driven somehow from a common config
        // metadata object instead of relying on the error-prone retyped
        // schema in the match segment.
        let mut file = File::open(path).unwrap();
        let mut toml = String::new();
        file.read_to_string(&mut toml).unwrap();

        let mut parser = toml::Parser::new(&toml);

        let settings = parser.parse();

        if settings.is_none() {
            let mut err = String::new();
            for e in parser.errors.iter() {
                err.push_str(&format!("{}", e));
            }
            return Err(err);
        }

        let settings = settings.unwrap();

        // TODO: Error message instead of silent no-op if the type of the
        // value isn't what we expect.
        if let Some(&Value::Boolean(b)) = settings.get("wall-sliding") {
            self.wall_sliding = b;
        }

        if let Some(&Value::String(ref mag)) = settings.get("magnify-mode") {
            match &mag[..] {
                "pixel" => {
                    self.magnify_mode = CanvasMagnify::PixelPerfect;
                }
                "nearest" => {
                    self.magnify_mode = CanvasMagnify::Nearest;
                }
                "smooth" => {
                    self.magnify_mode = CanvasMagnify::Smooth;
                }
                _ => {
                    return Err(format!("Bad magnify mode '{}'", mag));
                }
            };
        }

        if let Some(&Value::Boolean(b)) = settings.get("fullscreen") {
            self.fullscreen = b;
        }

        if let Some(&Value::Boolean(b)) = settings.get("fps") {
            self.show_fps = b;
        }

        Ok(())
    }
}
<|endoftext|>