<commit_before>//! The master module provides the Master struct which instructs Workers which
//! portions of the image they should render and collects their results to combine
//! into the final image.

use std::path::PathBuf;
use std::io::prelude::*;
use std::collections::HashMap;
use std::net::ToSocketAddrs;
use std::iter;

use bincode::rustc_serialize::decode;
use image;
use mio::tcp::{TcpStream, Shutdown};
use mio::*;

use film::Image;
use exec::Config;
use exec::distrib::{worker, Instructions};
use sampler::BlockQueue;

enum DistributedFrame {
    InProgress {
        frame: usize,
        // The number of workers who have reported results for this
        // frame so far
        num_reporting: usize,
        render: Image,
    },
    Completed,
}

#[derive(Clone, Debug)]
struct WorkerBuffer {
    pub buf: Vec<u8>,
    pub expected_size: usize,
    pub currently_read: usize,
}

impl WorkerBuffer {
    pub fn new() -> WorkerBuffer {
        WorkerBuffer { buf: Vec::new(), expected_size: 8, currently_read: 0 }
    }
}

pub struct Master {
    // Hostnames of the workers to send work too
    workers: Vec<String>,
    connections: Vec<TcpStream>,
    // Temporary buffers to store worker results in as they're
    // read in over TCP
    worker_buffers: Vec<WorkerBuffer>,
    config: Config,
    frames: HashMap<usize, DistributedFrame>,
    selected_frames: Option<(usize, usize)>,
    img_dim: (usize, usize),
    blocks_per_worker: usize,
    blocks_remainder: usize,
}

impl Master {
    /// Create a new master that will contact the worker nodes passed and
    /// send instructions on what parts of the scene to start rendering
    pub fn start_workers(workers: Vec<String>, config: Config, img_dim: (usize, usize),
                         frames: Option<(usize, usize)>) -> (Master, EventLoop<Master>) {
        // Figure out how many blocks we have for this image and assign them to our workers
        let queue = BlockQueue::new((img_dim.0 as u32, img_dim.1 as u32), (8, 8), (0, 0));
        let blocks_per_worker = queue.len() / workers.len();
        let blocks_remainder = queue.len() % workers.len();
        println!("Have {} workers, each worker does {} blocks w/ {} remainder",
                 workers.len(), blocks_per_worker, blocks_remainder);

        let mut event_loop = EventLoop::<Master>::new().unwrap();
        let mut connections = Vec::new();

        // Connect to each worker and send instructions on what to render
        // I guess this should also be queue'd up and the writes actually performed asynchronously?
        // Otherwise we need to loop on write_all while waiting for the connection to open
        for (i, host) in workers.iter().enumerate() {
            let addr = (&host[..], worker::PORT).to_socket_addrs().unwrap().next().unwrap();
            println!("Connecting too {:?}", addr);
            match TcpStream::connect(&addr) {
                Ok(stream) => {
                    println!("Connected and writing");
                    println!("Adding stream to event loop");
                    // Each worker is identified in the event loop by their index in the vec
                    match event_loop.register(&stream, Token(i)) {
                        Err(e) => println!("Error registering stream from {}: {}", host, e),
                        Ok(_) => {},
                    }
                    connections.push(stream);
                },
                Err(e) => println!("Failed to contact worker {}: {:?}", host, e),
            }
        }
        let worker_buffers: Vec<_> = iter::repeat(WorkerBuffer::new()).take(workers.len()).collect();
        let master = Master { workers: workers, connections: connections,
                              worker_buffers: worker_buffers, config: config,
                              frames: HashMap::new(), selected_frames: frames,
                              img_dim: img_dim,
                              blocks_per_worker: blocks_per_worker,
                              blocks_remainder: blocks_remainder };
        (master, event_loop)
    }
    /// Read a result frame from a worker and save it into the list of frames we're collecting from
    /// all workers. Will save out the final render if all workers have reported results for this
    /// frame.
    fn save_results(&mut self, frame: worker::Frame) {
        // Find the frame this worker is referring to and add its results
        let frame_num = frame.frame as usize;
        println!("Worker reporting frame {}", frame_num);
        if let Some(df) = self.frames.get_mut(&frame_num) {
            match df {
                DistributedFrame::InProgress { frame: _, num_reporting: num_reporting, render: render } => {
                    render.add_blocks(frame.block_size, &frame.blocks, &frame.pixels);
                    num_reporting += 1;
                    println!("We have parts of this frame already");
                },
                DistributedFrame::Completed => println!("Worker reporting on completed frame!?"),
            }
        }
        // TODO: Better way here? We get stuck because self.frames is counted as borrowed
        // from the if above, making this really awkward.
        if self.frames.get_mut(&frame_num).is_none() {
            // TODO: I need to seperate the render target from the actual image as the
            // filter here isn't used in this path and it doesn't make sense to have one
            let render = Image::new(self.img_dim);
            let mut df = DistributedFrame::InProgress { frame: frame_num, num_reporting: 1, render: render};
            df.render.add_blocks(frame.block_size, &frame.blocks, &frame.pixels);
            self.frames.insert(df.frame, df);
            println!("This is a new frame");
        }
        if let Some(df) = self.frames.get_mut(&frame_num) {
            match df {
                DistributedFrame::InProgress { frame: frame, num_reporting: num_reporting, render: render } => {
                    if df.num_reporting == self.workers.len() {
                        df.completed = true;
                        println!("We have completed frame {}", frame_num);
                        let out_file = match self.config.out_path.extension() {
                            Some(_) => self.config.out_path.clone(),
                            None => self.config.out_path.join(
                                PathBuf::from(format!("frame{:05}.png", df.frame))),
                        };
                        println!("Frame {}: rendered to '{}'\n--------------------",
                                 frame_num, out_file.display());
                        let img = df.render.get_srgb8();
                        let dim = df.render.dimensions();
                        match image::save_buffer(&out_file.as_path(), &img[..], dim.0 as u32,
                                                 dim.1 as u32, image::RGB(8)) {
                            Ok(_) => {},
                            Err(e) => println!("Error saving image, {}", e),
                        };
                    }
                },
                DistributedFrame::Completed => println!("Can not save out already completed frame"),
            }
            df = DistributedFrame::Completed;
        }
    }
    fn read_worker_buffer(&mut self, worker: usize) -> bool {
        let mut buf = &mut self.worker_buffers[worker];
        // If we haven't read the size of data being sent, read that now
        if buf.currently_read < 8 {
            // First 8 bytes are a u64 specifying the number of bytes being sent
            buf.buf.extend(iter::repeat(0u8).take(8));
            println!("Reading size header...");
            match self.connections[worker].read(&mut buf.buf[buf.currently_read..]) {
                Ok(n) => buf.currently_read += n,
                Err(e) => println!("Error reading results from worker {}: {}", self.workers[worker], e),
            }
            println!("Read {} bytes so far, must read {} in total", buf.currently_read, buf.expected_size);
            if buf.currently_read == buf.expected_size {
                println!("Got size header");
                // How many bytes we expect to get from the worker for a frame
                buf.expected_size = decode(&buf.buf[..]).unwrap();
                println!("Expecting {} bytes", buf.expected_size);
                // Extend the Vec so we've got enough room for the remaning bytes, minus the 8 for the
                // encoded size header
                buf.buf.extend(iter::repeat(0u8).take(buf.expected_size - 8));
            }
        }
        // If we've finished reading the size header we can now start reading the frame data
        if buf.currently_read >= 8 {
            println!("Reading from worker");
            match self.connections[worker].read(&mut buf.buf[buf.currently_read..]) {
                Ok(n) => buf.currently_read += n,
                Err(e) => println!("Error reading results from worker {}: {}", self.workers[worker], e),
            }
            println!("Read {} bytes so far, must read {} in total", buf.currently_read, buf.expected_size);
        }
        buf.currently_read == buf.expected_size
    }
}

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

    fn ready(&mut self, event_loop: &mut EventLoop<Master>, token: Token, event: EventSet) {
        let worker = token.as_usize();
        println!("Event from {}: {:?}", worker, event);
        if event.is_error() {
            println!("Error connecting too {}", self.workers[worker]);
            match self.connections[worker].shutdown(Shutdown::Both) {
                Err(e) => println!("Error shutting down worker {}: {}", worker, e),
                Ok(_) => {},
            }
            // Remove the connection from the event loop
            match event_loop.deregister(&self.connections[worker]) {
                Err(e) => println!("Error deregistering worker {}: {}", worker, e),
                Ok(_) => {},
            }
        }
        // A worker is ready to receive instructions from us
        if event.is_writable() {
            let b_start = worker * self.blocks_per_worker;
            let b_count =
                if worker == self.workers.len() - 1 {
                    self.blocks_per_worker + self.blocks_remainder
                } else {
                    self.blocks_per_worker
                };
            let instr = Instructions::new(&self.config.scene_file, self.selected_frames, b_start, b_count);
            println!("Sending instructions {:?} to {}", instr, self.workers[worker]);
            let bytes = instr.to_json().into_bytes();
            // Loop until we successfully write the byes
            match self.connections[worker].write_all(&bytes[..]) {
                Err(e) => {
                    println!("Failed to send instructions to {}: {:?}", self.workers[worker], e);
                    return;
                },
                Ok(_) => println!("Instructions sent"),
            }
            // Register that we no longer care about writable events on this connection
            event_loop.reregister(&self.connections[worker], token,
                                  EventSet::readable() | EventSet::error() | EventSet::hup(),
                                  PollOpt::level()).expect("Re-registering failed");
            // We no longer need to write anything, so close the write end
            match self.connections[worker].shutdown(Shutdown::Write) {
                Err(e) => panic!(format!("Failed to shutdown write end to worker {}: {}",
                                         self.workers[worker], e)),
                Ok(_) => {},
            }
        }
        // Some results are available from a worker
        if event.is_readable() {
            println!("Readable event from worker {}", worker);
            if self.read_worker_buffer(worker) {
                println!("Got all frame data, now parsing");
                let frame: worker::Frame = decode(&self.worker_buffers[worker].buf[..]).unwrap();
                println!("Saving frame results");
                self.save_results(frame);
                // Clean up our read buffer
                self.worker_buffers[worker].buf.clear();
                self.worker_buffers[worker].expected_size = 8;
                self.worker_buffers[worker].currently_read = 0;
            }
        }
        // If the worker has terminated, shutdown the read end of the connection
        if event.is_hup() {
            println!("Worker {} has hung up", worker);
            match self.connections[worker].shutdown(Shutdown::Read) {
                Err(e) => println!("Error shutting down worker {}: {}", worker, e),
                Ok(_) => {},
            }
            // Remove the connection from the event loop
            match event_loop.deregister(&self.connections[worker]) {
                Err(e) => println!("Error deregistering worker {}: {}", worker, e),
                Ok(_) => {},
            }
        }
        // After getting results from the worker we check if we've completed all our frames
        // and exit if so
        let all_complete = self.frames.values().fold(true,
                                |all, v| {
                                    match v {
                                        DistributedFrame::Completed => true && v,
                                        _ => false,
                                    }
                                });
        if self.frames.len() == self.config.frame_info.frames && all_complete {
            println!("All frames have been rendered, master exiting");
            event_loop.shutdown();
        }
    }
}

<commit_msg>Fix usage of the DistributedFrame enum<commit_after>//! The master module provides the Master struct which instructs Workers which
//! portions of the image they should render and collects their results to combine
//! into the final image.

use std::path::PathBuf;
use std::io::prelude::*;
use std::collections::HashMap;
use std::net::ToSocketAddrs;
use std::iter;

use bincode::rustc_serialize::decode;
use image;
use mio::tcp::{TcpStream, Shutdown};
use mio::*;

use film::Image;
use exec::Config;
use exec::distrib::{worker, Instructions};
use sampler::BlockQueue;

enum DistributedFrame {
    InProgress {
        frame: usize,
        // The number of workers who have reported results for this
        // frame so far
        num_reporting: usize,
        render: Image,
    },
    Completed,
}

#[derive(Clone, Debug)]
struct WorkerBuffer {
    pub buf: Vec<u8>,
    pub expected_size: usize,
    pub currently_read: usize,
}

impl WorkerBuffer {
    pub fn new() -> WorkerBuffer {
        WorkerBuffer { buf: Vec::new(), expected_size: 8, currently_read: 0 }
    }
}

pub struct Master {
    // Hostnames of the workers to send work too
    workers: Vec<String>,
    connections: Vec<TcpStream>,
    // Temporary buffers to store worker results in as they're
    // read in over TCP
    worker_buffers: Vec<WorkerBuffer>,
    config: Config,
    frames: HashMap<usize, DistributedFrame>,
    selected_frames: Option<(usize, usize)>,
    img_dim: (usize, usize),
    blocks_per_worker: usize,
    blocks_remainder: usize,
}

impl Master {
    /// Create a new master that will contact the worker nodes passed and
    /// send instructions on what parts of the scene to start rendering
    pub fn start_workers(workers: Vec<String>, config: Config, img_dim: (usize, usize),
                         frames: Option<(usize, usize)>) -> (Master, EventLoop<Master>) {
        // Figure out how many blocks we have for this image and assign them to our workers
        let queue = BlockQueue::new((img_dim.0 as u32, img_dim.1 as u32), (8, 8), (0, 0));
        let blocks_per_worker = queue.len() / workers.len();
        let blocks_remainder = queue.len() % workers.len();
        println!("Have {} workers, each worker does {} blocks w/ {} remainder",
                 workers.len(), blocks_per_worker, blocks_remainder);

        let mut event_loop = EventLoop::<Master>::new().unwrap();
        let mut connections = Vec::new();

        // Connect to each worker and send instructions on what to render
        // I guess this should also be queue'd up and the writes actually performed asynchronously?
        // Otherwise we need to loop on write_all while waiting for the connection to open
        for (i, host) in workers.iter().enumerate() {
            let addr = (&host[..], worker::PORT).to_socket_addrs().unwrap().next().unwrap();
            println!("Connecting too {:?}", addr);
            match TcpStream::connect(&addr) {
                Ok(stream) => {
                    println!("Connected and writing");
                    println!("Adding stream to event loop");
                    // Each worker is identified in the event loop by their index in the vec
                    match event_loop.register(&stream, Token(i)) {
                        Err(e) => println!("Error registering stream from {}: {}", host, e),
                        Ok(_) => {},
                    }
                    connections.push(stream);
                },
                Err(e) => println!("Failed to contact worker {}: {:?}", host, e),
            }
        }
        let worker_buffers: Vec<_> = iter::repeat(WorkerBuffer::new()).take(workers.len()).collect();
        let master = Master { workers: workers, connections: connections,
                              worker_buffers: worker_buffers, config: config,
                              frames: HashMap::new(), selected_frames: frames,
                              img_dim: img_dim,
                              blocks_per_worker: blocks_per_worker,
                              blocks_remainder: blocks_remainder };
        (master, event_loop)
    }
    /// Read a result frame from a worker and save it into the list of frames we're collecting from
    /// all workers. Will save out the final render if all workers have reported results for this
    /// frame.
    fn save_results(&mut self, frame: worker::Frame) {
        // Find the frame this worker is referring to and add its results
        let frame_num = frame.frame as usize;
        println!("Worker reporting frame {}", frame_num);
        if let Some(df) = self.frames.get_mut(&frame_num) {
            match df {
                &mut DistributedFrame::InProgress { frame: _, ref mut num_reporting, ref mut render } => {
                    render.add_blocks(frame.block_size, &frame.blocks, &frame.pixels);
                    *num_reporting += 1;
                    println!("We have parts of this frame already");
                },
                &mut DistributedFrame::Completed => println!("Worker reporting on completed frame!?"),
            }
        }
        // TODO: Better way here? We get stuck because self.frames is counted as borrowed
        // from the if above, making this really awkward.
        if self.frames.get_mut(&frame_num).is_none() {
            // TODO: I need to seperate the render target from the actual image as the
            // filter here isn't used in this path and it doesn't make sense to have one
            let mut render = Image::new(self.img_dim);
            render.add_blocks(frame.block_size, &frame.blocks, &frame.pixels);
            let df = DistributedFrame::InProgress { frame: frame_num, num_reporting: 1, render: render};
            self.frames.insert(frame_num, df);
            println!("This is a new frame");
        }
        if let Some(df) = self.frames.get_mut(&frame_num) {
            match df {
                &mut DistributedFrame::InProgress { frame, num_reporting, ref render } => {
                    if num_reporting == self.workers.len() {
                        println!("We have completed frame {}", frame_num);
                        let out_file = match self.config.out_path.extension() {
                            Some(_) => self.config.out_path.clone(),
                            None => self.config.out_path.join(
                                PathBuf::from(format!("frame{:05}.png", frame))),
                        };
                        println!("Frame {}: rendered to '{}'\n--------------------",
                                 frame_num, out_file.display());
                        let img = render.get_srgb8();
                        let dim = render.dimensions();
                        match image::save_buffer(&out_file.as_path(), &img[..], dim.0 as u32,
                                                 dim.1 as u32, image::RGB(8)) {
                            Ok(_) => {},
                            Err(e) => println!("Error saving image, {}", e),
                        };
                    }
                },
                &mut DistributedFrame::Completed => println!("Can not save out already completed frame"),
            }
            *df = DistributedFrame::Completed;
        }
    }
    fn read_worker_buffer(&mut self, worker: usize) -> bool {
        let mut buf = &mut self.worker_buffers[worker];
        // If we haven't read the size of data being sent, read that now
        if buf.currently_read < 8 {
            // First 8 bytes are a u64 specifying the number of bytes being sent
            buf.buf.extend(iter::repeat(0u8).take(8));
            println!("Reading size header...");
            match self.connections[worker].read(&mut buf.buf[buf.currently_read..]) {
                Ok(n) => buf.currently_read += n,
                Err(e) => println!("Error reading results from worker {}: {}", self.workers[worker], e),
            }
            println!("Read {} bytes so far, must read {} in total", buf.currently_read, buf.expected_size);
            if buf.currently_read == buf.expected_size {
                println!("Got size header");
                // How many bytes we expect to get from the worker for a frame
                buf.expected_size = decode(&buf.buf[..]).unwrap();
                println!("Expecting {} bytes", buf.expected_size);
                // Extend the Vec so we've got enough room for the remaning bytes, minus the 8 for the
                // encoded size header
                buf.buf.extend(iter::repeat(0u8).take(buf.expected_size - 8));
            }
        }
        // If we've finished reading the size header we can now start reading the frame data
        if buf.currently_read >= 8 {
            println!("Reading from worker");
            match self.connections[worker].read(&mut buf.buf[buf.currently_read..]) {
                Ok(n) => buf.currently_read += n,
                Err(e) => println!("Error reading results from worker {}: {}", self.workers[worker], e),
            }
            println!("Read {} bytes so far, must read {} in total", buf.currently_read, buf.expected_size);
        }
        buf.currently_read == buf.expected_size
    }
}

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

    fn ready(&mut self, event_loop: &mut EventLoop<Master>, token: Token, event: EventSet) {
        let worker = token.as_usize();
        println!("Event from {}: {:?}", worker, event);
        if event.is_error() {
            println!("Error connecting too {}", self.workers[worker]);
            match self.connections[worker].shutdown(Shutdown::Both) {
                Err(e) => println!("Error shutting down worker {}: {}", worker, e),
                Ok(_) => {},
            }
            // Remove the connection from the event loop
            match event_loop.deregister(&self.connections[worker]) {
                Err(e) => println!("Error deregistering worker {}: {}", worker, e),
                Ok(_) => {},
            }
        }
        // A worker is ready to receive instructions from us
        if event.is_writable() {
            let b_start = worker * self.blocks_per_worker;
            let b_count =
                if worker == self.workers.len() - 1 {
                    self.blocks_per_worker + self.blocks_remainder
                } else {
                    self.blocks_per_worker
                };
            let instr = Instructions::new(&self.config.scene_file, self.selected_frames, b_start, b_count);
            println!("Sending instructions {:?} to {}", instr, self.workers[worker]);
            let bytes = instr.to_json().into_bytes();
            // Loop until we successfully write the byes
            match self.connections[worker].write_all(&bytes[..]) {
                Err(e) => {
                    println!("Failed to send instructions to {}: {:?}", self.workers[worker], e);
                    return;
                },
                Ok(_) => println!("Instructions sent"),
            }
            // Register that we no longer care about writable events on this connection
            event_loop.reregister(&self.connections[worker], token,
                                  EventSet::readable() | EventSet::error() | EventSet::hup(),
                                  PollOpt::level()).expect("Re-registering failed");
            // We no longer need to write anything, so close the write end
            match self.connections[worker].shutdown(Shutdown::Write) {
                Err(e) => panic!(format!("Failed to shutdown write end to worker {}: {}",
                                         self.workers[worker], e)),
                Ok(_) => {},
            }
        }
        // Some results are available from a worker
        if event.is_readable() {
            println!("Readable event from worker {}", worker);
            if self.read_worker_buffer(worker) {
                println!("Got all frame data, now parsing");
                let frame: worker::Frame = decode(&self.worker_buffers[worker].buf[..]).unwrap();
                println!("Saving frame results");
                self.save_results(frame);
                // Clean up our read buffer
                self.worker_buffers[worker].buf.clear();
                self.worker_buffers[worker].expected_size = 8;
                self.worker_buffers[worker].currently_read = 0;
            }
        }
        // If the worker has terminated, shutdown the read end of the connection
        if event.is_hup() {
            println!("Worker {} has hung up", worker);
            match self.connections[worker].shutdown(Shutdown::Read) {
                Err(e) => println!("Error shutting down worker {}: {}", worker, e),
                Ok(_) => {},
            }
            // Remove the connection from the event loop
            match event_loop.deregister(&self.connections[worker]) {
                Err(e) => println!("Error deregistering worker {}: {}", worker, e),
                Ok(_) => {},
            }
        }
        // After getting results from the worker we check if we've completed all our frames
        // and exit if so
        let all_complete = self.frames.values().fold(true,
                                |all, v| {
                                    match v {
                                        &DistributedFrame::Completed => true && all,
                                        _ => false,
                                    }
                                });
        if self.frames.len() == self.config.frame_info.frames && all_complete {
            println!("All frames have been rendered, master exiting");
            event_loop.shutdown();
        }
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;

use gtk::{
    ButtonExt,
    Inhibit,
    OrientableExt,
    WidgetExt,
};
use gtk::Orientation::Vertical;
use relm::Widget;
use relm_attributes::widget;

use self::Msg::*;

#[derive(Msg)]
pub enum Msg {
    Quit,
}

#[widget]
impl Widget for Win {
    fn model() -> () {
        ()
    }

    fn update(&mut self, event: Msg, model: &mut ()) {
        match event {
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Notebook {
                gtk::Button {
                    tab: {
                        tab_label: Some("First Button"),
                    },
                    label: "+",
                },
                gtk::Label {
                    text: "0",
                },
                gtk::Button {
                    label: "-",
                },
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

fn main() {
    Win::run(()).unwrap();
}
<commit_msg>Fix warnings in tabs example<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;

use gtk::{
    ButtonExt,
    Inhibit,
    WidgetExt,
};
use relm::Widget;
use relm_attributes::widget;

use self::Msg::*;

#[derive(Msg)]
pub enum Msg {
    Quit,
}

#[widget]
impl Widget for Win {
    fn model() -> () {
        ()
    }

    fn update(&mut self, event: Msg, _model: &mut ()) {
        match event {
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Notebook {
                gtk::Button {
                    tab: {
                        tab_label: Some("First Button"),
                    },
                    label: "+",
                },
                gtk::Label {
                    text: "0",
                },
                gtk::Button {
                    label: "-",
                },
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

fn main() {
    Win::run(()).unwrap();
}
<|endoftext|>


<commit_before>//!
//! An example of using dsp-chain to create a simple Synthesiser with 3 sine wave oscillators.
//!

extern crate dsp;

use dsp::{
    Event,
    Node,
    SoundStream,
    Settings,
};

/// The number of frames processed per second.
const SAMPLE_HZ: u32 = 44100;
/// The number of channels to use for output. We'll use two for stereo.
const CHANNELS: u16 = 2;
/// This value is equal to (fixed-size buffer length / CHANNELS).
const FRAMES: u16 = 256;

const SETTINGS: Settings = Settings { sample_hz: SAMPLE_HZ, frames: FRAMES, channels: CHANNELS };

const BUFFER_SIZE: uint = (FRAMES * CHANNELS) as uint;

type Input = f32;
type Output = f32;
type OutputBuffer = [f32, ..BUFFER_SIZE];

fn main() {

    // Construct the stream and handle any errors that may have occurred.
    let mut stream = match SoundStream::<OutputBuffer, Input, Output>::new(SETTINGS) {
        Ok(stream) => { println!("It begins!"); stream },
        Err(err) => panic!("An error occurred while constructing SoundStream: {}", err),
    };

    // Construct our fancy Synth!
    let mut synth = Synth([Oscillator(0.0), ..3]);

    // We'll use this to count down from three seconds and then break from the loop.
    let mut timer: f64 = 3.0;

    // The SoundStream iterator will automatically return these events in this order.
    for event in stream {
        match event {
            Event::Out(buffer) => synth.audio_requested(buffer, SETTINGS),
            Event::Update(dt) => {
                timer -= dt as f64 / 1_000_000_000.0;
                if timer <= 0.0 { break }
            }
            _ => (),
        }
    }

    // Close the stream and shut down PortAudio.
    match stream.close() {
        Ok(()) => println!("Great success!"),
        Err(err) => println!("An error occurred while closing SoundStream: {}", err),
    }

}

/// Synth will be our demonstration of a parent DspNode where the Oscillators
/// that it owns are it's children.
struct Synth([Oscillator, ..3]);

impl Node<OutputBuffer, Output> for Synth {
    /// Here we return a reference to each of our Oscillators as our `inputs`.
    /// This allows the default `audio_requested` method to draw input from
    /// each of our oscillators automatically.
    fn inputs(&mut self) -> Vec<&mut Node<OutputBuffer, Output>> {
        let Synth(ref mut oscillators) = *self;
        oscillators.iter_mut().map(|osc| osc as &mut Node<OutputBuffer, Output>).collect()
    }
}

/// Oscillator will be our generator type of node, meaning that we will override
/// the way it provides audio via its `audio_requested` method.
type Phase = f64;
struct Oscillator(Phase);

impl Node<OutputBuffer, Output> for Oscillator {
    /// Here we'll override the audio_requested method and generate a sine wave.
    fn audio_requested(&mut self, buffer: &mut OutputBuffer, settings: Settings) {
        // Middle A on a keyboard in hz.
        const MIDDLE_A_HZ: f64 = 440.0;
        let (frames, channels) = (settings.frames as uint, settings.channels as uint);
        let Oscillator(ref mut phase) = *self;
        // For every frame in the buffer.
        for i in range(0u, frames) {
            *phase += MIDDLE_A_HZ / settings.sample_hz as f64;
            let val = sine_wave(*phase);
            // For each channel in the frame.
            for j in range(0u, channels) {
                let idx = i * channels + j;
                buffer[idx] = val;
            }
        }
    }
}

/// Return a sine wave for the given phase.
fn sine_wave(phase: Phase) -> Output {
    use std::f64::consts::PI_2;
    use std::num::FloatMath;
    ((phase * PI_2).sin() * 0.2) as Output
}

<commit_msg>Made example generate different frequencies<commit_after>//!
//! An example of using dsp-chain to create a simple Synthesiser with 3 sine wave oscillators.
//!

extern crate dsp;

use dsp::{
    Event,
    Node,
    SoundStream,
    Settings,
};

/// The number of frames processed per second.
const SAMPLE_HZ: u32 = 44100;
/// The number of channels to use for output. We'll use two for stereo.
const CHANNELS: u16 = 2;
/// This value is equal to (fixed-size buffer length / CHANNELS).
const FRAMES: u16 = 256;

const SETTINGS: Settings = Settings { sample_hz: SAMPLE_HZ, frames: FRAMES, channels: CHANNELS };

const BUFFER_SIZE: uint = (FRAMES * CHANNELS) as uint;

type Input = f32;
type Output = f32;
type OutputBuffer = [f32, ..BUFFER_SIZE];

type Phase = f64;
type Frequency = f64;

const A5_HZ: Frequency = 440.0;
const D5_HZ: Frequency = 587.33;
const F5_HZ: Frequency = 698.46;

fn main() {

    // Construct the stream and handle any errors that may have occurred.
    let mut stream = match SoundStream::<OutputBuffer, Input, Output>::new(SETTINGS) {
        Ok(stream) => { println!("It begins!"); stream },
        Err(err) => panic!("An error occurred while constructing SoundStream: {}", err),
    };

    // Construct our fancy Synth!
    let mut synth = Synth([Oscillator(0.0, A5_HZ), Oscillator(0.0, D5_HZ), Oscillator(0.0, F5_HZ)]);

    // We'll use this to count down from three seconds and then break from the loop.
    let mut timer: f64 = 3.0;

    // The SoundStream iterator will automatically return these events in this order.
    for event in stream {
        match event {
            Event::Out(buffer) => synth.audio_requested(buffer, SETTINGS),
            Event::Update(dt) => {
                timer -= dt as f64 / 1_000_000_000.0;
                if timer <= 0.0 { break }
            }
            _ => (),
        }
    }

    // Close the stream and shut down PortAudio.
    match stream.close() {
        Ok(()) => println!("Great success!"),
        Err(err) => println!("An error occurred while closing SoundStream: {}", err),
    }

}

/// Synth will be our demonstration of a parent DspNode where the Oscillators
/// that it owns are it's children.
struct Synth([Oscillator, ..3]);

impl Node<OutputBuffer, Output> for Synth {
    /// Here we return a reference to each of our Oscillators as our `inputs`.
    /// This allows the default `audio_requested` method to draw input from
    /// each of our oscillators automatically.
    fn inputs(&mut self) -> Vec<&mut Node<OutputBuffer, Output>> {
        let Synth(ref mut oscillators) = *self;
        oscillators.iter_mut().map(|osc| osc as &mut Node<OutputBuffer, Output>).collect()
    }
}

/// Oscillator will be our generator type of node, meaning that we will override
/// the way it provides audio via its `audio_requested` method.
struct Oscillator(Phase, Frequency);

impl Node<OutputBuffer, Output> for Oscillator {
    /// Here we'll override the audio_requested method and generate a sine wave.
    fn audio_requested(&mut self, buffer: &mut OutputBuffer, settings: Settings) {
        let (frames, channels) = (settings.frames as uint, settings.channels as uint);
        let Oscillator(ref mut phase, frequency) = *self;
        // For every frame in the buffer.
        for i in range(0u, frames) {
            *phase += frequency / settings.sample_hz as f64;
            let val = sine_wave(*phase);
            // For each channel in the frame.
            for j in range(0u, channels) {
                let idx = i * channels + j;
                buffer[idx] = val;
            }
        }
    }
}

/// Return a sine wave for the given phase.
fn sine_wave(phase: Phase) -> Output {
    use std::f64::consts::PI_2;
    use std::num::FloatMath;
    ((phase * PI_2).sin() * 0.2) as Output
}

<|endoftext|>


<commit_before>extern crate irc;

use irc::*;
use std::io::*;

fn main() {
    let mut user = IrcUser::new("rustybot1337", "yarircl", "Rust IRC Bot");
    user.set_password("");

    let mut client = IrcClient::new("chat.freenode.net:6667", user);
    let mut stream = client.connect();
    let mut buffer = String::new();

    /*while stream.read_line(&mut buffer).unwrap() > 0 {
        let msg = match IrcMessage::from_str(&buffer) {
            Ok(x) => println!(">> {}", x.raw),
            Err(e) => println!("error: {}", e)
        };
        buffer.clear();
    }*/

    /*loop {
        let messages = match client.get_messages(&mut stream) {
            Some(msgs) => {
                for msg in msgs {
                    println!("{}", msg.raw);
                }
            },
            None => break
        };
    }*/

    let mut previous = 0;
    let mut current = 0;
    while client.conn_handler(&mut stream) {
        println!("{:?}", client.messages[current].raw);

        previous = current;
        current += 1;
    }
}
<commit_msg>Update example<commit_after>extern crate irc;

use irc::*;
use std::io::*;

fn main() {
    let mut user = IrcUser::new("RockyTV", "yarircl", "Rust IRC Bot");
    user.set_password("1432");

    let mut client = IrcClient::new("chat.freenode.net:6667", user);
    let mut stream = client.connect();
    let mut buffer = String::new();

    let mut previous = 0;
    let mut current = 0;
    while client.conn_handler(&mut stream) {
        let ref curr_msg = client.messages[current];
        println!("{:?}", curr_msg.raw);

        if curr_msg.command == NumericReply::PRIVMSG {
            println!("{:?}", curr_msg);
            if curr_msg.params[1] == "!ping" {
                stream.send_message(&curr_msg.params[0], "Hello there!");
            }
        }

        previous = current;
        current += 1;
    }
}
<|endoftext|>


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

<%namespace name="helpers" file="/helpers.mako.rs" />

// SVG 1.1 (Second Edition)
// https://www.w3.org/TR/SVG/
<% data.new_style_struct("InheritedSVG",
                         inherited=True,
                         gecko_name="SVG") %>

// TODO(emilio): Should some of these types be animatable?

// Section 10 - Text

${helpers.single_keyword("text-anchor",
                         "start middle end",
                         products="gecko",
                         animatable=False)}

// Section 11 - Painting: Filling, Stroking and Marker Symbols
${helpers.single_keyword("color-interpolation",
                         "auto sRGB linearRGB",
                         products="gecko",
                         animatable=False)}

${helpers.single_keyword("color-interpolation-filters", "auto sRGB linearRGB",
                         products="gecko",
                         gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION",
                         animatable=False)}

${helpers.predefined_type("fill-opacity", "Opacity", "1.0",
                          products="gecko", animatable=False)}

${helpers.single_keyword("fill-rule", "nonzero evenodd",
                         gecko_enum_prefix="StyleFillRule",
                         gecko_inexhaustive=True,
                         products="gecko", animatable=False)}

${helpers.single_keyword("shape-rendering",
                         "auto optimizeSpeed crispEdges geometricPrecision",
                         products="gecko",
                         animatable=False)}

${helpers.single_keyword("stroke-linecap", "butt round square",
                         products="gecko", animatable=False)}

${helpers.single_keyword("stroke-linejoin", "miter round bevel",
                         products="gecko", animatable=False)}

${helpers.predefined_type("stroke-miterlimit", "Number", "4.0",
                          "parse_at_least_one", products="gecko",
                          needs_context=False,
                          animatable=False)}

${helpers.predefined_type("stroke-opacity", "Opacity", "1.0",
                          products="gecko", animatable=False)}

// Section 14 - Clipping, Masking and Compositing
${helpers.single_keyword("clip-rule", "nonzero evenodd",
                         products="gecko",
                         gecko_enum_prefix="StyleFillRule",
                         gecko_inexhaustive=True,
                         animatable=False)}
<commit_msg>Add spec links for inherited_svg properties<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

// SVG 1.1 (Second Edition)
// https://www.w3.org/TR/SVG/
<% data.new_style_struct("InheritedSVG",
                         inherited=True,
                         gecko_name="SVG") %>

// TODO(emilio): Should some of these types be animatable?

// Section 10 - Text

${helpers.single_keyword("text-anchor",
                         "start middle end",
                         products="gecko",
                         animatable=False,
                         spec="https://www.w3.org/TR/SVG/text.html#TextAnchorProperty")}

// Section 11 - Painting: Filling, Stroking and Marker Symbols
${helpers.single_keyword("color-interpolation",
                         "auto sRGB linearRGB",
                         products="gecko",
                         animatable=False,
                         spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationProperty")}

${helpers.single_keyword("color-interpolation-filters", "auto sRGB linearRGB",
                         products="gecko",
                         gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION",
                         animatable=False,
                         spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationFiltersProperty")}

${helpers.predefined_type("fill-opacity", "Opacity", "1.0",
                          products="gecko", animatable=False,
                          spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty")}

${helpers.single_keyword("fill-rule", "nonzero evenodd",
                         gecko_enum_prefix="StyleFillRule",
                         gecko_inexhaustive=True,
                         products="gecko", animatable=False,
                         spec="https://www.w3.org/TR/SVG11/painting.html#FillRuleProperty")}

${helpers.single_keyword("shape-rendering",
                         "auto optimizeSpeed crispEdges geometricPrecision",
                         products="gecko",
                         animatable=False,
                         spec="https://www.w3.org/TR/SVG11/painting.html#ShapeRenderingProperty")}

${helpers.single_keyword("stroke-linecap", "butt round square",
                         products="gecko", animatable=False,
                         spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinecapProperty")}

${helpers.single_keyword("stroke-linejoin", "miter round bevel",
                         products="gecko", animatable=False,
                         spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinejoinProperty")}

${helpers.predefined_type("stroke-miterlimit", "Number", "4.0",
                          "parse_at_least_one", products="gecko",
                          needs_context=False,
                          animatable=False,
                          spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty")}

${helpers.predefined_type("stroke-opacity", "Opacity", "1.0",
                          products="gecko", animatable=False,
                          spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty")}

// Section 14 - Clipping, Masking and Compositing
${helpers.single_keyword("clip-rule", "nonzero evenodd",
                         products="gecko",
                         gecko_enum_prefix="StyleFillRule",
                         gecko_inexhaustive=True,
                         animatable=False,
                         spec="https://www.w3.org/TR/SVG11/masking.html#ClipRuleProperty")}
<|endoftext|>


<commit_before>use clap::{App, Arg, SubCommand};
use core::str;
use ra_tools::{
    gen_tests, generate, install_format_hook, run, run_clippy, run_fuzzer, run_rustfmt, Cmd,
    Overwrite, Result,
};
use std::{env, path::PathBuf};

struct InstallOpt {
    client: Option<ClientOpt>,
    server: Option<ServerOpt>,
}

enum ClientOpt {
    VsCode,
}

struct ServerOpt {
    jemalloc: bool,
}

fn main() -> Result<()> {
    let matches = App::new("tasks")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("gen-syntax"))
        .subcommand(SubCommand::with_name("gen-tests"))
        .subcommand(
            SubCommand::with_name("install-ra")
                .arg(Arg::with_name("server").long("--server"))
                .arg(Arg::with_name("jemalloc").long("jemalloc"))
                .arg(Arg::with_name("client-code").long("client-code").conflicts_with("server")),
        )
        .alias("install-code")
        .subcommand(SubCommand::with_name("format"))
        .subcommand(SubCommand::with_name("format-hook"))
        .subcommand(SubCommand::with_name("fuzz-tests"))
        .subcommand(SubCommand::with_name("lint"))
        .get_matches();
    match matches.subcommand() {
        ("install-ra", Some(matches)) => {
            let opts = InstallOpt {
                client: if matches.is_present("server") { None } else { Some(ClientOpt::VsCode) },
                server: if matches.is_present("client-code") {
                    None
                } else {
                    Some(ServerOpt { jemalloc: matches.is_present("jemalloc") })
                },
            };
            install(opts)?
        }
        ("gen-tests", _) => gen_tests(Overwrite)?,
        ("gen-syntax", _) => generate(Overwrite)?,
        ("format", _) => run_rustfmt(Overwrite)?,
        ("format-hook", _) => install_format_hook()?,
        ("lint", _) => run_clippy()?,
        ("fuzz-tests", _) => run_fuzzer()?,
        _ => unreachable!(),
    }
    Ok(())
}

fn install(opts: InstallOpt) -> Result<()> {
    if cfg!(target_os = "macos") {
        fix_path_for_mac()?
    }
    if let Some(client) = opts.client {
        install_client(client)?;
    }
    if let Some(server) = opts.server {
        install_server(server)?;
    }
    Ok(())
}

fn fix_path_for_mac() -> Result<()> {
    let mut vscode_path: Vec<PathBuf> = {
        const COMMON_APP_PATH: &str =
            r"/Applications/Visual Studio Code.app/Contents/Resources/app/bin";
        const ROOT_DIR: &str = "";
        let home_dir = match env::var("HOME") {
            Ok(home) => home,
            Err(e) => Err(format!("Failed getting HOME from environment with error: {}.", e))?,
        };

        [ROOT_DIR, &home_dir]
            .iter()
            .map(|dir| String::from(*dir) + COMMON_APP_PATH)
            .map(PathBuf::from)
            .filter(|path| path.exists())
            .collect()
    };

    if !vscode_path.is_empty() {
        let vars = match env::var_os("PATH") {
            Some(path) => path,
            None => Err("Could not get PATH variable from env.")?,
        };

        let mut paths = env::split_paths(&vars).collect::<Vec<_>>();
        paths.append(&mut vscode_path);
        let new_paths = env::join_paths(paths)?;
        env::set_var("PATH", &new_paths);
    }

    Ok(())
}

fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
    Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm.cmd ci", work_dir: "./editors/code" }.run()?;
    Cmd {
        unix: r"npm run package",
        windows: r"cmd.exe /c npm.cmd run package",
        work_dir: "./editors/code",
    }
    .run()?;

    let code_in_path = Cmd {
        unix: r"code --version",
        windows: r"cmd.exe /c code.cmd --version",
        work_dir: "./editors/code",
    }
    .run()
    .is_ok();
    if !code_in_path {
        Err("Can't execute `code --version`. Perhaps it is not in $PATH?")?;
    }

    Cmd {
        unix: r"code --install-extension ./ra-lsp-0.0.1.vsix --force",
        windows: r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix --force",
        work_dir: "./editors/code",
    }
    .run()?;

    let output = Cmd {
        unix: r"code --list-extensions",
        windows: r"cmd.exe /c code.cmd --list-extensions",
        work_dir: ".",
    }
    .run_with_output()?;

    if !str::from_utf8(&output.stdout)?.contains("ra-lsp") {
        Err("Could not install the Visual Studio Code extension. \
             Please make sure you have at least NodeJS 10.x installed and try again.")?;
    }

    Ok(())
}

fn install_server(opts: ServerOpt) -> Result<()> {
    if opts.jemalloc {
        run("cargo install --path crates/ra_lsp_server --force --features jemalloc", ".")
    } else {
        run("cargo install --path crates/ra_lsp_server --force", ".")
    }
}
<commit_msg>install server first<commit_after>use clap::{App, Arg, SubCommand};
use core::str;
use ra_tools::{
    gen_tests, generate, install_format_hook, run, run_clippy, run_fuzzer, run_rustfmt, Cmd,
    Overwrite, Result,
};
use std::{env, path::PathBuf};

struct InstallOpt {
    client: Option<ClientOpt>,
    server: Option<ServerOpt>,
}

enum ClientOpt {
    VsCode,
}

struct ServerOpt {
    jemalloc: bool,
}

fn main() -> Result<()> {
    let matches = App::new("tasks")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("gen-syntax"))
        .subcommand(SubCommand::with_name("gen-tests"))
        .subcommand(
            SubCommand::with_name("install-ra")
                .arg(Arg::with_name("server").long("--server"))
                .arg(Arg::with_name("jemalloc").long("jemalloc"))
                .arg(Arg::with_name("client-code").long("client-code").conflicts_with("server")),
        )
        .alias("install-code")
        .subcommand(SubCommand::with_name("format"))
        .subcommand(SubCommand::with_name("format-hook"))
        .subcommand(SubCommand::with_name("fuzz-tests"))
        .subcommand(SubCommand::with_name("lint"))
        .get_matches();
    match matches.subcommand() {
        ("install-ra", Some(matches)) => {
            let opts = InstallOpt {
                client: if matches.is_present("server") { None } else { Some(ClientOpt::VsCode) },
                server: if matches.is_present("client-code") {
                    None
                } else {
                    Some(ServerOpt { jemalloc: matches.is_present("jemalloc") })
                },
            };
            install(opts)?
        }
        ("gen-tests", _) => gen_tests(Overwrite)?,
        ("gen-syntax", _) => generate(Overwrite)?,
        ("format", _) => run_rustfmt(Overwrite)?,
        ("format-hook", _) => install_format_hook()?,
        ("lint", _) => run_clippy()?,
        ("fuzz-tests", _) => run_fuzzer()?,
        _ => unreachable!(),
    }
    Ok(())
}

fn install(opts: InstallOpt) -> Result<()> {
    if cfg!(target_os = "macos") {
        fix_path_for_mac()?
    }
    if let Some(server) = opts.server {
        install_server(server)?;
    }
    if let Some(client) = opts.client {
        install_client(client)?;
    }
    Ok(())
}

fn fix_path_for_mac() -> Result<()> {
    let mut vscode_path: Vec<PathBuf> = {
        const COMMON_APP_PATH: &str =
            r"/Applications/Visual Studio Code.app/Contents/Resources/app/bin";
        const ROOT_DIR: &str = "";
        let home_dir = match env::var("HOME") {
            Ok(home) => home,
            Err(e) => Err(format!("Failed getting HOME from environment with error: {}.", e))?,
        };

        [ROOT_DIR, &home_dir]
            .iter()
            .map(|dir| String::from(*dir) + COMMON_APP_PATH)
            .map(PathBuf::from)
            .filter(|path| path.exists())
            .collect()
    };

    if !vscode_path.is_empty() {
        let vars = match env::var_os("PATH") {
            Some(path) => path,
            None => Err("Could not get PATH variable from env.")?,
        };

        let mut paths = env::split_paths(&vars).collect::<Vec<_>>();
        paths.append(&mut vscode_path);
        let new_paths = env::join_paths(paths)?;
        env::set_var("PATH", &new_paths);
    }

    Ok(())
}

fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
    Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm.cmd ci", work_dir: "./editors/code" }.run()?;
    Cmd {
        unix: r"npm run package",
        windows: r"cmd.exe /c npm.cmd run package",
        work_dir: "./editors/code",
    }
    .run()?;

    let code_in_path = Cmd {
        unix: r"code --version",
        windows: r"cmd.exe /c code.cmd --version",
        work_dir: "./editors/code",
    }
    .run()
    .is_ok();
    if !code_in_path {
        Err("Can't execute `code --version`. Perhaps it is not in $PATH?")?;
    }

    Cmd {
        unix: r"code --install-extension ./ra-lsp-0.0.1.vsix --force",
        windows: r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix --force",
        work_dir: "./editors/code",
    }
    .run()?;

    let output = Cmd {
        unix: r"code --list-extensions",
        windows: r"cmd.exe /c code.cmd --list-extensions",
        work_dir: ".",
    }
    .run_with_output()?;

    if !str::from_utf8(&output.stdout)?.contains("ra-lsp") {
        Err("Could not install the Visual Studio Code extension. \
             Please make sure you have at least NodeJS 10.x installed and try again.")?;
    }

    Ok(())
}

fn install_server(opts: ServerOpt) -> Result<()> {
    if opts.jemalloc {
        run("cargo install --path crates/ra_lsp_server --force --features jemalloc", ".")
    } else {
        run("cargo install --path crates/ra_lsp_server --force", ".")
    }
}
<|endoftext|>


<commit_before>use crate::StrError;

/// Computes the point-to-point distance
pub fn point_point_distance(a: &[f64], b: &[f64]) -> Result<f64, StrError> {
    let ndim = a.len();
    if ndim < 2 || ndim > 3 {
        return Err("a.len() == ndim must be 2 or 3");
    }
    if b.len() != ndim {
        return Err("b.len() must equal a.len() == ndim");
    }
    let distance: f64;
    if ndim == 2 {
        distance = f64::sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]));
    } else {
        distance =
            f64::sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]) + (b[2] - a[2]) * (b[2] - a[2]));
    }
    Ok(distance)
}

/// Computes the distance between a point and a segment
///
/// ```text
///                 c
///                /^
/// ⇀             / | ⇀   ⇀   ⇀
/// x = vec(c-a) /  | q = x - p
///             /   |
///            /    |
///           a----->-------------b
///             ⇀              ⇀
///             p = projection(x)
///
///           a-------------------b
///               ⇀
///               n = vec(b-c)
/// ```
///
/// ```text
/// x := c - a
/// n := b - a
/// p := ((x ⋅ n) / (n ⋅ n)) * n
/// q := x - p
/// distance := norm(q)
/// ```
pub fn point_segment_distance(a: &[f64], b: &[f64], c: &[f64]) -> Result<f64, StrError> {
    let ndim = a.len();
    if ndim < 2 || ndim > 3 {
        return Err("a.len() == ndim must be 2 or 3");
    }
    if b.len() != ndim {
        return Err("b.len() must equal a.len() == ndim");
    }
    if c.len() != ndim {
        return Err("c.len() must equal a.len() == ndim");
    }
    let distance: f64;
    if ndim == 2 {
        // n ⋅ n  with n = b - a
        let n_dot_n = (b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]);
        if n_dot_n <= f64::EPSILON {
            return Err("segment is too short");
        }
        // x ⋅ n  with x = c - a
        let x_dot_n = (c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1]);
        // q = x - p = (c-a) - (b-a) * (x⋅n)/(n⋅n)
        let q0 = (c[0] - a[0]) - (b[0] - a[0]) * x_dot_n / n_dot_n;
        let q1 = (c[1] - a[1]) - (b[1] - a[1]) * x_dot_n / n_dot_n;
        // norm(q)
        distance = f64::sqrt(q0 * q0 + q1 * q1);
    } else {
        // n ⋅ n  with n = b - a
        let n_dot_n = (b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]) + (b[2] - a[2]) * (b[2] - a[2]);
        if n_dot_n <= f64::EPSILON {
            return Err("segment is too short");
        }
        // x ⋅ n  with x = c - a
        let x_dot_n = (c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1]) + (c[2] - a[2]) * (b[2] - a[2]);
        // q = x - p = (c-a) - (b-a) * (x⋅n)/(n⋅n)
        let q0 = (c[0] - a[0]) - (b[0] - a[0]) * x_dot_n / n_dot_n;
        let q1 = (c[1] - a[1]) - (b[1] - a[1]) * x_dot_n / n_dot_n;
        let q2 = (c[2] - a[2]) - (b[2] - a[2]) * x_dot_n / n_dot_n;
        // norm(q)
        distance = f64::sqrt(q0 * q0 + q1 * q1 + q2 * q2);
    }
    Ok(distance)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::*;
    use crate::util::{SQRT_2, SQRT_2_BY_3, SQRT_3};
    use russell_chk::assert_approx_eq;

    #[test]
    fn point_point_distance_fails_on_wrong_input() {
        assert_eq!(
            point_point_distance(&[0.0], &[1.0, 1.0]).err(),
            Some("a.len() == ndim must be 2 or 3")
        );
        assert_eq!(
            point_point_distance(&[0.0, 0.0], &[1.0]).err(),
            Some("b.len() must equal a.len() == ndim")
        );
    }

    #[test]
    fn point_point_distance_2d_works() -> Result<(), StrError> {
        let a = &[0.0, 0.0];
        let b = &[1.0, 0.0];
        assert_approx_eq!(point_point_distance(a, b)?, 1.0, 1e-15);

        let b = &[0.0, 2.0];
        assert_approx_eq!(point_point_distance(a, b)?, 2.0, 1e-15);

        let a = &[1.0, 1.0];
        let b = &[2.0, 2.0];
        assert_approx_eq!(point_point_distance(a, b)?, SQRT_2, 1e-15);
        Ok(())
    }

    #[test]
    fn point_point_distance_3d_works() -> Result<(), StrError> {
        let a = &[0.0, 0.0, 0.0];
        let b = &[1.0, 0.0, 0.0];
        assert_approx_eq!(point_point_distance(a, b)?, 1.0, 1e-15);

        let b = &[0.0, 2.0, 0.0];
        assert_approx_eq!(point_point_distance(a, b)?, 2.0, 1e-15);

        let b = &[0.0, 0.0, 3.0];
        assert_approx_eq!(point_point_distance(a, b)?, 3.0, 1e-15);

        let a = &[1.0, 1.0, 1.0];
        let b = &[2.0, 2.0, 2.0];
        assert_approx_eq!(point_point_distance(a, b)?, SQRT_3, 1e-15);
        Ok(())
    }

    #[test]
    fn point_segment_distance_fails_on_wrong_input() {
        assert_eq!(
            point_segment_distance(&[0.0], &[1.0, 1.0], &[2.0, 2.0]).err(),
            Some("a.len() == ndim must be 2 or 3")
        );
        assert_eq!(
            point_segment_distance(&[0.0, 0.0], &[1.0], &[2.0, 2.0]).err(),
            Some("b.len() must equal a.len() == ndim")
        );
        assert_eq!(
            point_segment_distance(&[0.0, 0.0], &[1.0, 1.0], &[2.0]).err(),
            Some("c.len() must equal a.len() == ndim")
        );
    }

    #[test]
    fn point_segment_distance_2d_fails_on_short_segment() -> Result<(), StrError> {
        let a = &[0.0, 0.0];
        let b = &[0.0, f64::EPSILON];
        let c = &[1.0, 1.0];
        assert_eq!(point_segment_distance(a, b, c).err(), Some("segment is too short"));
        Ok(())
    }

    #[test]
    fn point_segment_distance_3d_fails_on_short_segment() -> Result<(), StrError> {
        let a = &[0.0, 0.0, 0.0];
        let b = &[0.0, 0.0, f64::EPSILON];
        let c = &[1.0, 1.0, 1.0];
        assert_eq!(point_segment_distance(a, b, c).err(), Some("segment is too short"));
        Ok(())
    }

    #[test]
    fn point_segment_distance_2d_works() -> Result<(), StrError> {
        let a = &[0.0, 0.0];
        let b = &[2.0, 2.0];
        let c = &a.clone();
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let c = &b.clone();
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let c = &[1.0, 0.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2 / 2.0, 1e-15);

        let c = &[0.0, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2 / 2.0, 1e-15);

        let c = &[0.5, 0.5];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let a = &[0.0, 0.0];
        let b = &[8.0, 0.0];
        let c = &[1.0, 0.5];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[0.0, 0.0];
        let b = &[0.0, 3.0];
        let c = &[0.5, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[0.6, 0.0];
        let b = &[0.6, 1.8];
        let c = &[0.3, 1.2];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.3);
        Ok(())
    }

    #[test]
    fn point_segment_distance_3d_works() -> Result<(), StrError> {
        let a = &[0.0, 0.0, 0.0];
        let b = &[2.0, 2.0, 2.0];
        let c = &a.clone();
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let c = &b.clone();
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let c = &[1.0, 1.0, 0.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2_BY_3, 1e-15);

        let c = &[0.0, 1.0, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2_BY_3, 1e-15);

        let c = &[1.0, 0.0, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2_BY_3, 1e-15);

        let c = &[0.5, 0.5, 0.5];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let a = &[0.0, 0.0, 0.0];
        let b = &[2.0, 0.0, 0.0];
        let c = &[1.0, 0.5, 0.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[0.0, 0.0, 0.0];
        let b = &[0.0, 3.0, 0.0];
        let c = &[0.5, 1.0, 0.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[0.0, 0.0, 0.0];
        let b = &[0.0, 0.0, 4.0];
        let c = &[0.0, 0.5, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[1.0, 2.0, 1.0];
        let b = &[1.0, 2.0, 5.0];
        let c = &[1.0, 1.0, 2.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 1.0);
        Ok(())
    }
}
<commit_msg>Impl point circum distance<commit_after>use crate::StrError;

/// Computes the point-to-point distance
pub fn point_point_distance(a: &[f64], b: &[f64]) -> Result<f64, StrError> {
    let ndim = a.len();
    if ndim < 2 || ndim > 3 {
        return Err("a.len() == ndim must be 2 or 3");
    }
    if b.len() != ndim {
        return Err("b.len() must equal a.len() == ndim");
    }
    let distance: f64;
    if ndim == 2 {
        distance = f64::sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]));
    } else {
        distance =
            f64::sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]) + (b[2] - a[2]) * (b[2] - a[2]));
    }
    Ok(distance)
}

/// Computes the distance between a point and a segment
///
/// ```text
///                 c
///                /^
/// ⇀             / | ⇀   ⇀   ⇀
/// x = vec(c-a) /  | q = x - p
///             /   |
///            /    |
///           a----->-------------b
///             ⇀              ⇀
///             p = projection(x)
///
///           a-------------------b
///               ⇀
///               n = vec(b-c)
/// ```
///
/// ```text
/// x := c - a
/// n := b - a
/// p := ((x ⋅ n) / (n ⋅ n)) * n
/// q := x - p
/// distance := norm(q)
/// ```
pub fn point_segment_distance(a: &[f64], b: &[f64], c: &[f64]) -> Result<f64, StrError> {
    let ndim = a.len();
    if ndim < 2 || ndim > 3 {
        return Err("a.len() == ndim must be 2 or 3");
    }
    if b.len() != ndim {
        return Err("b.len() must equal a.len() == ndim");
    }
    if c.len() != ndim {
        return Err("c.len() must equal a.len() == ndim");
    }
    let distance: f64;
    if ndim == 2 {
        // n ⋅ n  with n = b - a
        let n_dot_n = (b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]);
        if n_dot_n <= f64::EPSILON {
            return Err("segment is too short");
        }
        // x ⋅ n  with x = c - a
        let x_dot_n = (c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1]);
        // q = x - p = (c-a) - (b-a) * (x⋅n)/(n⋅n)
        let q0 = (c[0] - a[0]) - (b[0] - a[0]) * x_dot_n / n_dot_n;
        let q1 = (c[1] - a[1]) - (b[1] - a[1]) * x_dot_n / n_dot_n;
        // norm(q)
        distance = f64::sqrt(q0 * q0 + q1 * q1);
    } else {
        // n ⋅ n  with n = b - a
        let n_dot_n = (b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]) + (b[2] - a[2]) * (b[2] - a[2]);
        if n_dot_n <= f64::EPSILON {
            return Err("segment is too short");
        }
        // x ⋅ n  with x = c - a
        let x_dot_n = (c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1]) + (c[2] - a[2]) * (b[2] - a[2]);
        // q = x - p = (c-a) - (b-a) * (x⋅n)/(n⋅n)
        let q0 = (c[0] - a[0]) - (b[0] - a[0]) * x_dot_n / n_dot_n;
        let q1 = (c[1] - a[1]) - (b[1] - a[1]) * x_dot_n / n_dot_n;
        let q2 = (c[2] - a[2]) - (b[2] - a[2]) * x_dot_n / n_dot_n;
        // norm(q)
        distance = f64::sqrt(q0 * q0 + q1 * q1 + q2 * q2);
    }
    Ok(distance)
}

/// Computes the signed distance from point to circumference (negative is inside)
///
/// # Note
///
/// This works in 2D only
pub fn point_circumference_distance(center: &[f64], radius: f64, x: &[f64]) -> Result<f64, StrError> {
    let ndim = center.len();
    if ndim != 2 {
        return Err("center.len() == ndim must be 2");
    }
    if x.len() != ndim {
        return Err("x.len() must equal center.len() == ndim");
    }
    let center_distance = point_point_distance(center, x)?;
    let distance = center_distance - radius;
    Ok(distance)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::*;
    use crate::util::{SQRT_2, SQRT_2_BY_3, SQRT_3};
    use russell_chk::assert_approx_eq;

    #[test]
    fn point_point_distance_fails_on_wrong_input() {
        assert_eq!(
            point_point_distance(&[0.0], &[1.0, 1.0]).err(),
            Some("a.len() == ndim must be 2 or 3")
        );
        assert_eq!(
            point_point_distance(&[0.0, 0.0], &[1.0]).err(),
            Some("b.len() must equal a.len() == ndim")
        );
    }

    #[test]
    fn point_point_distance_2d_works() -> Result<(), StrError> {
        let a = &[0.0, 0.0];
        let b = &[1.0, 0.0];
        assert_approx_eq!(point_point_distance(a, b)?, 1.0, 1e-15);

        let b = &[0.0, 2.0];
        assert_approx_eq!(point_point_distance(a, b)?, 2.0, 1e-15);

        let a = &[1.0, 1.0];
        let b = &[2.0, 2.0];
        assert_approx_eq!(point_point_distance(a, b)?, SQRT_2, 1e-15);
        Ok(())
    }

    #[test]
    fn point_point_distance_3d_works() -> Result<(), StrError> {
        let a = &[0.0, 0.0, 0.0];
        let b = &[1.0, 0.0, 0.0];
        assert_approx_eq!(point_point_distance(a, b)?, 1.0, 1e-15);

        let b = &[0.0, 2.0, 0.0];
        assert_approx_eq!(point_point_distance(a, b)?, 2.0, 1e-15);

        let b = &[0.0, 0.0, 3.0];
        assert_approx_eq!(point_point_distance(a, b)?, 3.0, 1e-15);

        let a = &[1.0, 1.0, 1.0];
        let b = &[2.0, 2.0, 2.0];
        assert_approx_eq!(point_point_distance(a, b)?, SQRT_3, 1e-15);
        Ok(())
    }

    #[test]
    fn point_segment_distance_fails_on_wrong_input() {
        assert_eq!(
            point_segment_distance(&[0.0], &[1.0, 1.0], &[2.0, 2.0]).err(),
            Some("a.len() == ndim must be 2 or 3")
        );
        assert_eq!(
            point_segment_distance(&[0.0, 0.0], &[1.0], &[2.0, 2.0]).err(),
            Some("b.len() must equal a.len() == ndim")
        );
        assert_eq!(
            point_segment_distance(&[0.0, 0.0], &[1.0, 1.0], &[2.0]).err(),
            Some("c.len() must equal a.len() == ndim")
        );
    }

    #[test]
    fn point_segment_distance_2d_fails_on_short_segment() -> Result<(), StrError> {
        let a = &[0.0, 0.0];
        let b = &[0.0, f64::EPSILON];
        let c = &[1.0, 1.0];
        assert_eq!(point_segment_distance(a, b, c).err(), Some("segment is too short"));
        Ok(())
    }

    #[test]
    fn point_segment_distance_3d_fails_on_short_segment() -> Result<(), StrError> {
        let a = &[0.0, 0.0, 0.0];
        let b = &[0.0, 0.0, f64::EPSILON];
        let c = &[1.0, 1.0, 1.0];
        assert_eq!(point_segment_distance(a, b, c).err(), Some("segment is too short"));
        Ok(())
    }

    #[test]
    fn point_segment_distance_2d_works() -> Result<(), StrError> {
        let a = &[0.0, 0.0];
        let b = &[2.0, 2.0];
        let c = &a.clone();
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let c = &b.clone();
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let c = &[1.0, 0.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2 / 2.0, 1e-15);

        let c = &[0.0, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2 / 2.0, 1e-15);

        let c = &[0.5, 0.5];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let a = &[0.0, 0.0];
        let b = &[8.0, 0.0];
        let c = &[1.0, 0.5];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[0.0, 0.0];
        let b = &[0.0, 3.0];
        let c = &[0.5, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[0.6, 0.0];
        let b = &[0.6, 1.8];
        let c = &[0.3, 1.2];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.3);
        Ok(())
    }

    #[test]
    fn point_segment_distance_3d_works() -> Result<(), StrError> {
        let a = &[0.0, 0.0, 0.0];
        let b = &[2.0, 2.0, 2.0];
        let c = &a.clone();
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let c = &b.clone();
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let c = &[1.0, 1.0, 0.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2_BY_3, 1e-15);

        let c = &[0.0, 1.0, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2_BY_3, 1e-15);

        let c = &[1.0, 0.0, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_approx_eq!(distance, SQRT_2_BY_3, 1e-15);

        let c = &[0.5, 0.5, 0.5];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.0);

        let a = &[0.0, 0.0, 0.0];
        let b = &[2.0, 0.0, 0.0];
        let c = &[1.0, 0.5, 0.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[0.0, 0.0, 0.0];
        let b = &[0.0, 3.0, 0.0];
        let c = &[0.5, 1.0, 0.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[0.0, 0.0, 0.0];
        let b = &[0.0, 0.0, 4.0];
        let c = &[0.0, 0.5, 1.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 0.5);

        let a = &[1.0, 2.0, 1.0];
        let b = &[1.0, 2.0, 5.0];
        let c = &[1.0, 1.0, 2.0];
        let distance = point_segment_distance(a, b, c)?;
        assert_eq!(distance, 1.0);
        Ok(())
    }

    #[test]
    fn point_circumference_distance_fails_on_wrong_input() {
        assert_eq!(
            point_circumference_distance(&[0.0], 1.0, &[2.0, 2.0]).err(),
            Some("center.len() == ndim must be 2")
        );
        assert_eq!(
            point_circumference_distance(&[0.0, 0.0], 1.0, &[2.0]).err(),
            Some("x.len() must equal center.len() == ndim")
        );
    }

    #[test]
    fn point_circumference_distance_works() -> Result<(), StrError> {
        let center = &[3.0, 4.0];
        let radius = 5.0;
        let distance = point_circumference_distance(center, radius, &[0.0, 0.0])?;
        assert_eq!(distance, 0.0);

        let distance = point_circumference_distance(center, radius, &[3.0, 4.0])?;
        assert_eq!(distance, -5.0);

        let distance = point_circumference_distance(center, radius, &[6.0, 8.0])?;
        assert_eq!(distance, 0.0);

        let distance = point_circumference_distance(center, radius, &[9.0, 12.0])?;
        assert_eq!(distance, 5.0);
        Ok(())
    }
}
<|endoftext|>


<commit_before><commit_msg>cargo fmt<commit_after><|endoftext|>


<commit_before>extern crate gstreamer as gst;
extern crate gstreamer_app as gst_app;

extern crate byte_slice_cast;
use byte_slice_cast::AsSliceOf;

use std::i16;

use std::collections::vec_deque::VecDeque;

use std::mem;

use std::sync::{Arc, Mutex};

use super::SamplesExtractor;

pub struct AudioBuffer {
    capacity: usize,
    pub sample_duration: f64,
    channels: usize,
    drain_size: usize,

    pub samples_offset: usize,
    pub samples: VecDeque<f64>,

    waveform_buffer_mtx: Arc<Mutex<Box<SamplesExtractor>>>,
    second_waveform_buffer_box: Option<Box<SamplesExtractor>>,
}

impl AudioBuffer {
    pub fn new(
        caps: &gst::Caps,
        size_duration: u64,
        waveform_buffer_mtx: Arc<Mutex<Box<SamplesExtractor>>>,
        second_waveform_buffer: Box<SamplesExtractor>,
    ) -> Self
    {
        let structure = caps.get_structure(0)
            .expect("Couldn't get structure from audio caps");
        let rate = structure.get::<i32>("rate")
            .expect("Couldn't get rate from audio caps");

        // assert_eq!(format, S16);
        // assert_eq!(layout, Interleaved);

        let sample_duration = 1_000_000_000f64 / (rate as f64);
        let capacity = (size_duration as f64 / sample_duration) as usize;

        let drain_size = capacity / 5;

        AudioBuffer {
            capacity: capacity,
            sample_duration: sample_duration,
            channels: structure.get::<i32>("channels")
                .expect("Couldn't get channels from audio sample")
                as usize,
            drain_size: drain_size,

            samples_offset: 0,
            samples: VecDeque::with_capacity(capacity),

            waveform_buffer_mtx: waveform_buffer_mtx,
            second_waveform_buffer_box: Some(second_waveform_buffer),
        }
    }

    pub fn push_gst_sample(&mut self, sample: gst::Sample) {
        let buffer = sample.get_buffer()
            .expect("Couldn't get buffer from audio sample");

        let map = buffer.map_readable().unwrap();
        let incoming_samples = map.as_slice().as_slice_of::<i16>()
            .expect("Couldn't get audio samples as i16");

        if self.samples.len() + incoming_samples.len() > self.capacity
        {   // buffer will reach capacity => drain a chunk of samples
            // only if we have samples in history
            let offset_delta = self.second_waveform_buffer_box.as_ref()
                .expect("AudioBuffer: failed to get ref on second buffer for drain")
                .get_sample_offset() - self.samples_offset;
            if offset_delta > self.drain_size {
                self.samples.drain(..self.drain_size);
                self.samples_offset += self.drain_size;
            }
        }

        // normalize samples in range 0f64..2f64 ready to render

        // FIXME: use gstreamer downmix
        // FIXME: select the channels using the position info
        // if more than 2 channels,
        // Use 75% for first 2 channels (assumes front left and front right)
        // Use 25% for the rest
        let (front_norm_factor, others_norm_factor, front_channels) =
            if self.channels > 2 {
                (
                    0.75f64 / 2f64 / (i16::MAX as f64),
                    0.25f64 / ((self.channels - 2) as f64) / (i16::MAX as f64),
                    2
                )
            } else {
                (
                    1f64 / (self.channels as f64) / (i16::MAX as f64),
                    0f64,
                    self.channels
                )
            };

        let mut norm_sample;
        let mut index = 0;
        while index < incoming_samples.len() {
            norm_sample = 0f64;

            for _ in 0..front_channels {
                norm_sample += incoming_samples[index] as f64 * front_norm_factor;
                index += 1;
            }
            for _ in front_channels..self.channels {
                norm_sample += incoming_samples[index] as f64 * others_norm_factor;
                index += 1;
            }
            self.samples.push_back(1f64 - norm_sample);
        };

        // prepare the second waveform buffer for rendering
        if !self.samples.is_empty() {
            let mut moved_buffer = self.second_waveform_buffer_box.take()
                .expect("AudioBuffer: failed to take second buffer while updating");
            moved_buffer.extract_samples(&self);

            // swap buffers
            let waveform_buffer_box = &mut *self.waveform_buffer_mtx.lock()
                .expect("AudioBuffer: failed to lock the waveform buffer for swap");
            mem::swap(waveform_buffer_box, &mut moved_buffer);

            self.second_waveform_buffer_box = Some(moved_buffer);
            // self.second_waveform_buffer_box is now the buffer previously in
            // self.waveform_buffer_mtx
        }
    }

    pub fn iter(&self, first: usize, last: usize, step: usize) -> Iter {
        assert!(first >= self.samples_offset);
        let last = if last > first { last } else { first };
        Iter::new(self, first, last, step)
    }

    pub fn handle_eos(&mut self) {
        if !self.samples.is_empty() {
            // get all remaining samples in the buffer
            let mut moved_buffer = self.second_waveform_buffer_box.take()
                .expect("AudioBuffer: failed to take second buffer while handling eos");
            moved_buffer.handle_eos();
            moved_buffer.extract_samples(&self);

            // swap buffers
            // TODO: could we just replace? - need to verify that we won't
            // push_gst_sample after that
            let waveform_buffer_box = &mut *self.waveform_buffer_mtx.lock()
                .expect("AudioBuffer: failed to lock the waveform buffer for swap");

            mem::swap(waveform_buffer_box, &mut moved_buffer);

            self.second_waveform_buffer_box = Some(moved_buffer);
            // self.second_waveform_buffer_box is now the buffer previously in
            // self.waveform_buffer_mtx
        }
    }
}

pub struct Iter<'a> {
    buffer: &'a AudioBuffer,
    idx: usize,
    last: usize,
    step: usize,
}

impl<'a> Iter<'a> {
    fn new(buffer: &'a AudioBuffer, first: usize, last: usize, step: usize) -> Iter<'a> {
        Iter {
            buffer: buffer,
            idx: first - buffer.samples_offset,
            last: buffer.samples.len().min(last - buffer.samples_offset),
            step: step,
        }
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a f64;

    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.last {
            return None;
        }

        let item = self.buffer.samples.get(self.idx);
        self.idx += self.step;

        item
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.idx == self.last {
            return (0, Some(0));
        }

        let remaining = (self.last - self.idx) / self.step;

        (remaining, Some(remaining))
    }
}
<commit_msg>AudioBuffer: limit lock to actual swap (#25)<commit_after>extern crate gstreamer as gst;
extern crate gstreamer_app as gst_app;

extern crate byte_slice_cast;
use byte_slice_cast::AsSliceOf;

use std::i16;

use std::collections::vec_deque::VecDeque;

use std::mem;

use std::sync::{Arc, Mutex};

use super::SamplesExtractor;

pub struct AudioBuffer {
    capacity: usize,
    pub sample_duration: f64,
    channels: usize,
    drain_size: usize,

    pub samples_offset: usize,
    pub samples: VecDeque<f64>,

    waveform_buffer_mtx: Arc<Mutex<Box<SamplesExtractor>>>,
    second_waveform_buffer_box: Option<Box<SamplesExtractor>>,
}

impl AudioBuffer {
    pub fn new(
        caps: &gst::Caps,
        size_duration: u64,
        waveform_buffer_mtx: Arc<Mutex<Box<SamplesExtractor>>>,
        second_waveform_buffer: Box<SamplesExtractor>,
    ) -> Self
    {
        let structure = caps.get_structure(0)
            .expect("Couldn't get structure from audio caps");
        let rate = structure.get::<i32>("rate")
            .expect("Couldn't get rate from audio caps");

        // assert_eq!(format, S16);
        // assert_eq!(layout, Interleaved);

        let sample_duration = 1_000_000_000f64 / (rate as f64);
        let capacity = (size_duration as f64 / sample_duration) as usize;

        let drain_size = capacity / 5;

        AudioBuffer {
            capacity: capacity,
            sample_duration: sample_duration,
            channels: structure.get::<i32>("channels")
                .expect("Couldn't get channels from audio sample")
                as usize,
            drain_size: drain_size,

            samples_offset: 0,
            samples: VecDeque::with_capacity(capacity),

            waveform_buffer_mtx: waveform_buffer_mtx,
            second_waveform_buffer_box: Some(second_waveform_buffer),
        }
    }

    pub fn push_gst_sample(&mut self, sample: gst::Sample) {
        let buffer = sample.get_buffer()
            .expect("Couldn't get buffer from audio sample");

        let map = buffer.map_readable().unwrap();
        let incoming_samples = map.as_slice().as_slice_of::<i16>()
            .expect("Couldn't get audio samples as i16");

        if self.samples.len() + incoming_samples.len() > self.capacity
        {   // buffer will reach capacity => drain a chunk of samples
            // only if we have samples in history
            let offset_delta = self.second_waveform_buffer_box.as_ref()
                .expect("AudioBuffer: failed to get ref on second buffer for drain")
                .get_sample_offset() - self.samples_offset;
            if offset_delta > self.drain_size {
                self.samples.drain(..self.drain_size);
                self.samples_offset += self.drain_size;
            }
        }

        // normalize samples in range 0f64..2f64 ready to render

        // FIXME: use gstreamer downmix
        // FIXME: select the channels using the position info
        // if more than 2 channels,
        // Use 75% for first 2 channels (assumes front left and front right)
        // Use 25% for the rest
        let (front_norm_factor, others_norm_factor, front_channels) =
            if self.channels > 2 {
                (
                    0.75f64 / 2f64 / (i16::MAX as f64),
                    0.25f64 / ((self.channels - 2) as f64) / (i16::MAX as f64),
                    2
                )
            } else {
                (
                    1f64 / (self.channels as f64) / (i16::MAX as f64),
                    0f64,
                    self.channels
                )
            };

        let mut norm_sample;
        let mut index = 0;
        while index < incoming_samples.len() {
            norm_sample = 0f64;

            for _ in 0..front_channels {
                norm_sample += incoming_samples[index] as f64 * front_norm_factor;
                index += 1;
            }
            for _ in front_channels..self.channels {
                norm_sample += incoming_samples[index] as f64 * others_norm_factor;
                index += 1;
            }
            self.samples.push_back(1f64 - norm_sample);
        };

        // prepare the second waveform buffer for rendering
        if !self.samples.is_empty() {
            let mut moved_buffer = self.second_waveform_buffer_box.take()
                .expect("AudioBuffer: failed to take second buffer while updating");
            moved_buffer.extract_samples(&self);

            // swap buffers
            {
                let waveform_buffer_box = &mut *self.waveform_buffer_mtx.lock()
                    .expect("AudioBuffer: failed to lock the waveform buffer for swap");
                mem::swap(waveform_buffer_box, &mut moved_buffer);
            }

            self.second_waveform_buffer_box = Some(moved_buffer);
            // self.second_waveform_buffer_box is now the buffer previously in
            // self.waveform_buffer_mtx
        }
    }

    pub fn iter(&self, first: usize, last: usize, step: usize) -> Iter {
        assert!(first >= self.samples_offset);
        let last = if last > first { last } else { first };
        Iter::new(self, first, last, step)
    }

    pub fn handle_eos(&mut self) {
        if !self.samples.is_empty() {
            // get all remaining samples in the buffer
            let mut moved_buffer = self.second_waveform_buffer_box.take()
                .expect("AudioBuffer: failed to take second buffer while handling eos");
            moved_buffer.handle_eos();
            moved_buffer.extract_samples(&self);

            // swap buffers
            // TODO: could we just replace? - need to verify that we won't
            // push_gst_sample after that
            {
                let waveform_buffer_box = &mut *self.waveform_buffer_mtx.lock()
                    .expect("AudioBuffer: failed to lock the waveform buffer for swap");
                mem::swap(waveform_buffer_box, &mut moved_buffer);
            }

            self.second_waveform_buffer_box = Some(moved_buffer);
            // self.second_waveform_buffer_box is now the buffer previously in
            // self.waveform_buffer_mtx
        }
    }
}

pub struct Iter<'a> {
    buffer: &'a AudioBuffer,
    idx: usize,
    last: usize,
    step: usize,
}

impl<'a> Iter<'a> {
    fn new(buffer: &'a AudioBuffer, first: usize, last: usize, step: usize) -> Iter<'a> {
        Iter {
            buffer: buffer,
            idx: first - buffer.samples_offset,
            last: buffer.samples.len().min(last - buffer.samples_offset),
            step: step,
        }
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a f64;

    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.last {
            return None;
        }

        let item = self.buffer.samples.get(self.idx);
        self.idx += self.step;

        item
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.idx == self.last {
            return (0, Some(0));
        }

        let remaining = (self.last - self.idx) / self.step;

        (remaining, Some(remaining))
    }
}
<|endoftext|>


<commit_before>// ***WARNING***:
// Many trait impls are highly dependent on the fact that this enum is identical to
// the keycodes enum from SDL2
enum_from_primitive! {
    /// Definitions for mouse buttons.  Intended to be used with nitro::input::Input.
    #[derive(Eq, PartialEq, Copy, Clone, Debug, Serialize, Deserialize)]
    pub enum MouseButton {
        Unknown,
        Left,
        Right,
        Middle,
        X1,
        X2,
        Button6,
        Button7,
        Button8,
    }
}

/// Used to get input from the player's mouse, access from nitro::App.input.mouse
pub struct Mouse {
    mouse_util: MouseUtil,
    pos: Vector,
    relative_pos: Vector,
}

impl Mouse {
    pub fn pos(&self) -> Vector {
        pos
    }

    pub fn set_show_cursor(&mut self, input: bool) {
        mouse_util.show_cursor(input);
    }

    pub fn set_relative_mode(&mut self, input: bool) {
        mouse_util.set_relative_mouse_mode(input);
    }
}

pub fn new(mouse_util: MouseUtil) -> Mouse {
    Mouse {
        mouse_util: mouse_util,
        pos: Vector::new(0.0, 0.0),
        relative_pos: Vector::new(0.0, 0.0),
    }
}

pub fn process_event(mouse: &mut Mouse, event: &Event) {
    match *input_event {
        _ => {}
    }
}
<commit_msg>Adding changes to track on development<commit_after>// ***WARNING***:
// Many trait impls are highly dependent on the fact that this enum is identical to
// the keycodes enum from SDL2
enum_from_primitive! {
    /// Definitions for mouse buttons.  Intended to be used with nitro::input::Input.
    #[derive(Eq, PartialEq, Copy, Clone, Debug, Serialize, Deserialize)]
    pub enum MouseButton {
        Unknown,
        Left,
        Right,
        Middle,
        X1,
        X2,
        Button6,
        Button7,
        Button8,
    }
}

/// Used to get input from the player's mouse, access from nitro::App.input.mouse
pub struct Mouse {
    mouse_util: MouseUtil,
    pos: Vector,
    relative_pos: Vector,
}

impl Mouse {
    pub fn pos(&self) -> Vector {
        pos
    }

    pub fn set_show_cursor(&mut self, input: bool) {
        mouse_util.show_cursor(input);
    }

    pub fn set_relative_mode(&mut self, input: bool) {
        mouse_util.set_relative_mouse_mode(input);
    }
}

pub fn new(mouse_util: MouseUtil) -> Mouse {
    Mouse {
        mouse_util: mouse_util,
        pos: Vector::new(0.0, 0.0),
        relative_pos: Vector::new(0.0, 0.0),
    }
}

pub fn process_event(mouse: &mut Mouse, event: &Event) {
    match *input_event {
        Event::MouseMotion{ x, y, .. } => {
            mouse.pos = IntVector::new(x, y);
        }
        _ => {}
    }
}
<|endoftext|>