<commit_before>
use std::num::Float;
use sdl::video::{Surface};
use sdl::event::{Key};

use map::{Map};
use math::{LineSeg, Vec2, Mat3};
use input::{InputState};
use math;

pub struct Game<'a> {
    pub pos: Vec2,
    pub face_angle: f32,
    pub map: &'a Map,
    pub show_map: bool,
}

const SPEED: f32 = 0.4;
const TURN: f32 = 0.03;
const FOV_DIV: f32 = 500.0;
const WALL: f32 = 3000.0;

impl<'a> Game<'a> {

    pub fn step(&mut self, input: &InputState) {
        if input.has_key(Key::Left) {
            self.face_angle -= TURN;
        }
        if input.has_key(Key::Right) {
            self.face_angle += TURN;
        }
        if input.has_key(Key::W) {
            self.pos.x += SPEED*Float::sin(self.face_angle);
            self.pos.y -= SPEED*Float::cos(self.face_angle);
        }
        if input.has_key(Key::S) {
            self.pos.x -= SPEED*Float::sin(self.face_angle);
            self.pos.y += SPEED*Float::cos(self.face_angle);
        }
        if input.has_key(Key::A) {
            self.pos.x -= SPEED*Float::cos(self.face_angle);
            self.pos.y -= SPEED*Float::sin(self.face_angle);
        }
        if input.has_key(Key::D) {
            self.pos.x += SPEED*Float::cos(self.face_angle);
            self.pos.y += SPEED*Float::sin(self.face_angle);
        }
        self.show_map = input.has_key(Key::Tab);
        }
    }

    pub fn render(&self, surf: &Surface) {
        if self.show_map {
            self.render_lines(&surf);
        } else {
            self.render_cast(&surf);
        }
    }

    fn render_lines(&self, surf: &Surface) {
        let trans = Mat3::rotation(-self.face_angle)
                  * Mat3::translation(-self.pos);

        surf.clear();
        for wall in self.map.walls.iter() {
            draw_seg(&surf, &wall.transform(trans), 0xFF, 0x00, 0x00);
        }

        let w = surf.get_width() as usize;
        for x in 0..w {
            let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;
            let (q1,q2) = self.cast_ray(offset);
            match q1 {
                Some(dist) => {
                    let hit = Vec2::new(
                         Float::sin(self.face_angle),
                        -Float::cos(self.face_angle)
                    ) * dist;
                    let draw_sg = LineSeg::new(self.pos.x, self.pos.y, q2.x, q2.y);
                    draw_seg(&surf, &draw_sg.transform(trans), 0x00, 0xFF, 0x00);
                }
                None => {}
            }
        }
    }

    fn render_cast(&self, surf: &Surface) {
        let w = surf.get_width() as usize;
        let h = surf.get_height() as usize;

        surf.clear();
        surf.with_lock(|pixels| {
            for x in 0..w {
                let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;
                let (q1,q2) = self.cast_ray(offset);
                match q1 {
                    Some(dist) => {
                        let ray_height = (WALL / dist) as usize;
                        let top = if h > ray_height { (h - ray_height) / 2 } else { 0 };
                        let bottom = h - top;
                        let proto_color = (0xFF-(h/2) + ray_height/2);
                        let color = if proto_color > 0xFF { 0xFF } else { proto_color as u8 };
                        for y in 0..top {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in top..bottom {
                            put_px(pixels, w, x, y, color, 0, 0);
                        }
                        for y in bottom..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                    None => {
                        for y in 0..(h/2) {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in (h/2)..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                }
            }
            true
        });
    }

    fn cast_ray(&self, offset: f32) -> (Option<f32>, Vec2) {
        let ray = LineSeg::new(
            self.pos.x,
            self.pos.y,
            self.pos.x + 1000.0*Float::sin(self.face_angle + offset),
            self.pos.y - 1000.0*Float::cos(self.face_angle + offset)
        );

        let mut shortest: Option<f32> = None;
        let mut vv: Vec2 = math::V2_ORIGIN;

        for wall in self.map.walls.iter() {
            match ray.intersects_at(*wall) {
                Some(t) => {
                    let dist = (wall.at(t) - self.pos).get_length() * Float::cos(offset);
                    shortest = match shortest {
                        Some(d) => { if dist < d { vv = wall.at(t); Some(dist) } else { shortest } }
                        None    => { vv = wall.at(t); Some(dist) }
                    }
                }
                None => {}
            };
        }

        (shortest, vv)
    }
}

fn put_px(pixels: &mut [u8], w: usize, x: usize, y: usize, r: u8, g: u8, b: u8) {
    pixels[3*(w*y+x) + 0] = b;
    pixels[3*(w*y+x) + 1] = g;
    pixels[3*(w*y+x) + 2] = r;
}

fn draw_seg(surf: &Surface, seg: &LineSeg, r: u8, g: u8, b: u8) {
    let w = surf.get_width() as usize;
    let h = surf.get_height() as usize;
    let len = seg.get_length();

    surf.with_lock(|pixels| {
        for t in 0..(len as usize) {
            let pt = seg.at(t as f32 / len);
            let ux = (pt.x + (w/2) as f32) as usize;
            let uy = (pt.y + (h/2) as f32) as usize;

            if ux < w && uy < h {
                put_px(pixels, w, ux, uy, r, g, b);
            }
        };
        true
    });
}
<commit_msg>Removed broken }<commit_after>
use std::num::Float;
use sdl::video::{Surface};
use sdl::event::{Key};

use map::{Map};
use math::{LineSeg, Vec2, Mat3};
use input::{InputState};
use math;

pub struct Game<'a> {
    pub pos: Vec2,
    pub face_angle: f32,
    pub map: &'a Map,
    pub show_map: bool,
}

const SPEED: f32 = 0.4;
const TURN: f32 = 0.03;
const FOV_DIV: f32 = 500.0;
const WALL: f32 = 3000.0;

impl<'a> Game<'a> {

    pub fn step(&mut self, input: &InputState) {
        if input.has_key(Key::Left) {
            self.face_angle -= TURN;
        }
        if input.has_key(Key::Right) {
            self.face_angle += TURN;
        }
        if input.has_key(Key::W) {
            self.pos.x += SPEED*Float::sin(self.face_angle);
            self.pos.y -= SPEED*Float::cos(self.face_angle);
        }
        if input.has_key(Key::S) {
            self.pos.x -= SPEED*Float::sin(self.face_angle);
            self.pos.y += SPEED*Float::cos(self.face_angle);
        }
        if input.has_key(Key::A) {
            self.pos.x -= SPEED*Float::cos(self.face_angle);
            self.pos.y -= SPEED*Float::sin(self.face_angle);
        }
        if input.has_key(Key::D) {
            self.pos.x += SPEED*Float::cos(self.face_angle);
            self.pos.y += SPEED*Float::sin(self.face_angle);
        }
        self.show_map = input.has_key(Key::Tab);
    }

    pub fn render(&self, surf: &Surface) {
        if self.show_map {
            self.render_lines(&surf);
        } else {
            self.render_cast(&surf);
        }
    }

    fn render_lines(&self, surf: &Surface) {
        let trans = Mat3::rotation(-self.face_angle)
                  * Mat3::translation(-self.pos);

        surf.clear();
        for wall in self.map.walls.iter() {
            draw_seg(&surf, &wall.transform(trans), 0xFF, 0x00, 0x00);
        }

        let w = surf.get_width() as usize;
        for x in 0..w {
            let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;
            let (q1,q2) = self.cast_ray(offset);
            match q1 {
                Some(dist) => {
                    let hit = Vec2::new(
                         Float::sin(self.face_angle),
                        -Float::cos(self.face_angle)
                    ) * dist;
                    let draw_sg = LineSeg::new(self.pos.x, self.pos.y, q2.x, q2.y);
                    draw_seg(&surf, &draw_sg.transform(trans), 0x00, 0xFF, 0x00);
                }
                None => {}
            }
        }
    }

    fn render_cast(&self, surf: &Surface) {
        let w = surf.get_width() as usize;
        let h = surf.get_height() as usize;

        surf.clear();
        surf.with_lock(|pixels| {
            for x in 0..w {
                let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;
                let (q1,q2) = self.cast_ray(offset);
                match q1 {
                    Some(dist) => {
                        let ray_height = (WALL / dist) as usize;
                        let top = if h > ray_height { (h - ray_height) / 2 } else { 0 };
                        let bottom = h - top;
                        let proto_color = (0xFF-(h/2) + ray_height/2);
                        let color = if proto_color > 0xFF { 0xFF } else { proto_color as u8 };
                        for y in 0..top {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in top..bottom {
                            put_px(pixels, w, x, y, color, 0, 0);
                        }
                        for y in bottom..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                    None => {
                        for y in 0..(h/2) {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in (h/2)..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                }
            }
            true
        });
    }

    fn cast_ray(&self, offset: f32) -> (Option<f32>, Vec2) {
        let ray = LineSeg::new(
            self.pos.x,
            self.pos.y,
            self.pos.x + 1000.0*Float::sin(self.face_angle + offset),
            self.pos.y - 1000.0*Float::cos(self.face_angle + offset)
        );

        let mut shortest: Option<f32> = None;
        let mut vv: Vec2 = math::V2_ORIGIN;

        for wall in self.map.walls.iter() {
            match ray.intersects_at(*wall) {
                Some(t) => {
                    let dist = (wall.at(t) - self.pos).get_length() * Float::cos(offset);
                    shortest = match shortest {
                        Some(d) => { if dist < d { vv = wall.at(t); Some(dist) } else { shortest } }
                        None    => { vv = wall.at(t); Some(dist) }
                    }
                }
                None => {}
            };
        }

        (shortest, vv)
    }
}

fn put_px(pixels: &mut [u8], w: usize, x: usize, y: usize, r: u8, g: u8, b: u8) {
    pixels[3*(w*y+x) + 0] = b;
    pixels[3*(w*y+x) + 1] = g;
    pixels[3*(w*y+x) + 2] = r;
}

fn draw_seg(surf: &Surface, seg: &LineSeg, r: u8, g: u8, b: u8) {
    let w = surf.get_width() as usize;
    let h = surf.get_height() as usize;
    let len = seg.get_length();

    surf.with_lock(|pixels| {
        for t in 0..(len as usize) {
            let pt = seg.at(t as f32 / len);
            let ux = (pt.x + (w/2) as f32) as usize;
            let uy = (pt.y + (h/2) as f32) as usize;

            if ux < w && uy < h {
                put_px(pixels, w, ux, uy, r, g, b);
            }
        };
        true
    });
}
<|endoftext|>


<commit_before>use std::result;

use futures::sync::oneshot;

use super::ParsedRequest;

// This defines the possible outcomes of an async request from the perspective of the VMM. Currently
// an async action can be successful (and have an associated timestamp of the completion time), or
// it can result in some error whose message is captured and sent to the API server.
#[derive(Debug)]
pub enum AsyncOutcome {
    Ok(u64),
    Error(String),
}

// The halves of a request/reponse channel associated with each async request.
pub type AsyncOutcomeSender = oneshot::Sender<AsyncOutcome>;
pub type AsyncOutcomeReceiver = oneshot::Receiver<AsyncOutcome>;

// This enum contains messages which convey to the VMM the type of async request. Each request must
// also be associated with an outcome sender, which is used by the VMM to transmit the result.
#[derive(Debug)]
pub enum AsyncRequest {
    StartInstance(AsyncOutcomeSender),
    StopInstance(AsyncOutcomeSender),
}

#[derive(Debug, Deserialize, Serialize)]
pub enum DeviceType {
    Drive,
}

// Represents the associated json block from the async request body.
#[derive(Debug, Deserialize, Serialize)]
struct InstanceDeviceDetachAction {
    device_type: DeviceType,
    device_resource_id: String,
    force: bool,
}

// The names of the members from this enum must precisely correspond (as a string) to the possible
// values of "action_type" from the json request body. This is useful to get a strongly typed
// struct from the Serde deserialization process.
#[derive(Debug, Deserialize, Serialize)]
pub enum AsyncActionType {
    InstanceStart,
    InstanceHalt,
}

// The model of the json body from an async request. We use Serde to transform each associated
// json body into this.
#[derive(Debug, Deserialize, Serialize)]
pub struct AsyncRequestBody {
    action_id: String,
    action_type: AsyncActionType,
    #[serde(skip_serializing_if = "Option::is_none")]
    instance_device_detach_action: Option<InstanceDeviceDetachAction>,
    #[serde(skip_serializing_if = "Option::is_none")]
    timestamp: Option<u64>,
}

impl AsyncRequestBody {
    pub fn set_timestamp(&mut self, timestamp: u64) {
        self.timestamp = Some(timestamp);
    }

    // The same overall body structure is shared by all async action. This function extracts the
    // particular type of action from a body, while also handling validation.
    pub fn to_parsed_request(&self, _id_from_path: &str) -> result::Result<ParsedRequest, String> {
        // todo: how do we validate the input? (for example, what do we do when timestamp is
        // present in the request body?) do we check if the id_from_path is the same as the body id?
        let (sender, receiver) = oneshot::channel();
        let id = self.action_id.clone();

        match self.action_type {
            AsyncActionType::InstanceStart => Ok(ParsedRequest::Async(
                id,
                AsyncRequest::StartInstance(sender),
                receiver,
            )),
            AsyncActionType::InstanceHalt => Ok(ParsedRequest::Async(
                id,
                AsyncRequest::StopInstance(sender),
                receiver,
            )),
        }
    }
}
<commit_msg>api_server: add unit tests to request::async<commit_after>use std::result;

use futures::sync::oneshot;

use super::ParsedRequest;

// This defines the possible outcomes of an async request from the perspective of the VMM. Currently
// an async action can be successful (and have an associated timestamp of the completion time), or
// it can result in some error whose message is captured and sent to the API server.
#[derive(Debug)]
pub enum AsyncOutcome {
    Ok(u64),
    Error(String),
}

// The halves of a request/reponse channel associated with each async request.
pub type AsyncOutcomeSender = oneshot::Sender<AsyncOutcome>;
pub type AsyncOutcomeReceiver = oneshot::Receiver<AsyncOutcome>;

// This enum contains messages which convey to the VMM the type of async request. Each request must
// also be associated with an outcome sender, which is used by the VMM to transmit the result.
#[derive(Debug)]
pub enum AsyncRequest {
    StartInstance(AsyncOutcomeSender),
    StopInstance(AsyncOutcomeSender),
}

#[derive(Debug, Deserialize, Serialize)]
pub enum DeviceType {
    Drive,
}

// Represents the associated json block from the async request body.
#[derive(Debug, Deserialize, Serialize)]
struct InstanceDeviceDetachAction {
    device_type: DeviceType,
    device_resource_id: String,
    force: bool,
}

// The names of the members from this enum must precisely correspond (as a string) to the possible
// values of "action_type" from the json request body. This is useful to get a strongly typed
// struct from the Serde deserialization process.
#[derive(Debug, Deserialize, Serialize)]
pub enum AsyncActionType {
    InstanceStart,
    InstanceHalt,
}

// The model of the json body from an async request. We use Serde to transform each associated
// json body into this.
#[derive(Debug, Deserialize, Serialize)]
pub struct AsyncRequestBody {
    action_id: String,
    action_type: AsyncActionType,
    #[serde(skip_serializing_if = "Option::is_none")]
    instance_device_detach_action: Option<InstanceDeviceDetachAction>,
    #[serde(skip_serializing_if = "Option::is_none")]
    timestamp: Option<u64>,
}

impl AsyncRequestBody {
    pub fn set_timestamp(&mut self, timestamp: u64) {
        self.timestamp = Some(timestamp);
    }

    // The same overall body structure is shared by all async action. This function extracts the
    // particular type of action from a body, while also handling validation.
    pub fn to_parsed_request(&self, _id_from_path: &str) -> result::Result<ParsedRequest, String> {
        // todo: how do we validate the input? (for example, what do we do when timestamp is
        // present in the request body?) do we check if the id_from_path is the same as the body id?
        let (sender, receiver) = oneshot::channel();
        let id = self.action_id.clone();

        match self.action_type {
            AsyncActionType::InstanceStart => Ok(ParsedRequest::Async(
                id,
                AsyncRequest::StartInstance(sender),
                receiver,
            )),
            AsyncActionType::InstanceHalt => Ok(ParsedRequest::Async(
                id,
                AsyncRequest::StopInstance(sender),
                receiver,
            )),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json;

    impl PartialEq for AsyncRequest {
        fn eq(&self, other: &AsyncRequest) -> bool {
            match (self, other) {
                (&AsyncRequest::StartInstance(_), &AsyncRequest::StartInstance(_)) => true,
                (&AsyncRequest::StopInstance(_), &AsyncRequest::StopInstance(_)) => true,
                _ => false
            }
        }
    }

    impl PartialEq for ParsedRequest {
        fn eq(&self, other: &ParsedRequest) -> bool {
            match (self, other) {
                (&ParsedRequest::Async(ref id, ref request, _),
                    &ParsedRequest::Async(ref other_id, ref other_request, _)) =>
                        id == other_id && request == other_request,
                (&ParsedRequest::Sync(ref sync_req, _),
                    &ParsedRequest::Sync(ref other_sync_req, _)) =>
                        sync_req == other_sync_req,
                (&ParsedRequest::Dummy, &ParsedRequest::Dummy) => true,
                (&ParsedRequest::GetInstanceInfo, &ParsedRequest::GetInstanceInfo) => true,
                (&ParsedRequest::GetActions, &ParsedRequest::GetActions) => true,
                (&ParsedRequest::GetAction(ref id), &ParsedRequest::GetAction(ref other_id)) =>
                    id == other_id,
                _ => false
            }
        }
    }

    #[test]
    fn test_to_parsed_request() {
        let jsons = vec!(
            "{
                \"action_id\": \"dummy\",
                \"action_type\": \"InstanceStart\",
                \"instance_device_detach_action\": {\
                    \"device_type\": \"Drive\",
                    \"device_resource_id\": \"dummy\",
                    \"force\": true},
                \"timestamp\": 1522850095
              }",
            "{
                \"action_id\": \"dummy\",
                \"action_type\": \"InstanceHalt\",
                \"instance_device_detach_action\": {\
                    \"device_type\": \"Drive\",
                    \"device_resource_id\": \"dummy\",
                    \"force\": true},
                \"timestamp\": 1522850095
              }",
            "{
                \"action_id\": \"not_dummy\",
                \"action_type\": \"InstanceStart\",
                \"instance_device_detach_action\": {\
                    \"device_type\": \"Drive\",
                    \"device_resource_id\": \"dummy\",
                    \"force\": true},
                \"timestamp\": 1522850095
              }",
            "{
                \"action_id\": \"dummy\",
                \"action_type\": \"IAmNotAnActionType\"\
              }"
        );
        let (sender, receiver) = oneshot::channel();
        let req: ParsedRequest = ParsedRequest::Async(
                String::from("dummy"),
                AsyncRequest::StartInstance(sender),
                receiver
            );

        let mut result: Result<AsyncRequestBody, serde_json::Error> =
            serde_json::from_str(jsons[0]);
        assert!(result.is_ok());
        assert!(result.unwrap().to_parsed_request("dummy").unwrap().eq(&req));

        for json in jsons[1..3].to_vec() {
            result = serde_json::from_str(json);
            assert!(result.is_ok());
            assert!(!result.unwrap().to_parsed_request("dummy").unwrap().eq(&req));
        }

        result = serde_json::from_str(jsons[3]);
        assert!(result.is_err());
    }

    #[test]
    fn test_set_timestamp() {
        let j = b"{
                    \"action_id\": \"dummy\",
                    \"action_type\": \"InstanceStart\",
                    \"instance_device_detach_action\": {\
                        \"device_type\": \"Drive\",
                        \"device_resource_id\": \"dummy\",
                        \"force\": true},
                    \"timestamp\": 1522850095
                  }";
        let mut async_body: AsyncRequestBody =
            serde_json::from_slice(j).unwrap();
        async_body.set_timestamp(1522850096);

        assert_eq!(async_body.timestamp, Some(1522850096));
    }
}
<|endoftext|>


<commit_before>//! A priority queue implemented with a splay tree.
use std;
use std::cmp;
use core;
use iter;

/// `SplayHeap` iterator.
pub struct Iter<'a, T: 'a> {
    iter: iter::Iter<'a, Item<T>, ()>,
}
impl<'a, T: 'a> Iter<'a, T> {
    fn new(tree: &'a core::Tree<Item<T>, ()>) -> Self {
        Iter { iter: iter::Iter::new(tree) }
    }
}
impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(i, _)| &i.0)
    }
}

/// An iterator that moves out of a `SplayHeap`.
pub struct IntoIter<T>(SplayHeap<T>);
impl<T> Iterator for IntoIter<T>
    where T: Ord
{
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.pop()
    }
}

#[derive(Debug,Clone,PartialEq,Eq,PartialOrd)]
struct Item<T>(T);
impl<T> Ord for Item<T>
    where T: Ord
{
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        match self.0.cmp(&other.0) {
            cmp::Ordering::Equal => cmp::Ordering::Greater,
            cmp::Ordering::Less => cmp::Ordering::Greater,
            cmp::Ordering::Greater => cmp::Ordering::Less,
        }
    }
}

/// A priority queue implemented with a splay tree.
///
/// This will be a max-heap.
///
/// A splay tree based heap is a self-adjusting data structure.
/// It performs pushing and popping in `O(log n)` amortized time.
///
/// It is a logic error for a key to be modified in such a way that
/// the key's ordering relative to any other key,
/// as determined by the `Ord` trait, changes while it is in the map.
/// This is normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code.
///
/// # Examples
/// ```
/// use splay_tree::SplayHeap;
///
/// let mut heap = SplayHeap::new();
///
/// heap.push(0);
/// heap.push(10);
/// heap.push(7);
///
/// assert_eq!(heap.peek(), Some(&10));
/// assert_eq!(heap.pop(), Some(10));
/// assert_eq!(heap.pop(), Some(7));
/// assert_eq!(heap.pop(), Some(0));
/// assert_eq!(heap.pop(), None);
/// ```
#[derive(Debug,Clone)]
pub struct SplayHeap<T> {
    tree: core::Tree<Item<T>, ()>,
}
impl<T> SplayHeap<T>
    where T: Ord
{
    /// Creates an empty `SplayHeap` as a max-heap.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap = SplayHeap::new();
    ///
    /// heap.push(10);
    /// assert_eq!(heap.pop(), Some(10));
    /// ```
    pub fn new() -> Self {
        SplayHeap { tree: core::Tree::new() }
    }

    /// Returns the greatest item in the heap, or `None` if it is empty.
    ///
    /// # NOTICE
    /// Because `SplayHeap` is a self-adjusting amortized data structure,
    /// this function requires the `mut` qualifier.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap = SplayHeap::new();
    /// assert_eq!(heap.peek(), None);
    ///
    /// heap.push(1);
    /// heap.push(5);
    /// heap.push(2);
    /// assert_eq!(heap.peek(), Some(&5));
    /// ```
    pub fn peek(&mut self) -> Option<&T> {
        self.tree.get_lftmost().map(|(i, _)| &i.0)
    }

    /// Removes the greatest item from the heap and returns it, or `None` if it is empty.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap: SplayHeap<_> = vec![1, 3].into_iter().collect();
    ///
    /// assert_eq!(heap.pop(), Some(3));
    /// assert_eq!(heap.pop(), Some(1));
    /// assert_eq!(heap.pop(), None);
    /// ```
    pub fn pop(&mut self) -> Option<T> {
        self.tree.take_lftmost().map(|(i, _)| i.0)
    }

    /// Pushes an item onto the heap.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap = SplayHeap::new();
    /// heap.push(3);
    /// heap.push(5);
    /// heap.push(1);
    ///
    /// assert_eq!(heap.len(), 3);
    /// assert_eq!(heap.peek(), Some(&5));
    /// ```
    pub fn push(&mut self, item: T) {
        self.tree.insert(Item(item), ());
    }

    /// Drops all items from the heap.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap: SplayHeap<_> = vec![1, 3].into_iter().collect();
    ///
    /// assert!(!heap.is_empty());
    /// heap.clear();
    /// assert!(heap.is_empty());
    /// ```
    pub fn clear(&mut self) {
        self.tree = core::Tree::new();
    }
}
impl<T> SplayHeap<T> {
    /// Returns an iterator visiting all items in sorted (ascending) order.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let heap: SplayHeap<_> = vec![1, 4, 2, 3].into_iter().collect();
    ///
    /// // Print all values in `heap` in sorted order
    /// for x in heap.iter() {
    ///   println!("{}", x);
    /// }
    /// ```
    pub fn iter(&self) -> Iter<T> {
        Iter::new(&self.tree)
    }

    /// Returns the length of the heap.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let heap: SplayHeap<_> = vec![1, 3].into_iter().collect();
    ///
    /// assert_eq!(heap.len(), 2);
    /// ```
    pub fn len(&self) -> usize {
        self.tree.len
    }

    /// Checkes if the heap is empty.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap = SplayHeap::new();
    ///
    /// assert!(heap.is_empty());
    ///
    /// heap.push(1);
    /// assert!(!heap.is_empty());
    ///
    /// heap.pop();
    /// assert!(heap.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}
impl<T> Default for SplayHeap<T>
    where T: Ord
{
    fn default() -> Self {
        SplayHeap::new()
    }
}
impl<T> std::iter::FromIterator<T> for SplayHeap<T>
    where T: Ord
{
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item = T>
    {
        let mut heap = SplayHeap::new();
        for x in iter {
            heap.push(x);
        }
        heap
    }
}
impl<T> IntoIterator for SplayHeap<T>
    where T: Ord
{
    type Item = T;
    type IntoIter = IntoIter<T>;
    fn into_iter(self) -> Self::IntoIter {
        IntoIter(self)
    }
}
impl<'a, T> IntoIterator for &'a SplayHeap<T>
    where T: Ord
{
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}
impl<T> Extend<T> for SplayHeap<T>
    where T: Ord
{
    fn extend<I>(&mut self, iter: I)
        where I: IntoIterator<Item = T>
    {
        for x in iter {
            self.push(x);
        }
    }
}
impl<'a, T> Extend<&'a T> for SplayHeap<T>
    where T: Copy + 'a + Ord
{
    fn extend<I>(&mut self, iter: I)
        where I: IntoIterator<Item = &'a T>
    {
        for x in iter {
            self.push(*x);
        }
    }
}
<commit_msg>Modify comment<commit_after>//! A priority queue implemented with a splay tree.
use std;
use std::cmp;
use core;
use iter;

/// `SplayHeap` iterator.
pub struct Iter<'a, T: 'a> {
    iter: iter::Iter<'a, Item<T>, ()>,
}
impl<'a, T: 'a> Iter<'a, T> {
    fn new(tree: &'a core::Tree<Item<T>, ()>) -> Self {
        Iter { iter: iter::Iter::new(tree) }
    }
}
impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(i, _)| &i.0)
    }
}

/// An iterator that moves out of a `SplayHeap`.
pub struct IntoIter<T>(SplayHeap<T>);
impl<T> Iterator for IntoIter<T>
    where T: Ord
{
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.pop()
    }
}

#[derive(Debug,Clone,PartialEq,Eq,PartialOrd)]
struct Item<T>(T);
impl<T> Ord for Item<T>
    where T: Ord
{
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        match self.0.cmp(&other.0) {
            cmp::Ordering::Equal => cmp::Ordering::Greater,
            cmp::Ordering::Less => cmp::Ordering::Greater,
            cmp::Ordering::Greater => cmp::Ordering::Less,
        }
    }
}

/// A priority queue implemented with a splay tree.
///
/// This will be a max-heap.
///
/// A splay tree based heap is a self-adjusting data structure.
/// It performs pushing and popping in `O(log n)` amortized time.
///
/// It is a logic error for a key to be modified in such a way that
/// the key's ordering relative to any other key,
/// as determined by the `Ord` trait, changes while it is in the map.
/// This is normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code.
///
/// # Examples
/// ```
/// use splay_tree::SplayHeap;
///
/// let mut heap = SplayHeap::new();
///
/// heap.push(0);
/// heap.push(10);
/// heap.push(7);
///
/// assert_eq!(heap.peek(), Some(&10));
/// assert_eq!(heap.pop(), Some(10));
/// assert_eq!(heap.pop(), Some(7));
/// assert_eq!(heap.pop(), Some(0));
/// assert_eq!(heap.pop(), None);
/// ```
#[derive(Debug,Clone)]
pub struct SplayHeap<T> {
    tree: core::Tree<Item<T>, ()>,
}
impl<T> SplayHeap<T>
    where T: Ord
{
    /// Creates an empty `SplayHeap` as a max-heap.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap = SplayHeap::new();
    ///
    /// heap.push(10);
    /// assert_eq!(heap.pop(), Some(10));
    /// ```
    pub fn new() -> Self {
        SplayHeap { tree: core::Tree::new() }
    }

    /// Returns the greatest item in the heap, or `None` if it is empty.
    ///
    /// # NOTICE
    /// Because `SplayHeap` is a self-adjusting amortized data structure,
    /// this function requires the `mut` qualifier.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap = SplayHeap::new();
    /// assert_eq!(heap.peek(), None);
    ///
    /// heap.push(1);
    /// heap.push(5);
    /// heap.push(2);
    /// assert_eq!(heap.peek(), Some(&5));
    /// ```
    pub fn peek(&mut self) -> Option<&T> {
        self.tree.get_lftmost().map(|(i, _)| &i.0)
    }

    /// Removes the greatest item from the heap and returns it, or `None` if it is empty.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap: SplayHeap<_> = vec![1, 3].into_iter().collect();
    ///
    /// assert_eq!(heap.pop(), Some(3));
    /// assert_eq!(heap.pop(), Some(1));
    /// assert_eq!(heap.pop(), None);
    /// ```
    pub fn pop(&mut self) -> Option<T> {
        self.tree.take_lftmost().map(|(i, _)| i.0)
    }

    /// Pushes an item onto the heap.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap = SplayHeap::new();
    /// heap.push(3);
    /// heap.push(5);
    /// heap.push(1);
    ///
    /// assert_eq!(heap.len(), 3);
    /// assert_eq!(heap.peek(), Some(&5));
    /// ```
    pub fn push(&mut self, item: T) {
        self.tree.insert(Item(item), ());
    }

    /// Drops all items from the heap.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap: SplayHeap<_> = vec![1, 3].into_iter().collect();
    ///
    /// assert!(!heap.is_empty());
    /// heap.clear();
    /// assert!(heap.is_empty());
    /// ```
    pub fn clear(&mut self) {
        self.tree = core::Tree::new();
    }
}
impl<T> SplayHeap<T> {
    /// Returns an iterator visiting all items in sorted (descending) order.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let heap: SplayHeap<_> = vec![1, 4, 2, 3].into_iter().collect();
    ///
    /// // Print all values in `heap` in sorted order
    /// for x in heap.iter() {
    ///   println!("{}", x);
    /// }
    /// ```
    pub fn iter(&self) -> Iter<T> {
        Iter::new(&self.tree)
    }

    /// Returns the length of the heap.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let heap: SplayHeap<_> = vec![1, 3].into_iter().collect();
    ///
    /// assert_eq!(heap.len(), 2);
    /// ```
    pub fn len(&self) -> usize {
        self.tree.len
    }

    /// Checkes if the heap is empty.
    ///
    /// # Examples
    /// ```
    /// use splay_tree::SplayHeap;
    /// let mut heap = SplayHeap::new();
    ///
    /// assert!(heap.is_empty());
    ///
    /// heap.push(1);
    /// assert!(!heap.is_empty());
    ///
    /// heap.pop();
    /// assert!(heap.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}
impl<T> Default for SplayHeap<T>
    where T: Ord
{
    fn default() -> Self {
        SplayHeap::new()
    }
}
impl<T> std::iter::FromIterator<T> for SplayHeap<T>
    where T: Ord
{
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item = T>
    {
        let mut heap = SplayHeap::new();
        for x in iter {
            heap.push(x);
        }
        heap
    }
}
impl<T> IntoIterator for SplayHeap<T>
    where T: Ord
{
    type Item = T;
    type IntoIter = IntoIter<T>;
    fn into_iter(self) -> Self::IntoIter {
        IntoIter(self)
    }
}
impl<'a, T> IntoIterator for &'a SplayHeap<T>
    where T: Ord
{
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}
impl<T> Extend<T> for SplayHeap<T>
    where T: Ord
{
    fn extend<I>(&mut self, iter: I)
        where I: IntoIterator<Item = T>
    {
        for x in iter {
            self.push(x);
        }
    }
}
impl<'a, T> Extend<&'a T> for SplayHeap<T>
    where T: Copy + 'a + Ord
{
    fn extend<I>(&mut self, iter: I)
        where I: IntoIterator<Item = &'a T>
    {
        for x in iter {
            self.push(*x);
        }
    }
}
<|endoftext|>


<commit_before>//! Contains information for keybindings.

use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};
use rustwlc::xkb::{Keysym, NameFlags};
use rustwlc::types::*; // Need * for bitflags...
use std::hash::{Hash, Hasher};

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut map = HashMap::<KeyPress, KeyEvent>::new();
        let press_s = KeyPress::from_key_names(vec!["Mod4"], vec!["s"]).unwrap();
        trace!("[bindings] Press_s: {:?}", press_s);
        map.insert(press_s, Arc::new(Box::new(key_s)));
        let press_f4 = KeyPress::from_key_names(vec!["Alt"], vec!["F4"]).unwrap();
        trace!("[bindings] press_f4: {:?}", press_f4);
        map.insert(press_f4, Arc::new(Box::new(key_f4)));
        RwLock::new(map)
    };
}

fn key_s() {
    info!("[Key handler] S keypress!");
}

fn key_f4() {
    info!("[Key handler] F4 keypress!");
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct KeyPress {
    modifiers: KeyMod,
    keys: Vec<Keysym>
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: Vec<&str>) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result);
}

impl KeyPress {
    /// Creates a new KeyPress struct from a list of modifier and key names
    pub fn from_key_names(mods: Vec<&str>, keys: Vec<&str>) -> Result<KeyPress, String> {
        match keymod_from_names(mods) {
            Err(message) => Err(message),
            Ok(mods) => {
                let mut syms: Vec<Keysym> = Vec::with_capacity(keys.len());
                for name in keys {
                    if let Some(sym) = Keysym::from_name(name.to_string(),
                                                         NameFlags::None) {
                            syms.push(sym);
                    }
                    // Else if could not parse
                    else if let Some(sym) = Keysym::from_name(name.to_string(),
                                                        NameFlags::CaseInsensitive) {
                        syms.push(sym);
                    }
                    else {
                        return Err(format!("Invalid key: {}", name));
                    }
                }
                syms.sort_by_key(|s| s.get_code());
                syms.dedup();
                return Ok(KeyPress { modifiers: mods, keys: syms });
            }
        }
    }

    /// Creates a KeyPress from keys that are pressed at the moment
    pub fn new(mods: KeyMod, mut keys: Vec<Keysym>) -> KeyPress {
        keys.sort_by_key(|k| k.get_code());
        keys.dedup();

        KeyPress { modifiers: mods, keys: keys }
    }
}

impl Hash for KeyPress {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.modifiers.bits());
        for ref sym in &self.keys {
            hasher.write_u32(sym.get_code());
        }
    }
}

/// The type of function a key press handler is.
pub type KeyEvent = Arc<Box<Fn() + Send + Sync>>;

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read().unwrap();
    match bindings.get(key) {
        None => None,
        Some(val) => Some(val.clone())
    }
}

/// Register a new key mapping
pub fn register(values: Vec<(KeyPress, KeyEvent)>) {
    let mut bindings = BINDINGS.write().unwrap();
    for value in values {
        bindings.insert(value.0, value.1);
    }
}
<commit_msg>Add basic ctrl+l keybinding that prints hello world from lua<commit_after>//! Contains information for keybindings.

use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};
use rustwlc::xkb::{Keysym, NameFlags};
use rustwlc::types::*; // Need * for bitflags...
use std::hash::{Hash, Hasher};

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut map = HashMap::<KeyPress, KeyEvent>::new();

        let press_s = KeyPress::from_key_names(vec!["Mod4"], vec!["s"]).unwrap();
        map.insert(press_s, Arc::new(Box::new(key_s)));

        let press_f4 = KeyPress::from_key_names(vec!["Alt"], vec!["F4"]).unwrap();
        map.insert(press_f4, Arc::new(Box::new(key_f4)));

        let press_l = KeyPress::from_key_names(vec!["Ctrl"], vec!["l"]).unwrap();
        map.insert(press_l, Arc::new(Box::new(key_lua)));

        RwLock::new(map)
    };
}

fn key_s() {
    info!("[Key handler] S keypress!");
}

fn key_f4() {
    info!("[Key handler] F4 keypress!");
}

fn key_lua() {
    use super::lua;
    use lua::LuaQuery;
    info!("[Key handler] ctrl+l keypress!");
    lua::send(LuaQuery::Execute("print('Hello world from lua keypress!')".to_string()));
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct KeyPress {
    modifiers: KeyMod,
    keys: Vec<Keysym>
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: Vec<&str>) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result);
}

impl KeyPress {
    /// Creates a new KeyPress struct from a list of modifier and key names
    pub fn from_key_names(mods: Vec<&str>, keys: Vec<&str>) -> Result<KeyPress, String> {
        match keymod_from_names(mods) {
            Err(message) => Err(message),
            Ok(mods) => {
                let mut syms: Vec<Keysym> = Vec::with_capacity(keys.len());
                for name in keys {
                    if let Some(sym) = Keysym::from_name(name.to_string(),
                                                         NameFlags::None) {
                            syms.push(sym);
                    }
                    // Else if could not parse
                    else if let Some(sym) = Keysym::from_name(name.to_string(),
                                                        NameFlags::CaseInsensitive) {
                        syms.push(sym);
                    }
                    else {
                        return Err(format!("Invalid key: {}", name));
                    }
                }
                syms.sort_by_key(|s| s.get_code());
                syms.dedup();
                return Ok(KeyPress { modifiers: mods, keys: syms });
            }
        }
    }

    /// Creates a KeyPress from keys that are pressed at the moment
    pub fn new(mods: KeyMod, mut keys: Vec<Keysym>) -> KeyPress {
        keys.sort_by_key(|k| k.get_code());
        keys.dedup();

        KeyPress { modifiers: mods, keys: keys }
    }
}

impl Hash for KeyPress {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.modifiers.bits());
        for ref sym in &self.keys {
            hasher.write_u32(sym.get_code());
        }
    }
}

/// The type of function a key press handler is.
pub type KeyEvent = Arc<Box<Fn() + Send + Sync>>;

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read().unwrap();
    match bindings.get(key) {
        None => None,
        Some(val) => Some(val.clone())
    }
}

/// Register a new key mapping
pub fn register(values: Vec<(KeyPress, KeyEvent)>) {
    let mut bindings = BINDINGS.write().unwrap();
    for value in values {
        bindings.insert(value.0, value.1);
    }
}
<|endoftext|>


<commit_before>use std::env;

fn main() {
    let argc = env::args().count();

    if argc == 1 {
        loop {
            println!("y");
        }
    } else {
        loop {
            for i in 1..argc {
                match env::args().nth(i) {
                    Some(x) => print!("{}", x),
                    None => continue,
                }
            }

            print!("\n");
        }
    }
}
<commit_msg>use if let instead of matching<commit_after>use std::env;

fn main() {
    let arg_count = env::args().count();

    if arg_count == 1 {
        loop {
            println!("y");
        }
    } else {
        loop {
            for index in 1..arg_count {
                if let Some(arg) = env::args().nth(index) {
                    print!("{}", arg);
                }
            }

            print!("\n");
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::cmp;
use std::env;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::thread;

use chan;
use fst::{Streamer, raw};
use num_cpus;
use tempdir::TempDir;

use Error;

pub struct Merger<I> {
    it: I,
    output: PathBuf,
    value_merger: Option<Arc<Fn(u64, u64) -> u64 + Send + Sync + 'static>>,
    fd_limit: u32,
    batch_size: u32,
    threads: u32,
    tmp_dir: PathBuf,
    keep_tmp_dir: bool,
}

type KV = (String, u64);

impl<I> Merger<I>
where I: Iterator<Item=Result<(String, u64), Error>> + Send + 'static {
    pub fn new<T, P>(it: T, output: P) -> Self
            where P: AsRef<Path>,
                  T: IntoIterator<IntoIter=I, Item=I::Item> {
        Merger {
            it: it.into_iter(),
            output: output.as_ref().to_path_buf(),
            value_merger: None,
            fd_limit: 5,
            batch_size: 100_000,
            threads: num_cpus::get() as u32,
            tmp_dir: env::temp_dir(),
            keep_tmp_dir: false,
        }
    }

    pub fn value_merger<F>(mut self, f: F) -> Self
            where F: Fn(u64, u64) -> u64 + Send + Sync + 'static {
        self.value_merger = Some(Arc::new(f));
        self
    }

    pub fn fd_limit(mut self, fd_limit: u32) -> Self {
        self.fd_limit = fd_limit;
        self
    }

    pub fn batch_size(mut self, batch_size: u32) -> Self {
        self.batch_size = batch_size;
        self
    }

    pub fn threads(mut self, threads: u32) -> Self {
        self.threads = threads;
        self
    }

    pub fn tmp_dir<P: AsRef<Path>>(mut self, path: P) -> Self {
        self.tmp_dir = path.as_ref().to_path_buf();
        self
    }

    pub fn keep_tmp_dir(mut self, yes: bool) -> Self {
        self.keep_tmp_dir = yes;
        self
    }

    pub fn merge(self) -> Result<(), Error> {
        let tmp_dir = try!(TempDir::new_in(&self.tmp_dir, "rust-fst"));
        let tmp_dir_path = Arc::new(tmp_dir.path().to_path_buf());

        // Do the initial round of creating FSTs for every batch in the input.
        let batches = batcher(self.it, self.batch_size, self.threads);
        let sorters = Sorters::new(self.threads);
        for (i, kv_batch) in batches.into_iter().enumerate() {
            sorters.create_fst(KvBatch {
                tmp_dir: tmp_dir_path.clone(),
                index: i,
                kvs: try!(kv_batch),
            });
        }
        let mut results = sorters.results();

        // Nothing? Create an empty FST and be done with it.
        if results.is_empty() {
            let wtr = io::BufWriter::new(try!(File::create(&self.output)));
            let builder = try!(raw::Builder::new(wtr));
            try!(builder.finish());
            return Ok(());
        }

        // Now union batches of FSTs until only one remains.
        // That one is our final FST with all key/values.
        let mut gen = 0;
        while results.len() > 1 {
            let batches = batcher(results, self.fd_limit, self.threads);
            let sorters = Sorters::new(self.threads);
            for (i, union_batch) in batches.into_iter().enumerate() {
                sorters.create_fst(UnionBatch {
                    tmp_dir: tmp_dir_path.clone(),
                    gen: gen,
                    index: i,
                    fsts: try!(union_batch),
                    value_merger: self.value_merger.clone(),
                });
            }
            results = sorters.results();
            gen += 1;
        }
        assert_eq!(results.len(), 1);
        try!(fs::copy(try!(results.pop().unwrap()), &self.output));
        if self.keep_tmp_dir {
            drop(tmp_dir.into_path());
        }
        Ok(())
    }
}

fn batcher<I, T, IT>(
    it: I,
    batch_size: u32,
    threads: u32,
) -> chan::Receiver<Result<Vec<T>, Error>>
where T: Send + 'static,
      IT: Iterator<Item=Result<T, Error>> + Send + 'static,
      I: IntoIterator<IntoIter=IT, Item=IT::Item> + Send + 'static {
    let batch_size = batch_size as usize;
    let (send, recv) = chan::sync(cmp::min(1, threads as usize / 3));
    let it = it.into_iter();
    thread::spawn(move || {
        let mut batch = Vec::with_capacity(batch_size);
        for item in it {
            match item {
                Err(err) => {
                    send.send(Err(From::from(err)));
                    return;
                }
                Ok(item) => {
                    batch.push(item);
                    if batch.len() >= batch_size {
                        send.send(Ok(batch));
                        batch = Vec::with_capacity(batch_size);
                    }
                }
            }
        }
        if !batch.is_empty() {
            send.send(Ok(batch));
        }
    });
    recv
}

struct Sorters<B> {
    send: chan::Sender<B>,
    results: chan::Receiver<Vec<Result<PathBuf, Error>>>,
}

impl<B: Batchable + Send + 'static> Sorters<B> {
    fn new(threads: u32) -> Self {
        let (bsend, brecv) = chan::sync::<B>(0); // not sure why B is explicit
        let (rsend, rrecv) = chan::sync(0);
        for _ in 0..threads {
            let brecv = brecv.clone();
            let rsend = rsend.clone();
            thread::spawn(move || {
                let mut results = vec![];
                for mut batch in brecv {
                    results.push(batch.create_fst());
                }
                rsend.send(results);
            });
        }
        Sorters {
            send: bsend,
            results: rrecv,
        }
    }

    fn create_fst(&self, batch: B) {
        self.send.send(batch);
    }

    fn results(self) -> Vec<Result<PathBuf, Error>> {
        drop(self.send);
        let mut results = vec![];
        for rs in self.results {
            results.extend(rs);
        }
        results
    }
}

trait Batchable {
    fn create_fst(&mut self) -> Result<PathBuf, Error>;
}

struct KvBatch {
    tmp_dir: Arc<PathBuf>,
    index: usize,
    kvs: Vec<KV>,
}

impl Batchable for KvBatch {
    fn create_fst(&mut self) -> Result<PathBuf, Error> {
        self.kvs.sort();
        self.kvs.dedup();
        let file_name = format!("batch{}", self.index);
        let path = self.tmp_dir.join(file_name).to_path_buf();
        let wtr = io::BufWriter::new(try!(File::create(&path)));
        let mut builder = try!(raw::Builder::new(wtr));
        for &(ref k, v) in &self.kvs {
            try!(builder.insert(k, v));
        }
        try!(builder.finish());
        Ok(path)
    }
}

struct UnionBatch {
    tmp_dir: Arc<PathBuf>,
    gen: usize,
    index: usize,
    fsts: Vec<PathBuf>,
    value_merger: Option<Arc<Fn(u64, u64) -> u64 + Send + Sync + 'static>>,
}

impl Batchable for UnionBatch {
    fn create_fst(&mut self) -> Result<PathBuf, Error> {
        let file_name = format!("union-gen{}-batch{}", self.gen, self.index);
        let path = self.tmp_dir.join(file_name).to_path_buf();
        let wtr = io::BufWriter::new(try!(File::create(&path)));
        let mut builder = try!(raw::Builder::new(wtr));

        let mut fsts = vec![];
        for path in &self.fsts {
            fsts.push(try!(raw::Fst::from_path(path)));
        }
        let mut union = fsts.iter().collect::<raw::OpBuilder>().union();
        while let Some((key, outputs)) = union.next() {
            let mut merged = 0;
            if let Some(ref value_merger) = self.value_merger {
                merged = outputs.iter().fold(0, |merged, iv| {
                    value_merger(merged, iv.value)
                });
            }
            try!(builder.insert(key, merged));
        }
        try!(builder.finish());
        Ok(path)
    }
}
<commit_msg>Drop duplicate key errors.<commit_after>#![allow(dead_code)]

use std::cmp;
use std::env;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::thread;

use chan;
use fst::{self, Streamer, raw};
use num_cpus;
use tempdir::TempDir;

use Error;

pub struct Merger<I> {
    it: I,
    output: PathBuf,
    value_merger: Option<Arc<Fn(u64, u64) -> u64 + Send + Sync + 'static>>,
    fd_limit: u32,
    batch_size: u32,
    threads: u32,
    tmp_dir: PathBuf,
    keep_tmp_dir: bool,
}

type KV = (String, u64);

impl<I> Merger<I>
where I: Iterator<Item=Result<(String, u64), Error>> + Send + 'static {
    pub fn new<T, P>(it: T, output: P) -> Self
            where P: AsRef<Path>,
                  T: IntoIterator<IntoIter=I, Item=I::Item> {
        Merger {
            it: it.into_iter(),
            output: output.as_ref().to_path_buf(),
            value_merger: None,
            fd_limit: 5,
            batch_size: 100_000,
            threads: num_cpus::get() as u32,
            tmp_dir: env::temp_dir(),
            keep_tmp_dir: false,
        }
    }

    pub fn value_merger<F>(mut self, f: F) -> Self
            where F: Fn(u64, u64) -> u64 + Send + Sync + 'static {
        self.value_merger = Some(Arc::new(f));
        self
    }

    pub fn fd_limit(mut self, fd_limit: u32) -> Self {
        self.fd_limit = fd_limit;
        self
    }

    pub fn batch_size(mut self, batch_size: u32) -> Self {
        self.batch_size = batch_size;
        self
    }

    pub fn threads(mut self, threads: u32) -> Self {
        self.threads = threads;
        self
    }

    pub fn tmp_dir<P: AsRef<Path>>(mut self, path: P) -> Self {
        self.tmp_dir = path.as_ref().to_path_buf();
        self
    }

    pub fn keep_tmp_dir(mut self, yes: bool) -> Self {
        self.keep_tmp_dir = yes;
        self
    }

    pub fn merge(self) -> Result<(), Error> {
        let tmp_dir = try!(TempDir::new_in(&self.tmp_dir, "rust-fst"));
        let tmp_dir_path = Arc::new(tmp_dir.path().to_path_buf());

        // Do the initial round of creating FSTs for every batch in the input.
        let batches = batcher(self.it, self.batch_size, self.threads);
        let sorters = Sorters::new(self.threads);
        for (i, kv_batch) in batches.into_iter().enumerate() {
            sorters.create_fst(KvBatch {
                tmp_dir: tmp_dir_path.clone(),
                index: i,
                kvs: try!(kv_batch),
            });
        }
        let mut results = sorters.results();

        // Nothing? Create an empty FST and be done with it.
        if results.is_empty() {
            let wtr = io::BufWriter::new(try!(File::create(&self.output)));
            let builder = try!(raw::Builder::new(wtr));
            try!(builder.finish());
            return Ok(());
        }

        // Now union batches of FSTs until only one remains.
        // That one is our final FST with all key/values.
        let mut gen = 0;
        while results.len() > 1 {
            let batches = batcher(results, self.fd_limit, self.threads);
            let sorters = Sorters::new(self.threads);
            for (i, union_batch) in batches.into_iter().enumerate() {
                sorters.create_fst(UnionBatch {
                    tmp_dir: tmp_dir_path.clone(),
                    gen: gen,
                    index: i,
                    fsts: try!(union_batch),
                    value_merger: self.value_merger.clone(),
                });
            }
            results = sorters.results();
            gen += 1;
        }
        assert_eq!(results.len(), 1);
        try!(fs::copy(try!(results.pop().unwrap()), &self.output));
        if self.keep_tmp_dir {
            drop(tmp_dir.into_path());
        }
        Ok(())
    }
}

fn batcher<I, T, IT>(
    it: I,
    batch_size: u32,
    threads: u32,
) -> chan::Receiver<Result<Vec<T>, Error>>
where T: Send + 'static,
      IT: Iterator<Item=Result<T, Error>> + Send + 'static,
      I: IntoIterator<IntoIter=IT, Item=IT::Item> + Send + 'static {
    let batch_size = batch_size as usize;
    let (send, recv) = chan::sync(cmp::min(1, threads as usize / 3));
    let it = it.into_iter();
    thread::spawn(move || {
        let mut batch = Vec::with_capacity(batch_size);
        for item in it {
            match item {
                Err(err) => {
                    send.send(Err(From::from(err)));
                    return;
                }
                Ok(item) => {
                    batch.push(item);
                    if batch.len() >= batch_size {
                        send.send(Ok(batch));
                        batch = Vec::with_capacity(batch_size);
                    }
                }
            }
        }
        if !batch.is_empty() {
            send.send(Ok(batch));
        }
    });
    recv
}

struct Sorters<B> {
    send: chan::Sender<B>,
    results: chan::Receiver<Vec<Result<PathBuf, Error>>>,
}

impl<B: Batchable + Send + 'static> Sorters<B> {
    fn new(threads: u32) -> Self {
        let (bsend, brecv) = chan::sync::<B>(0); // not sure why B is explicit
        let (rsend, rrecv) = chan::sync(0);
        for _ in 0..threads {
            let brecv = brecv.clone();
            let rsend = rsend.clone();
            thread::spawn(move || {
                let mut results = vec![];
                for mut batch in brecv {
                    results.push(batch.create_fst());
                }
                rsend.send(results);
            });
        }
        Sorters {
            send: bsend,
            results: rrecv,
        }
    }

    fn create_fst(&self, batch: B) {
        self.send.send(batch);
    }

    fn results(self) -> Vec<Result<PathBuf, Error>> {
        drop(self.send);
        let mut results = vec![];
        for rs in self.results {
            results.extend(rs);
        }
        results
    }
}

trait Batchable {
    fn create_fst(&mut self) -> Result<PathBuf, Error>;
}

struct KvBatch {
    tmp_dir: Arc<PathBuf>,
    index: usize,
    kvs: Vec<KV>,
}

impl Batchable for KvBatch {
    fn create_fst(&mut self) -> Result<PathBuf, Error> {
        self.kvs.sort();
        self.kvs.dedup();
        let file_name = format!("batch{}", self.index);
        let path = self.tmp_dir.join(file_name).to_path_buf();
        let wtr = io::BufWriter::new(try!(File::create(&path)));
        let mut builder = try!(raw::Builder::new(wtr));
        for &(ref k, v) in &self.kvs {
            match builder.insert(k, v) {
                Ok(_) => {}
                Err(fst::Error::Fst(fst::raw::Error::DuplicateKey { .. })) => {}
                Err(err) => return Err(From::from(err)),
            }
        }
        try!(builder.finish());
        Ok(path)
    }
}

struct UnionBatch {
    tmp_dir: Arc<PathBuf>,
    gen: usize,
    index: usize,
    fsts: Vec<PathBuf>,
    value_merger: Option<Arc<Fn(u64, u64) -> u64 + Send + Sync + 'static>>,
}

impl Batchable for UnionBatch {
    fn create_fst(&mut self) -> Result<PathBuf, Error> {
        let file_name = format!("union-gen{}-batch{}", self.gen, self.index);
        let path = self.tmp_dir.join(file_name).to_path_buf();
        let wtr = io::BufWriter::new(try!(File::create(&path)));
        let mut builder = try!(raw::Builder::new(wtr));

        let mut fsts = vec![];
        for path in &self.fsts {
            fsts.push(try!(raw::Fst::from_path(path)));
        }
        let mut union = fsts.iter().collect::<raw::OpBuilder>().union();
        while let Some((key, outputs)) = union.next() {
            let mut merged = 0;
            if let Some(ref value_merger) = self.value_merger {
                merged = outputs.iter().fold(0, |merged, iv| {
                    value_merger(merged, iv.value)
                });
            }
            try!(builder.insert(key, merged));
        }
        try!(builder.finish());
        Ok(path)
    }
}
<|endoftext|>


<commit_before>#![recursion_limit = "256"]

extern crate ape;
extern crate app_dirs;
extern crate base64;
extern crate core;
extern crate crypto;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_migrations;
#[macro_use]
extern crate error_chain;
extern crate getopts;
extern crate hyper;
extern crate id3;
extern crate image;
extern crate iron;
extern crate lewton;
extern crate md5;
extern crate metaflac;
extern crate mount;
extern crate mp3_duration;
extern crate params;
extern crate rand;
extern crate regex;
extern crate reqwest;
extern crate ring;
extern crate router;
extern crate rustfm_scrobble;
extern crate secure_session;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate staticfile;
extern crate toml;
extern crate typemap;
extern crate url;
#[macro_use]
extern crate log;
extern crate simplelog;

#[cfg(windows)]
extern crate uuid;
#[cfg(windows)]
extern crate winapi;

#[cfg(unix)]
extern crate unix_daemonize;

#[cfg(unix)]
use std::fs::File;
#[cfg(unix)]
use std::io::prelude::*;
#[cfg(unix)]
use unix_daemonize::{daemonize_redirect, ChdirMode};

use core::ops::Deref;
use errors::*;
use getopts::Options;
use iron::prelude::*;
use mount::Mount;
#[cfg(unix)]
use simplelog::SimpleLogger;
use simplelog::{Level, LevelFilter, TermLogger};
use staticfile::Static;
use std::path::Path;
use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};

mod api;
mod config;
mod db;
mod ddns;
mod errors;
mod index;
mod lastfm;
mod metadata;
mod playlist;
mod serve;
mod thumbnails;
mod ui;
mod user;
mod utils;
mod vfs;

static LOG_CONFIG: simplelog::Config = simplelog::Config {
	time: Some(Level::Error),
	level: Some(Level::Error),
	target: Some(Level::Error),
	location: Some(Level::Error),
	time_format: None,
};

fn main() {
	if let Err(ref e) = run() {
		println!("Error: {}", e);

		for e in e.iter().skip(1) {
			println!("caused by: {}", e);
		}
		if let Some(backtrace) = e.backtrace() {
			println!("backtrace: {:?}", backtrace);
		}
		::std::process::exit(1);
	}
}

#[cfg(unix)]
fn daemonize(options: &getopts::Matches) -> Result<()> {
	if options.opt_present("f") {
		return Ok(());
	}
	let mut log_file = utils::get_data_root()?;
	log_file.push("polaris.log");
	let pid = match daemonize_redirect(Some(&log_file), Some(&log_file), ChdirMode::NoChdir) {
		Ok(p) => p,
		Err(_) => bail!(ErrorKind::DaemonError),
	};
	let mut pid_path = utils::get_data_root()?;
	pid_path.push("polaris.pid");
	let mut file = File::create(pid_path)?;
	file.write_all(pid.to_string().as_bytes())?;
	Ok(())
}

#[cfg(unix)]
fn init_log(log_level: LevelFilter, options: &getopts::Matches) -> Result<()> {
	if options.opt_present("f") {
		if let Err(e) = TermLogger::init(log_level, LOG_CONFIG) {
			bail!("Error starting terminal logger: {}", e);
		};
	} else {
		if let Err(e) = SimpleLogger::init(log_level, LOG_CONFIG) {
			bail!("Error starting simple logger: {}", e);
		}
	}
	Ok(())
}

#[cfg(windows)]
fn init_log(log_level: LevelFilter, _: &getopts::Matches) -> Result<()> {
	if let Err(e) = TermLogger::init(log_level, LOG_CONFIG) {
		bail!("Error starting terminal logger: {}", e);
	};
	Ok(())
}

fn run() -> Result<()> {
	// Parse CLI options
	let args: Vec<String> = std::env::args().collect();
	let mut options = Options::new();
	options.optopt("c", "config", "set the configuration file", "FILE");
	options.optopt("p", "port", "set polaris to run on a custom port", "PORT");
	options.optopt("d", "database", "set the path to index database", "FILE");
	options.optopt("w", "web", "set the path to web client files", "DIRECTORY");
	options.optopt(
		"l",
		"log",
		"set the log level to a value between 0 (off) and 3 (debug)",
		"LEVEL",
	);

	#[cfg(unix)]
	options.optflag(
		"f",
		"foreground",
		"run polaris in the foreground instead of daemonizing",
	);

	options.optflag("h", "help", "print this help menu");

	let matches = options.parse(&args[1..])?;

	if matches.opt_present("h") {
		let program = args[0].clone();
		let brief = format!("Usage: {} [options]", program);
		print!("{}", options.usage(&brief));
		return Ok(());
	}

	let log_level = match matches.opt_str("l").as_ref().map(String::as_ref) {
		Some("0") => LevelFilter::Off,
		Some("1") => LevelFilter::Error,
		Some("2") => LevelFilter::Info,
		Some("3") => LevelFilter::Debug,
		_ => LevelFilter::Info,
	};

	init_log(log_level, &matches)?;

	#[cfg(unix)]
	daemonize(&matches)?;

	// Init DB
	info!("Starting up database");
	let db_path = matches.opt_str("d");
	let mut default_db_path = utils::get_data_root()?;
	default_db_path.push("db.sqlite");
	let db_path = db_path
		.map(|n| Path::new(n.as_str()).to_path_buf())
		.unwrap_or(default_db_path);
	let db = Arc::new(db::DB::new(&db_path)?);

	// Parse config
	let config_file_name = matches.opt_str("c");
	let config_file_path = config_file_name.map(|p| Path::new(p.as_str()).to_path_buf());
	if let Some(path) = config_file_path {
		let config = config::parse_toml_file(&path)?;
		config::overwrite(db.deref(), &config)?;
	}
	let config = config::read(db.deref())?;

	// Init index
	let (index_sender, index_receiver) = channel();
	let index_sender = Arc::new(Mutex::new(index_sender));
	let db_ref = db.clone();
	std::thread::spawn(move || {
		let db = db_ref.deref();
		index::update_loop(db, &index_receiver);
	});

	// Trigger auto-indexing
	let db_ref = db.clone();
	let sender_ref = index_sender.clone();
	std::thread::spawn(move || {
		index::self_trigger(db_ref.deref(), &sender_ref);
	});

	// Mount API
	let prefix_url = config.prefix_url.unwrap_or_else(|| "".to_string());
	let api_url = format!("{}/api", &prefix_url);
	info!("Mounting API on {}", api_url);
	let mut mount = Mount::new();
	let handler = api::get_handler(&db.clone(), &index_sender)?;
	mount.mount(&api_url, handler);

	// Mount static files
	let static_url = format!("/{}", &prefix_url);

	info!("Mounting static files on {}", static_url);
	let web_dir_name = matches.opt_str("w");
	let mut default_web_dir = utils::get_data_root()?;
	default_web_dir.push("web");
	let web_dir_path = web_dir_name
		.map(|n| Path::new(n.as_str()).to_path_buf())
		.unwrap_or(default_web_dir);

	mount.mount(&static_url, Static::new(web_dir_path));

	info!("Starting up server");
	let port: u16 = matches
		.opt_str("p")
		.unwrap_or_else(|| "5050".to_owned())
		.parse()
		.or(Err("invalid port number"))?;

	let mut server = match Iron::new(mount).http(("0.0.0.0", port)) {
		Ok(s) => s,
		Err(e) => bail!("Error starting up server: {}", e),
	};

	// Start DDNS updates
	let db_ref = db.clone();
	std::thread::spawn(move || {
		ddns::run(db_ref.deref());
	});

	// Run UI
	ui::run();

	info!("Shutting down server");
	if let Err(e) = server.close() {
		bail!("Error shutting down server: {}", e);
	}

	Ok(())
}
<commit_msg>Log static web files location<commit_after>#![recursion_limit = "256"]

extern crate ape;
extern crate app_dirs;
extern crate base64;
extern crate core;
extern crate crypto;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_migrations;
#[macro_use]
extern crate error_chain;
extern crate getopts;
extern crate hyper;
extern crate id3;
extern crate image;
extern crate iron;
extern crate lewton;
extern crate md5;
extern crate metaflac;
extern crate mount;
extern crate mp3_duration;
extern crate params;
extern crate rand;
extern crate regex;
extern crate reqwest;
extern crate ring;
extern crate router;
extern crate rustfm_scrobble;
extern crate secure_session;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate staticfile;
extern crate toml;
extern crate typemap;
extern crate url;
#[macro_use]
extern crate log;
extern crate simplelog;

#[cfg(windows)]
extern crate uuid;
#[cfg(windows)]
extern crate winapi;

#[cfg(unix)]
extern crate unix_daemonize;

#[cfg(unix)]
use std::fs::File;
#[cfg(unix)]
use std::io::prelude::*;
#[cfg(unix)]
use unix_daemonize::{daemonize_redirect, ChdirMode};

use core::ops::Deref;
use errors::*;
use getopts::Options;
use iron::prelude::*;
use mount::Mount;
#[cfg(unix)]
use simplelog::SimpleLogger;
use simplelog::{Level, LevelFilter, TermLogger};
use staticfile::Static;
use std::path::Path;
use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};

mod api;
mod config;
mod db;
mod ddns;
mod errors;
mod index;
mod lastfm;
mod metadata;
mod playlist;
mod serve;
mod thumbnails;
mod ui;
mod user;
mod utils;
mod vfs;

static LOG_CONFIG: simplelog::Config = simplelog::Config {
	time: Some(Level::Error),
	level: Some(Level::Error),
	target: Some(Level::Error),
	location: Some(Level::Error),
	time_format: None,
};

fn main() {
	if let Err(ref e) = run() {
		println!("Error: {}", e);

		for e in e.iter().skip(1) {
			println!("caused by: {}", e);
		}
		if let Some(backtrace) = e.backtrace() {
			println!("backtrace: {:?}", backtrace);
		}
		::std::process::exit(1);
	}
}

#[cfg(unix)]
fn daemonize(options: &getopts::Matches) -> Result<()> {
	if options.opt_present("f") {
		return Ok(());
	}
	let mut log_file = utils::get_data_root()?;
	log_file.push("polaris.log");
	let pid = match daemonize_redirect(Some(&log_file), Some(&log_file), ChdirMode::NoChdir) {
		Ok(p) => p,
		Err(_) => bail!(ErrorKind::DaemonError),
	};
	let mut pid_path = utils::get_data_root()?;
	pid_path.push("polaris.pid");
	let mut file = File::create(pid_path)?;
	file.write_all(pid.to_string().as_bytes())?;
	Ok(())
}

#[cfg(unix)]
fn init_log(log_level: LevelFilter, options: &getopts::Matches) -> Result<()> {
	if options.opt_present("f") {
		if let Err(e) = TermLogger::init(log_level, LOG_CONFIG) {
			bail!("Error starting terminal logger: {}", e);
		};
	} else {
		if let Err(e) = SimpleLogger::init(log_level, LOG_CONFIG) {
			bail!("Error starting simple logger: {}", e);
		}
	}
	Ok(())
}

#[cfg(windows)]
fn init_log(log_level: LevelFilter, _: &getopts::Matches) -> Result<()> {
	if let Err(e) = TermLogger::init(log_level, LOG_CONFIG) {
		bail!("Error starting terminal logger: {}", e);
	};
	Ok(())
}

fn run() -> Result<()> {
	// Parse CLI options
	let args: Vec<String> = std::env::args().collect();
	let mut options = Options::new();
	options.optopt("c", "config", "set the configuration file", "FILE");
	options.optopt("p", "port", "set polaris to run on a custom port", "PORT");
	options.optopt("d", "database", "set the path to index database", "FILE");
	options.optopt("w", "web", "set the path to web client files", "DIRECTORY");
	options.optopt(
		"l",
		"log",
		"set the log level to a value between 0 (off) and 3 (debug)",
		"LEVEL",
	);

	#[cfg(unix)]
	options.optflag(
		"f",
		"foreground",
		"run polaris in the foreground instead of daemonizing",
	);

	options.optflag("h", "help", "print this help menu");

	let matches = options.parse(&args[1..])?;

	if matches.opt_present("h") {
		let program = args[0].clone();
		let brief = format!("Usage: {} [options]", program);
		print!("{}", options.usage(&brief));
		return Ok(());
	}

	let log_level = match matches.opt_str("l").as_ref().map(String::as_ref) {
		Some("0") => LevelFilter::Off,
		Some("1") => LevelFilter::Error,
		Some("2") => LevelFilter::Info,
		Some("3") => LevelFilter::Debug,
		_ => LevelFilter::Info,
	};

	init_log(log_level, &matches)?;

	#[cfg(unix)]
	daemonize(&matches)?;

	// Init DB
	info!("Starting up database");
	let db_path = matches.opt_str("d");
	let mut default_db_path = utils::get_data_root()?;
	default_db_path.push("db.sqlite");
	let db_path = db_path
		.map(|n| Path::new(n.as_str()).to_path_buf())
		.unwrap_or(default_db_path);
	let db = Arc::new(db::DB::new(&db_path)?);

	// Parse config
	let config_file_name = matches.opt_str("c");
	let config_file_path = config_file_name.map(|p| Path::new(p.as_str()).to_path_buf());
	if let Some(path) = config_file_path {
		let config = config::parse_toml_file(&path)?;
		config::overwrite(db.deref(), &config)?;
	}
	let config = config::read(db.deref())?;

	// Init index
	let (index_sender, index_receiver) = channel();
	let index_sender = Arc::new(Mutex::new(index_sender));
	let db_ref = db.clone();
	std::thread::spawn(move || {
		let db = db_ref.deref();
		index::update_loop(db, &index_receiver);
	});

	// Trigger auto-indexing
	let db_ref = db.clone();
	let sender_ref = index_sender.clone();
	std::thread::spawn(move || {
		index::self_trigger(db_ref.deref(), &sender_ref);
	});

	// Mount API
	let prefix_url = config.prefix_url.unwrap_or_else(|| "".to_string());
	let api_url = format!("{}/api", &prefix_url);
	info!("Mounting API on {}", api_url);
	let mut mount = Mount::new();
	let handler = api::get_handler(&db.clone(), &index_sender)?;
	mount.mount(&api_url, handler);

	// Mount static files
	let web_dir_name = matches.opt_str("w");
	let mut default_web_dir = utils::get_data_root()?;
	default_web_dir.push("web");
	let web_dir_path = web_dir_name
		.map(|n| Path::new(n.as_str()).to_path_buf())
		.unwrap_or(default_web_dir);
	info!("Static files location is {}", web_dir_path.display());
	let static_url = format!("/{}", &prefix_url);
	info!("Mounting static files on {}", static_url);
	mount.mount(&static_url, Static::new(web_dir_path));

	info!("Starting up server");
	let port: u16 = matches
		.opt_str("p")
		.unwrap_or_else(|| "5050".to_owned())
		.parse()
		.or(Err("invalid port number"))?;

	let mut server = match Iron::new(mount).http(("0.0.0.0", port)) {
		Ok(s) => s,
		Err(e) => bail!("Error starting up server: {}", e),
	};

	// Start DDNS updates
	let db_ref = db.clone();
	std::thread::spawn(move || {
		ddns::run(db_ref.deref());
	});

	// Run UI
	ui::run();

	info!("Shutting down server");
	if let Err(e) = server.close() {
		bail!("Error shutting down server: {}", e);
	}

	Ok(())
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![feature(scoped)]
#![plugin(quickcheck_macros)]
#![feature(convert)]
#[macro_use] extern crate log;
extern crate env_logger;
extern crate yak_client;
extern crate capnp;
extern crate log4rs;
#[cfg(test)]
extern crate quickcheck;

use std::default::Default;
use std::net::{TcpListener, TcpStream};
use std::thread;
use std::io::{self,Read,Write};
use std::fmt;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;
use std::clone::Clone;
use std::error::Error;

use yak_client::{WireProtocol,Request,Response,Operation,Datum,YakError};

#[macro_use] mod store;
mod mem_store;

#[derive(Debug)]
enum ServerError {
  CapnpError(capnp::Error),
  CapnpNotInSchema(capnp::NotInSchema),
  IoError(std::io::Error),
  DownstreamError(YakError)
}

impl fmt::Display for ServerError {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match self {
      &ServerError::CapnpError(ref e) => e.fmt(f),
      &ServerError::CapnpNotInSchema(ref e) => e.fmt(f),
      &ServerError::IoError(ref e) => e.fmt(f),
      &ServerError::DownstreamError(ref e) => e.fmt(f)
    }
  }
}

impl Error for ServerError {
  fn description(&self) -> &str {
    match self {
      &ServerError::CapnpError(ref e) => e.description(),
      &ServerError::CapnpNotInSchema(ref e) => e.description(),
      &ServerError::IoError(ref e) => e.description(),
      &ServerError::DownstreamError(ref e) => e.description()
    }
  }
}

struct DownStream<S: Read+Write> {
  protocol: Arc<Mutex<WireProtocol<S>>>,
}

impl <S: ::std::fmt::Debug + Read + Write> ::std::fmt::Debug for DownStream<S>
 where S: ::std::fmt::Debug + 'static {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match self {
            &DownStream { protocol: ref proto } =>
            fmt.debug_struct("DownStream").field("protocol",
                                                     (proto)).finish(),
        }
    }
}

impl<S> Clone for DownStream<S> where S: Read+Write {
  fn clone(&self) -> DownStream<S> {
    DownStream { protocol: self.protocol.clone() }
  }
}

static LOG_FILE: &'static str = "log.toml";

pub fn main() {
  if let Err(e) = log4rs::init_file(LOG_FILE, Default::default()) {
    panic!("Could not init logger from file {}: {}", LOG_FILE, e);
  }

  match do_run() {
    Ok(()) => info!("Terminated normally"),
    Err(e) => panic!("Failed: {}", e),
  }
}

fn do_run() -> Result<(), ServerError> {
  let mut a = std::env::args().skip(1);
  let local : String = a.next().unwrap();
  let next = match a.next() {
      Some(ref addr) => Some(try!(DownStream::new(addr))),
      None => None
  };

  let listener = TcpListener::bind(local.as_str()).unwrap();
  info!("listening started on {}, ready to accept", local);
  let store = mem_store::MemStore::new();
  for stream in listener.incoming() {
    let next = next.clone();
    let store = store.clone();
    let sock = stream.unwrap();
    let peer = sock.peer_addr().unwrap();
    let _ = try!(thread::Builder::new().name(format!("client-{}", peer)).spawn(move || {
	debug!("Accept stream from {:?}", peer);
        match Session::new(peer, sock, store, next).process_requests() {
          Err(e) => panic!("Processing requests failed: {}", e),
          _ => ()
        }
      }));
  }
  Ok(())
}

impl DownStream<TcpStream> {
  fn new(addr: &str) -> Result<DownStream<TcpStream>, ServerError> {
    debug!("Connect downstream: {:?}", addr);
    let proto = try!(WireProtocol::connect(addr));
    debug!("Connected downstream: {:?}", proto);

    Ok(DownStream { protocol: Arc::new(Mutex::new(proto)) })
  }

}
impl<S: Read+Write> DownStream<S> {
  fn handle(&self, msg: &Request) -> Result<Response, ServerError> {
    let mut wire = self.protocol.lock().unwrap();
    trace!("Downstream: -> {:?}", msg);
    try!(wire.send(msg));
    let resp = try!(wire.read::<Response>());
    trace!("Downstream: <- {:?}", resp);
    resp.map(Ok).unwrap_or(Err(ServerError::DownstreamError(YakError::ProtocolError)))
  }
}

struct Session<Id, S:Read+Write+'static, ST> {
  id: Id,
  protocol: WireProtocol<S>,
  store: ST,
  next: Option<DownStream<S>>
}

impl<Id: fmt::Display, S: Read+Write, ST:store::Store> Session<Id, S, ST> {
  fn new(id: Id, conn: S, store: ST, next: Option<DownStream<S>>) -> Session<Id, S, ST> {
    Session {
    	id: id,
	protocol: WireProtocol::new(conn),
	store: store,
	next: next
    }
  }

  fn process_requests(&mut self) -> Result<(), ServerError> {
    trace!("{}: Waiting for message", self.id);
    while let Some(msg) = try!(self.protocol.read::<Request>()) {
      try!(self.process_one(msg));
    }

    Ok(())
  }

  fn process_one(&mut self, msg: Request) -> Result<(), ServerError> {
    trace!("{}: Handle message: {:?}", self.id, msg);

    let resp = match msg.operation {
      Operation::Truncate => {
        let resp = try!(self.truncate(&msg.space));
        try!(self.send_downstream_or(&msg, resp))
      },
        Operation::Write { ref key, ref value } => {
          let resp = try!(self.write(&msg.space, &key, &value));
          try!(self.send_downstream_or(&msg, resp))
        },
        Operation::Read { key } =>
          try!(self.read(&msg.space, &key)),
      Operation::Subscribe => {
        try!(self.subscribe(&msg.space));
        Response::Okay
      },
    };

    trace!("Response: {:?}", resp);

    try!(self.protocol.send(&resp));
    Ok(())
  }

  fn send_downstream_or(&self, msg: &Request, default: Response) -> Result<Response, ServerError> {
    match self.next {
      Some(ref d) => d.handle(msg),
      None => Ok(default),
    }
  }

  fn truncate(&self, space: &str) -> Result<Response, ServerError> {
    trace!("{}/{:?}: truncate", self.id, space);
    self.store.truncate(space);
    Ok(Response::Okay)
  }

  fn read(&self, space: &str, key: &[u8]) -> Result<Response, ServerError> {
    let val = self.store.read(space, key);
    trace!("{}/{:?}: read:{:?}: -> {:?}", self.id, space, key, val);
    let data = val.iter().map(|c| Datum { key: Vec::new(), content: c.clone() }).collect();
    Ok(Response::OkayData(data))
  }

  fn write(&self, space: &str, key: &[u8], val: &[u8]) -> Result<Response, ServerError> {
    trace!("{}/{:?}: write:{:?} -> {:?}", self.id, space, key, val);
    self.store.write(space, key, val);
    Ok(Response::Okay)
  }
  fn subscribe(&mut self, space: &str) -> Result<(), ServerError> {
    try!(self.protocol.send(&Response::Okay));
    for d in self.store.subscribe(space) {
      try!(self.protocol.send(&Response::Delivery(d)));
    }
    Ok(())
  }
}

impl From<capnp::Error> for ServerError {
  fn from(err: capnp::Error) -> ServerError {
    ServerError::CapnpError(err)
  }
}

impl From<capnp::NotInSchema> for ServerError {
  fn from(err: capnp::NotInSchema) -> ServerError {
    ServerError::CapnpNotInSchema(err)
  }
}

impl From<io::Error> for ServerError {
  fn from(err: io::Error) -> ServerError {
    ServerError::IoError(err)
  }
}

impl From<YakError> for ServerError {
  fn from(err: YakError) -> ServerError {
    ServerError::DownstreamError(err)
  }
}
<commit_msg>Report errors with causes.<commit_after>#![feature(plugin)]
#![feature(scoped)]
#![plugin(quickcheck_macros)]
#![feature(convert)]
#[macro_use] extern crate log;
extern crate env_logger;
extern crate yak_client;
extern crate capnp;
extern crate log4rs;
#[cfg(test)]
extern crate quickcheck;

use std::default::Default;
use std::net::{TcpListener, TcpStream};
use std::thread;
use std::io::{self,Read,Write};
use std::fmt;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;
use std::clone::Clone;
use std::error::Error;

use yak_client::{WireProtocol,Request,Response,Operation,Datum,YakError};

#[macro_use] mod store;
mod mem_store;

#[derive(Debug)]
enum ServerError {
  CapnpError(capnp::Error),
  CapnpNotInSchema(capnp::NotInSchema),
  IoError(std::io::Error),
  DownstreamError(YakError)
}

impl fmt::Display for ServerError {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match self {
      &ServerError::CapnpError(ref e) => e.fmt(f),
      &ServerError::CapnpNotInSchema(ref e) => e.fmt(f),
      &ServerError::IoError(ref e) => e.fmt(f),
      &ServerError::DownstreamError(ref e) => e.fmt(f)
    }
  }
}

impl Error for ServerError {
  fn description(&self) -> &str {
    match self {
      &ServerError::CapnpError(ref e) => e.description(),
      &ServerError::CapnpNotInSchema(ref e) => e.description(),
      &ServerError::IoError(ref e) => e.description(),
      &ServerError::DownstreamError(ref e) => e.description()
    }
  }
}

struct DownStream<S: Read+Write> {
  protocol: Arc<Mutex<WireProtocol<S>>>,
}

impl <S: ::std::fmt::Debug + Read + Write> ::std::fmt::Debug for DownStream<S>
 where S: ::std::fmt::Debug + 'static {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match self {
            &DownStream { protocol: ref proto } =>
            fmt.debug_struct("DownStream").field("protocol",
                                                     (proto)).finish(),
        }
    }
}

impl<S> Clone for DownStream<S> where S: Read+Write {
  fn clone(&self) -> DownStream<S> {
    DownStream { protocol: self.protocol.clone() }
  }
}

static LOG_FILE: &'static str = "log.toml";

pub fn main() {
  if let Err(e) = log4rs::init_file(LOG_FILE, Default::default()) {
    panic!("Could not init logger from file {}: {}", LOG_FILE, e);
  }

  match do_run() {
    Ok(()) => info!("Terminated normally"),
    Err(e) => panic!("Failed: {}", e),
  }
}

fn do_run() -> Result<(), ServerError> {
  let mut a = std::env::args().skip(1);
  let local : String = a.next().unwrap();
  let next = match a.next() {
      Some(ref addr) => Some(try!(DownStream::new(addr))),
      None => None
  };

  let listener = TcpListener::bind(local.as_str()).unwrap();
  info!("listening started on {}, ready to accept", local);
  let store = mem_store::MemStore::new();
  for stream in listener.incoming() {
    let next = next.clone();
    let store = store.clone();
    let sock = stream.unwrap();
    let peer = sock.peer_addr().unwrap();
    let _ = try!(thread::Builder::new().name(format!("client-{}", peer)).spawn(move || {
	debug!("Accept stream from {:?}", peer);
        match Session::new(peer, sock, store, next).process_requests() {
          Err(e) => report_errors(&e),
          _ => ()
        }
      }));
  }
  Ok(())
}

fn report_errors(error: &Error) {
  error!("Error: {}", error);
  while let Some(error) = error.cause() {
    error!("\tCaused by: {}", error);
  }
}

impl DownStream<TcpStream> {
  fn new(addr: &str) -> Result<DownStream<TcpStream>, ServerError> {
    debug!("Connect downstream: {:?}", addr);
    let proto = try!(WireProtocol::connect(addr));
    debug!("Connected downstream: {:?}", proto);

    Ok(DownStream { protocol: Arc::new(Mutex::new(proto)) })
  }

}
impl<S: Read+Write> DownStream<S> {
  fn handle(&self, msg: &Request) -> Result<Response, ServerError> {
    let mut wire = self.protocol.lock().unwrap();
    trace!("Downstream: -> {:?}", msg);
    try!(wire.send(msg));
    let resp = try!(wire.read::<Response>());
    trace!("Downstream: <- {:?}", resp);
    resp.map(Ok).unwrap_or(Err(ServerError::DownstreamError(YakError::ProtocolError)))
  }
}

struct Session<Id, S:Read+Write+'static, ST> {
  id: Id,
  protocol: WireProtocol<S>,
  store: ST,
  next: Option<DownStream<S>>
}

impl<Id: fmt::Display, S: Read+Write, ST:store::Store> Session<Id, S, ST> {
  fn new(id: Id, conn: S, store: ST, next: Option<DownStream<S>>) -> Session<Id, S, ST> {
    Session {
    	id: id,
	protocol: WireProtocol::new(conn),
	store: store,
	next: next
    }
  }

  fn process_requests(&mut self) -> Result<(), ServerError> {
    trace!("{}: Waiting for message", self.id);
    while let Some(msg) = try!(self.protocol.read::<Request>()) {
      try!(self.process_one(msg));
    }

    Ok(())
  }

  fn process_one(&mut self, msg: Request) -> Result<(), ServerError> {
    trace!("{}: Handle message: {:?}", self.id, msg);

    let resp = match msg.operation {
      Operation::Truncate => {
        let resp = try!(self.truncate(&msg.space));
        try!(self.send_downstream_or(&msg, resp))
      },
        Operation::Write { ref key, ref value } => {
          let resp = try!(self.write(&msg.space, &key, &value));
          try!(self.send_downstream_or(&msg, resp))
        },
        Operation::Read { key } =>
          try!(self.read(&msg.space, &key)),
      Operation::Subscribe => {
        try!(self.subscribe(&msg.space));
        Response::Okay
      },
    };

    trace!("Response: {:?}", resp);

    try!(self.protocol.send(&resp));
    Ok(())
  }

  fn send_downstream_or(&self, msg: &Request, default: Response) -> Result<Response, ServerError> {
    match self.next {
      Some(ref d) => d.handle(msg),
      None => Ok(default),
    }
  }

  fn truncate(&self, space: &str) -> Result<Response, ServerError> {
    trace!("{}/{:?}: truncate", self.id, space);
    self.store.truncate(space);
    Ok(Response::Okay)
  }

  fn read(&self, space: &str, key: &[u8]) -> Result<Response, ServerError> {
    let val = self.store.read(space, key);
    trace!("{}/{:?}: read:{:?}: -> {:?}", self.id, space, key, val);
    let data = val.iter().map(|c| Datum { key: Vec::new(), content: c.clone() }).collect();
    Ok(Response::OkayData(data))
  }

  fn write(&self, space: &str, key: &[u8], val: &[u8]) -> Result<Response, ServerError> {
    trace!("{}/{:?}: write:{:?} -> {:?}", self.id, space, key, val);
    self.store.write(space, key, val);
    Ok(Response::Okay)
  }
  fn subscribe(&mut self, space: &str) -> Result<(), ServerError> {
    try!(self.protocol.send(&Response::Okay));
    for d in self.store.subscribe(space) {
      try!(self.protocol.send(&Response::Delivery(d)));
    }
    Ok(())
  }
}

impl From<capnp::Error> for ServerError {
  fn from(err: capnp::Error) -> ServerError {
    ServerError::CapnpError(err)
  }
}

impl From<capnp::NotInSchema> for ServerError {
  fn from(err: capnp::NotInSchema) -> ServerError {
    ServerError::CapnpNotInSchema(err)
  }
}

impl From<io::Error> for ServerError {
  fn from(err: io::Error) -> ServerError {
    ServerError::IoError(err)
  }
}

impl From<YakError> for ServerError {
  fn from(err: YakError) -> ServerError {
    ServerError::DownstreamError(err)
  }
}
<|endoftext|>


<commit_before>use gl;
use mandelbrot::Mandelbrot;
use std::io::timer;
use std::mem;
use std::time::duration::Duration;
use sdl2;
use sdl2::event::Event;
use sdl2::keycode::KeyCode;
use sdl2::mouse::Mouse;
use stopwatch::TimerSet;
use yaglw::gl_context::{GLContext, GLContextExistence};
use yaglw::shader::Shader;
use yaglw::vertex_buffer::{GLArray, GLBuffer, GLType, VertexAttribData, DrawMode};

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

#[repr(C)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

pub fn main() {
  let timers = TimerSet::new();

  let window = make_window();

  let _sdl_gl_context = window.gl_create_context().unwrap();

  // Load the OpenGL function pointers.
  gl::load_with(|s| unsafe {
    mem::transmute(sdl2::video::gl_get_proc_address(s))
  });

  let (gl, mut gl_context) = unsafe {
    GLContext::new()
  };

  match gl_context.get_error() {
    gl::NO_ERROR => {},
    err => {
      println!("OpenGL error 0x{:x} in setup", err);
      return;
    },
  }

  let shader = make_shader(&gl);
  shader.use_shader(&mut gl_context);

  let mut vao = make_vao(&gl, &mut gl_context, &shader);
  vao.bind(&mut gl_context);

  let mut mdlbt =
    Mandelbrot {
      low_x: -2.0,
      low_y: -2.0,
      width: 4.0,
      height: 4.0,
      max_iter: 128,
    };

  timers.time("update", || {
    vao.push(&mut gl_context, mdlbt.render().as_slice());
  });

  while process_events(&timers, &mut gl_context, &mut mdlbt, &mut vao) {
    timers.time("draw", || {
      gl_context.clear_buffer();
      vao.draw(&mut gl_context);
      // swap buffers
      window.gl_swap_window();
    });

    timer::sleep(Duration::milliseconds(10));
  }

  timers.print();
}

fn make_shader<'a>(
  gl: &'a GLContextExistence,
) -> Shader<'a> {
  let vertex_shader: String = format!("
    #version 330 core

    const int W = {};
    const int H = {};

    in vec3 color;
    out vec4 v_color;

    void main() {{
      v_color = vec4(color, 1);
      gl_Position =
        vec4(
          float(gl_VertexID % W) / W * 2 - 1,
          float(gl_VertexID / W) / H * 2 - 1,
          0, 1
        );
    }}
  ", WINDOW_WIDTH, WINDOW_HEIGHT);

  let fragment_shader: String = "
    #version 330 core

    in vec4 v_color;

    void main() {
      gl_FragColor = v_color;
    }
  ".to_string();

  let components = vec!(
    ((vertex_shader, gl::VERTEX_SHADER)),
    ((fragment_shader, gl::FRAGMENT_SHADER)),
  );

  Shader::new(gl, components.into_iter())
}

fn make_window() -> sdl2::video::Window {
  sdl2::init(sdl2::INIT_EVERYTHING);

  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMajorVersion, 3);
  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMinorVersion, 3);
  sdl2::video::gl_set_attribute(
    sdl2::video::GLAttr::GLContextProfileMask,
    sdl2::video::GLProfile::GLCoreProfile as isize
  );

  let window = sdl2::video::Window::new(
    "OpenCL",
    sdl2::video::WindowPos::PosCentered,
    sdl2::video::WindowPos::PosCentered,
    WINDOW_WIDTH as isize,
    WINDOW_HEIGHT as isize,
    sdl2::video::OPENGL,
  ).unwrap();

  window
}

fn make_vao<'a>(
  gl: &'a GLContextExistence,
  gl_context: &mut GLContext,
  shader: &Shader<'a>,
) -> GLArray<'a, RGB> {
  let attribs = [
    VertexAttribData {
      name: "color",
      size: 3,
      unit: GLType::Float,
    },
  ];

  let capacity = WINDOW_WIDTH as usize * WINDOW_HEIGHT as usize * 3;
  let vbo = GLBuffer::new(gl, gl_context, capacity);

  GLArray::new(
    gl,
    gl_context,
    shader,
    &attribs,
    DrawMode::Points,
    vbo,
  )
}

fn process_events<'a>(
  timers: &TimerSet,
  gl: &mut GLContext,
  mdlbt: &mut Mandelbrot,
  vao: &mut GLArray<'a, RGB>,
) -> bool {
  loop {
    match sdl2::event::poll_event() {
      Event::None => {
        return true;
      },
      Event::Quit(_) => {
        return false;
      },
      Event::AppTerminating(_) => {
        return false;
      },
      Event::MouseButtonDown(_, _, _, btn, x, y) => {
        let y = WINDOW_HEIGHT as i32 - y;
        match btn {
          Mouse::Left => {
            let ww = WINDOW_WIDTH as f32;
            let wh = WINDOW_HEIGHT as f32;
            mdlbt.low_x = (x as f32) / ww * mdlbt.width + mdlbt.low_x;
            mdlbt.low_y = (y as f32) / wh * mdlbt.height + mdlbt.low_y;
            mdlbt.width = mdlbt.width / ww;
            mdlbt.height = mdlbt.height / wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          },
          _ => {},
        };
      },
      Event::KeyDown(_, _, key, _, _, repeat) => {
        if !repeat {
          match key {
            KeyCode::Up => {
              mdlbt.max_iter *= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            KeyCode::Down => {
              mdlbt.max_iter /= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            _ => {},
          }
        }
      },
      _ => {},
    }
  }
}
<commit_msg>Right-click to zoom out<commit_after>use gl;
use mandelbrot::Mandelbrot;
use std::io::timer;
use std::mem;
use std::time::duration::Duration;
use sdl2;
use sdl2::event::Event;
use sdl2::keycode::KeyCode;
use sdl2::mouse::Mouse;
use stopwatch::TimerSet;
use yaglw::gl_context::{GLContext, GLContextExistence};
use yaglw::shader::Shader;
use yaglw::vertex_buffer::{GLArray, GLBuffer, GLType, VertexAttribData, DrawMode};

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

#[repr(C)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

pub fn main() {
  let timers = TimerSet::new();

  let window = make_window();

  let _sdl_gl_context = window.gl_create_context().unwrap();

  // Load the OpenGL function pointers.
  gl::load_with(|s| unsafe {
    mem::transmute(sdl2::video::gl_get_proc_address(s))
  });

  let (gl, mut gl_context) = unsafe {
    GLContext::new()
  };

  match gl_context.get_error() {
    gl::NO_ERROR => {},
    err => {
      println!("OpenGL error 0x{:x} in setup", err);
      return;
    },
  }

  let shader = make_shader(&gl);
  shader.use_shader(&mut gl_context);

  let mut vao = make_vao(&gl, &mut gl_context, &shader);
  vao.bind(&mut gl_context);

  let mut mdlbt =
    Mandelbrot {
      low_x: -2.0,
      low_y: -2.0,
      width: 4.0,
      height: 4.0,
      max_iter: 128,
    };

  timers.time("update", || {
    vao.push(&mut gl_context, mdlbt.render().as_slice());
  });

  while process_events(&timers, &mut gl_context, &mut mdlbt, &mut vao) {
    timers.time("draw", || {
      gl_context.clear_buffer();
      vao.draw(&mut gl_context);
      // swap buffers
      window.gl_swap_window();
    });

    timer::sleep(Duration::milliseconds(10));
  }

  timers.print();
}

fn make_shader<'a>(
  gl: &'a GLContextExistence,
) -> Shader<'a> {
  let vertex_shader: String = format!("
    #version 330 core

    const int W = {};
    const int H = {};

    in vec3 color;
    out vec4 v_color;

    void main() {{
      v_color = vec4(color, 1);
      gl_Position =
        vec4(
          float(gl_VertexID % W) / W * 2 - 1,
          float(gl_VertexID / W) / H * 2 - 1,
          0, 1
        );
    }}
  ", WINDOW_WIDTH, WINDOW_HEIGHT);

  let fragment_shader: String = "
    #version 330 core

    in vec4 v_color;

    void main() {
      gl_FragColor = v_color;
    }
  ".to_string();

  let components = vec!(
    ((vertex_shader, gl::VERTEX_SHADER)),
    ((fragment_shader, gl::FRAGMENT_SHADER)),
  );

  Shader::new(gl, components.into_iter())
}

fn make_window() -> sdl2::video::Window {
  sdl2::init(sdl2::INIT_EVERYTHING);

  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMajorVersion, 3);
  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMinorVersion, 3);
  sdl2::video::gl_set_attribute(
    sdl2::video::GLAttr::GLContextProfileMask,
    sdl2::video::GLProfile::GLCoreProfile as isize
  );

  let window = sdl2::video::Window::new(
    "OpenCL",
    sdl2::video::WindowPos::PosCentered,
    sdl2::video::WindowPos::PosCentered,
    WINDOW_WIDTH as isize,
    WINDOW_HEIGHT as isize,
    sdl2::video::OPENGL,
  ).unwrap();

  window
}

fn make_vao<'a>(
  gl: &'a GLContextExistence,
  gl_context: &mut GLContext,
  shader: &Shader<'a>,
) -> GLArray<'a, RGB> {
  let attribs = [
    VertexAttribData {
      name: "color",
      size: 3,
      unit: GLType::Float,
    },
  ];

  let capacity = WINDOW_WIDTH as usize * WINDOW_HEIGHT as usize * 3;
  let vbo = GLBuffer::new(gl, gl_context, capacity);

  GLArray::new(
    gl,
    gl_context,
    shader,
    &attribs,
    DrawMode::Points,
    vbo,
  )
}

fn process_events<'a>(
  timers: &TimerSet,
  gl: &mut GLContext,
  mdlbt: &mut Mandelbrot,
  vao: &mut GLArray<'a, RGB>,
) -> bool {
  loop {
    match sdl2::event::poll_event() {
      Event::None => {
        return true;
      },
      Event::Quit(_) => {
        return false;
      },
      Event::AppTerminating(_) => {
        return false;
      },
      Event::MouseButtonDown(_, _, _, btn, x, y) => {
        let y = WINDOW_HEIGHT as i32 - y;
        match btn {
          Mouse::Left => {
            let ww = WINDOW_WIDTH as f32;
            let wh = WINDOW_HEIGHT as f32;
            mdlbt.low_x = (x as f32) / ww * mdlbt.width + mdlbt.low_x;
            mdlbt.low_y = (y as f32) / wh * mdlbt.height + mdlbt.low_y;
            mdlbt.width = mdlbt.width / ww;
            mdlbt.height = mdlbt.height / wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          },
          Mouse::Right => {
            let ww = WINDOW_WIDTH as f32;
            let wh = WINDOW_HEIGHT as f32;
            mdlbt.width = mdlbt.width * ww;
            mdlbt.height = mdlbt.height * wh;
            mdlbt.low_x = mdlbt.low_x - mdlbt.width / 2.0;
            mdlbt.low_y = mdlbt.low_y - mdlbt.height / 2.0;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          }
          _ => {},
        };
      },
      Event::KeyDown(_, _, key, _, _, repeat) => {
        if !repeat {
          match key {
            KeyCode::Up => {
              mdlbt.max_iter *= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            KeyCode::Down => {
              mdlbt.max_iter /= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            _ => {},
          }
        }
      },
      _ => {},
    }
  }
}
<|endoftext|>