<commit_before>//   Copyright 2015 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

use std::sync::{Arc, Mutex};
use std::collections::HashMap;
use {Signal, ArmedSignal, Pulse, Waiting, Barrier, Signals};

pub struct Inner {
    pub ready: Vec<usize>,
    pub trigger: Option<Pulse>
}

pub struct Handle(pub Arc<Mutex<Inner>>);

/// A `Select` listens to 1 or more signals. It will wait until
/// any signal becomes available before Pulsing. `Select` will then
/// return the `Signal` that has been `Pulsed`. `Select` has no defined
/// ordering of events for `Signal`s when there are more then one `Signals`
/// pending.
pub struct Select {
    inner: Arc<Mutex<Inner>>,
    signals: HashMap<usize, ArmedSignal>
}

impl Select {
    /// Create a new empty `Select`
    pub fn new() -> Select {
        Select {
            inner: Arc::new(Mutex::new(Inner{
                ready: Vec::new(),
                trigger: None
            })),
            signals: HashMap::new()
        }
    }

    /// Add a signal to the `Select`, a unique id that is associated
    /// With the signal is returned. This can be used to remove the
    /// signal from the `Select` or to lookup the `Pulse` when it fires.
    pub fn add(&mut self, pulse: Signal) -> usize {
        let id = pulse.id();
        let p = pulse.arm(Waiting::select(Handle(self.inner.clone())));
        self.signals.insert(id, p);
        id
    }

    /// Remove a `Signal1 from the `Select` using it's unique id.
    pub fn remove(&mut self, id: usize) -> Option<Signal> {
        self.signals.remove(&id)
            .map(|x| x.disarm())
    }

    /// Convert all the signals present in the `Select` into a `Barrier`
    pub fn into_barrier(self) -> Barrier {
        let vec: Vec<Signal> =
            self.signals
                .into_iter()
                .map(|(_, p)| p.disarm())
                .collect();

        Barrier::new(&vec)
    }

    /// This is a non-blocking attempt to get a `Signal` from a `Select`
    /// this will return a `Some(Signal)` if there is a pending `Signal`
    /// in the select. Otherwise it will return `None`
    pub fn try_next(&mut self) -> Option<Signal> {
        let mut guard = self.inner.lock().unwrap();
        if let Some(x) = guard.ready.pop() {
            return Some(self.signals.remove(&x).map(|x| x.disarm()).unwrap())
        }
        None
    }

    /// Get the number of Signals being watched
    pub fn len(&self) -> usize {
        self.signals.len()
    }
}

impl Iterator for Select {
    type Item = Signal;

    fn next(&mut self) -> Option<Signal> {
        loop {
            if self.signals.len() == 0 {
                return None;
            }

            let pulse = {
                let mut guard = self.inner.lock().unwrap();
                if let Some(x) = guard.ready.pop() {
                    return Some(self.signals.remove(&x).map(|x| x.disarm()).unwrap());
                }
                let (pulse, t) = Signal::new();
                guard.trigger = Some(t);
                pulse
            };
            pulse.wait().unwrap();
        }
    }
}

impl Signals for Select {
    fn signal(&self) -> Signal {
        let (pulse, t) = Signal::new();
        let mut guard = self.inner.lock().unwrap();
        if guard.ready.len() == 0 {
            guard.trigger = Some(t);
        } else {
            t.pulse();
        }
        pulse
    }
}

/// `SelectMap` is a wrapper around a `Select` rather then use
/// a unique id to find out what signal has been asserts, `SelectMap`
/// will return an supplied object.
pub struct SelectMap<T> {
    select: Select,
    items: HashMap<usize, T>
}

impl<T> SelectMap<T> {
    /// Create a new empty `SelectMap`
    pub fn new() -> SelectMap<T> {
        SelectMap {
            select: Select::new(),
            items: HashMap::new()
        }
    }

    /// Add a `Signal` and an associated value into the `SelectMap`
    pub fn add(&mut self, signal: Signal, value: T) {
        let id = self.select.add(signal);
        self.items.insert(id, value);
    }

    /// This is a non-blocking attempt to get a `Signal` from a `SelectMap`
    /// this will return a `Some((Signal, T))` if there is a pending `Signal`
    /// in the select. Otherwise it will return `None`
    pub fn try_next(&mut self) -> Option<(Signal, T)> {
        self.select.try_next().map(|x| {
            let id = x.id();
            (x, self.items.remove(&id).unwrap())
        })
    }

    /// Get the number of items in the `SelectMap`
    pub fn len(&self) -> usize { self.items.len() }
}

impl<T> Iterator for SelectMap<T> {
    type Item = (Signal, T);

    fn next(&mut self) -> Option<(Signal, T)> {
        self.select.next().map(|x| {
            let id = x.id();
            (x, self.items.remove(&id).unwrap())
        })
    }
}

impl<T> Signals for SelectMap<T> {
    fn signal(&self) -> Signal {
        self.select.signal()
    }
}
<commit_msg>Select panic bugfix<commit_after>//   Copyright 2015 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

use std::sync::{Arc, Mutex};
use std::collections::HashMap;
use {Signal, ArmedSignal, Pulse, Waiting, Barrier, Signals};

pub struct Inner {
    pub ready: Vec<usize>,
    pub trigger: Option<Pulse>
}

pub struct Handle(pub Arc<Mutex<Inner>>);

/// A `Select` listens to 1 or more signals. It will wait until
/// any signal becomes available before Pulsing. `Select` will then
/// return the `Signal` that has been `Pulsed`. `Select` has no defined
/// ordering of events for `Signal`s when there are more then one `Signals`
/// pending.
pub struct Select {
    inner: Arc<Mutex<Inner>>,
    signals: HashMap<usize, ArmedSignal>
}

impl Select {
    /// Create a new empty `Select`
    pub fn new() -> Select {
        Select {
            inner: Arc::new(Mutex::new(Inner{
                ready: Vec::new(),
                trigger: None
            })),
            signals: HashMap::new()
        }
    }

    /// Add a signal to the `Select`, a unique id that is associated
    /// With the signal is returned. This can be used to remove the
    /// signal from the `Select` or to lookup the `Pulse` when it fires.
    pub fn add(&mut self, pulse: Signal) -> usize {
        let id = pulse.id();
        let p = pulse.arm(Waiting::select(Handle(self.inner.clone())));
        self.signals.insert(id, p);
        id
    }

    /// Remove a `Signal1 from the `Select` using it's unique id.
    pub fn remove(&mut self, id: usize) -> Option<Signal> {
        self.signals.remove(&id)
            .map(|x| x.disarm())
    }

    /// Convert all the signals present in the `Select` into a `Barrier`
    pub fn into_barrier(self) -> Barrier {
        let vec: Vec<Signal> =
            self.signals
                .into_iter()
                .map(|(_, p)| p.disarm())
                .collect();

        Barrier::new(&vec)
    }

    /// This is a non-blocking attempt to get a `Signal` from a `Select`
    /// this will return a `Some(Signal)` if there is a pending `Signal`
    /// in the select. Otherwise it will return `None`
    pub fn try_next(&mut self) -> Option<Signal> {
        let mut guard = self.inner.lock().unwrap();
        if let Some(x) = guard.ready.pop() {
            return Some(self.signals.remove(&x).map(|x| x.disarm()).unwrap())
        }
        None
    }

    /// Get the number of Signals being watched
    pub fn len(&self) -> usize {
        self.signals.len()
    }
}

impl Iterator for Select {
    type Item = Signal;

    fn next(&mut self) -> Option<Signal> {
        loop {
            if self.signals.len() == 0 {
                return None;
            }

            let pulse = {
                let mut guard = self.inner.lock().unwrap();
                while let Some(x) = guard.ready.pop() {
                    if let Some(x) = self.signals.remove(&x) {
                        return Some(x.disarm());
                    }
                }
                let (pulse, t) = Signal::new();
                guard.trigger = Some(t);
                pulse
            };
            pulse.wait().unwrap();
        }
    }
}

impl Signals for Select {
    fn signal(&self) -> Signal {
        let (pulse, t) = Signal::new();
        let mut guard = self.inner.lock().unwrap();
        if guard.ready.len() == 0 {
            guard.trigger = Some(t);
        } else {
            t.pulse();
        }
        pulse
    }
}

/// `SelectMap` is a wrapper around a `Select` rather then use
/// a unique id to find out what signal has been asserts, `SelectMap`
/// will return an supplied object.
pub struct SelectMap<T> {
    select: Select,
    items: HashMap<usize, T>
}

impl<T> SelectMap<T> {
    /// Create a new empty `SelectMap`
    pub fn new() -> SelectMap<T> {
        SelectMap {
            select: Select::new(),
            items: HashMap::new()
        }
    }

    /// Add a `Signal` and an associated value into the `SelectMap`
    pub fn add(&mut self, signal: Signal, value: T) {
        let id = self.select.add(signal);
        self.items.insert(id, value);
    }

    /// This is a non-blocking attempt to get a `Signal` from a `SelectMap`
    /// this will return a `Some((Signal, T))` if there is a pending `Signal`
    /// in the select. Otherwise it will return `None`
    pub fn try_next(&mut self) -> Option<(Signal, T)> {
        self.select.try_next().map(|x| {
            let id = x.id();
            (x, self.items.remove(&id).unwrap())
        })
    }

    /// Get the number of items in the `SelectMap`
    pub fn len(&self) -> usize { self.items.len() }
}

impl<T> Iterator for SelectMap<T> {
    type Item = (Signal, T);

    fn next(&mut self) -> Option<(Signal, T)> {
        self.select.next().map(|x| {
            let id = x.id();
            (x, self.items.remove(&id).unwrap())
        })
    }
}

impl<T> Signals for SelectMap<T> {
    fn signal(&self) -> Signal {
        self.select.signal()
    }
}
<|endoftext|>


<commit_before>extern crate toml;
extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate handlebars_iron as hbs;

use std::io::prelude::*;
use std::fs::{ File };
use std::path::Path;

use self::iron::prelude::*;
use self::mount::Mount;
use self::router::Router;
use self::staticfile::Static;
use self::hbs::{ HandlebarsEngine, DirectorySource };

use routers;

pub fn server() {
	// 解析配置文件
	let mut config_file = File::open("./src/Config.toml".to_string()).unwrap();
	let mut buffer = String::new();
	config_file.read_to_string(&mut buffer).unwrap();
	let config_toml = toml::Parser::new(buffer.to_string().as_str()).parse().unwrap();
	let config_basic = config_toml.get("basic").unwrap();

	let config_theme = config_basic.lookup("theme").unwrap();
	let theme = config_theme.as_str().unwrap();

	// 设置模板目录
	let mut hbse = HandlebarsEngine::new();
	hbse.add(Box::new(DirectorySource::new(("./src/themes/".to_string() + theme + "/templates/").as_str(), ".hbs")));
	hbse.reload().unwrap();

	// 设置路由
	let mut router = Router::new();
	router.get("/", routers::home::home, "index");
	router.get("/:page", routers::home::home, "home");
	router.get("/posts/:id", routers::post::post, "posts");

	// 设置静态文件
	let mut mount = Mount::new();
	mount.mount("/", router);
	mount.mount("/static/", Static::new(Path::new(("./src/themes/".to_string() + theme + "/static/").as_str())));

	// 追加中间件
	let mut chain = Chain::new(mount);
	chain.link_after(hbse);
  chain.link_after(routers::error::Error404);

	Iron::new(chain).http("localhost:4000").unwrap();
}
<commit_msg>Server: update hostname<commit_after>extern crate toml;
extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate handlebars_iron as hbs;

use std::io::prelude::*;
use std::fs::{ File };
use std::path::Path;

use self::iron::prelude::*;
use self::mount::Mount;
use self::router::Router;
use self::staticfile::Static;
use self::hbs::{ HandlebarsEngine, DirectorySource };

use routers;

pub fn server() {
	// 解析配置文件
	let mut config_file = File::open("./src/Config.toml".to_string()).unwrap();
	let mut buffer = String::new();
	config_file.read_to_string(&mut buffer).unwrap();
	let config_toml = toml::Parser::new(buffer.to_string().as_str()).parse().unwrap();
	let config_basic = config_toml.get("basic").unwrap();

	let config_theme = config_basic.lookup("theme").unwrap();
	let theme = config_theme.as_str().unwrap();

	// 设置模板目录
	let mut hbse = HandlebarsEngine::new();
	hbse.add(Box::new(DirectorySource::new(("./src/themes/".to_string() + theme + "/templates/").as_str(), ".hbs")));
	hbse.reload().unwrap();

	// 设置路由
	let mut router = Router::new();
	router.get("/", routers::home::home, "index");
	router.get("/:page", routers::home::home, "home");
	router.get("/posts/:id", routers::post::post, "posts");

	// 设置静态文件
	let mut mount = Mount::new();
	mount.mount("/", router);
	mount.mount("/static/", Static::new(Path::new(("./src/themes/".to_string() + theme + "/static/").as_str())));

	// 追加中间件
	let mut chain = Chain::new(mount);
	chain.link_after(hbse);
  chain.link_after(routers::error::Error404);

	Iron::new(chain).http("0.0.0.0:4000").unwrap();
}
<|endoftext|>


<commit_before>use num::{ Float, ToPrimitive, FromPrimitive };
use frame::Frameable;
use color::{ Color, Colorable };
use dimensions::Dimensions;
use label;
use mouse::Mouse;
use graphics::Graphics;
use graphics::character::CharacterCache;
use point::Point;
use rectangle;
use ui_context::{ UIID, UiContext };
use utils::{
    clamp,
    percentage,
    value_from_perc,
};
use widget::Widget;
use vecmath::vec2_add;

/// Represents the state of the Button widget.
#[derive(PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(Slider, State, Widget::Slider(State::Normal));

/// Check the current state of the slider.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _ => Normal,
    }
}

/// A context on which the builder pattern can be implemented.
pub struct Slider<'a, T, F> {
    ui_id: UIID,
    value: T,
    min: T,
    max: T,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
}

impl<'a, T, F> Slider<'a, T, F> {
    /// A button builder method to be implemented by the UiContext.
    pub fn new(ui_id: UIID, value: T, min: T, max: T) -> Slider<'a, T, F> {
        Slider {
            ui_id: ui_id,
            value: value,
            min: min,
            max: max,
            pos: [0.0, 0.0],
            dim: [192.0, 48.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }
}

impl<'a, T, F> Colorable for Slider<'a, T, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, T, F> Frameable for Slider<'a, T, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

/*
quack! {
    slider: Slider['a, T, F]
    get:
        fn () -> Size [] { Size(slider.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::Slider(State::Normal))
        }
        fn () -> Id [] { Id(slider.ui_id) }
    set:
        fn (val: Callback<F>) [where F: FnMut(T) + 'a] {
            slider.maybe_callback = Some(val.0)
        }
        fn (val: LabelText<'a>) [] { slider.maybe_label = Some(val.0) }
        fn (val: LabelColor) [] { slider.maybe_label_color = Some(val.0) }
        fn (val: LabelFontSize) [] { slider.maybe_label_font_size = Some(val.0) }
        fn (val: Position) [] { slider.pos = val.0 }
        fn (val: Size) [] { slider.dim = val.0 }
    action:
}
*/

impl<'a, T, F> ::draw::Drawable for Slider<'a, T, F>
    where
        T: Float + FromPrimitive + ToPrimitive,
        F: FnMut(T) + 'a
{

    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {

        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let is_over = rectangle::is_over(self.pos, mouse.pos, self.dim);
        let new_state = get_new_state(is_over, state, mouse);

        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let frame_w2 = frame_w * 2.0;
        let frame_color = self.maybe_frame_color.unwrap_or(uic.theme.frame_color);

        let is_horizontal = self.dim[0] > self.dim[1];
        let (new_value, pad_pos, pad_dim) = if is_horizontal {
            // Horizontal.
            let p = vec2_add(self.pos, [frame_w, frame_w]);
            let max_w = self.dim[0] - frame_w2;
            let w = match (is_over, state, new_state) {
                (true, State::Highlighted, State::Clicked) | (_, State::Clicked, State::Clicked)  =>
                     clamp(mouse.pos[0] - p[0], 0f64, max_w),
                _ => clamp(percentage(self.value, self.min, self.max) as f64 * max_w, 0f64, max_w),
            };
            let h = self.dim[1] - frame_w2;
            let new_value = value_from_perc((w / max_w) as f32, self.min, self.max);
            (new_value, p, [w, h])
        } else {
            // Vertical.
            let max_h = self.dim[1] - frame_w2;
            let corner = vec2_add(self.pos, [frame_w, frame_w]);
            let y_max = corner[1] + max_h;
            let (h, p) = match (is_over, state, new_state) {
                (true, State::Highlighted, State::Clicked) | (_, State::Clicked, State::Clicked) => {
                    let p = [corner[0], clamp(mouse.pos[1], corner[1], y_max)];
                    let h = clamp(max_h - (p[1] - corner[1]), 0.0, max_h);
                    (h, p)
                },
                _ => {
                    let h = clamp(percentage(self.value, self.min, self.max) as f64 * max_h, 0.0, max_h);
                    let p = [corner[0], corner[1] + max_h - h];
                    (h, p)
                },
            };
            let w = self.dim[0] - frame_w2;
            let new_value = value_from_perc((h / max_h) as f32, self.min, self.max);
            (new_value, p, [w, h])
        };

        // Callback.
        match self.maybe_callback {
            Some(ref mut callback) => {
                if self.value != new_value || match (state, new_state) {
                    (State::Highlighted, State::Clicked) | (State::Clicked, State::Highlighted) => true,
                    _ => false,
                } { (*callback)(new_value) }
            }, None => (),
        }

        // Draw.
        let rect_state = new_state.as_rectangle_state();
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);

        // Rectangle frame / backdrop.
        rectangle::draw(uic.win_w, uic.win_h, graphics, rect_state,
                        self.pos, self.dim, None, frame_color);
        // Slider rectangle.
        rectangle::draw(uic.win_w, uic.win_h, graphics, rect_state,
                        pad_pos, pad_dim, None, color);

        // If there's a label, draw it.
        if let Some(text) = self.maybe_label {
            let text_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
            let size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
            let is_horizontal = self.dim[0] > self.dim[1];
            let l_pos = if is_horizontal {
                let x = pad_pos[0] + (pad_dim[1] - size as f64) / 2.0;
                let y = pad_pos[1] + (pad_dim[1] - size as f64) / 2.0;
                [x, y]
            } else {
                let label_w = label::width(uic, size, &text);
                let x = pad_pos[0] + (pad_dim[0] - label_w) / 2.0;
                let y = pad_pos[1] + pad_dim[1] - pad_dim[0] - frame_w;
                [x, y]
            };
            // Draw the label.
            uic.draw_text(graphics, l_pos, size, text_color, &text);
        }

        set_state(uic, self.ui_id, Widget::Slider(new_state), self.pos, self.dim);

    }
}
<commit_msg>Implemented `Callable` for `Slider`<commit_after>use num::{ Float, ToPrimitive, FromPrimitive };
use callback::Callable;
use frame::Frameable;
use color::{ Color, Colorable };
use dimensions::Dimensions;
use label;
use mouse::Mouse;
use graphics::Graphics;
use graphics::character::CharacterCache;
use point::Point;
use rectangle;
use ui_context::{ UIID, UiContext };
use utils::{
    clamp,
    percentage,
    value_from_perc,
};
use widget::Widget;
use vecmath::vec2_add;

/// Represents the state of the Button widget.
#[derive(PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(Slider, State, Widget::Slider(State::Normal));

/// Check the current state of the slider.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _ => Normal,
    }
}

/// A context on which the builder pattern can be implemented.
pub struct Slider<'a, T, F> {
    ui_id: UIID,
    value: T,
    min: T,
    max: T,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
}

impl<'a, T, F> Slider<'a, T, F> {
    /// A button builder method to be implemented by the UiContext.
    pub fn new(ui_id: UIID, value: T, min: T, max: T) -> Slider<'a, T, F> {
        Slider {
            ui_id: ui_id,
            value: value,
            min: min,
            max: max,
            pos: [0.0, 0.0],
            dim: [192.0, 48.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }
}

impl<'a, T, F> Colorable for Slider<'a, T, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, T, F> Frameable for Slider<'a, T, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, T, F> Callable<F> for Slider<'a, T, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

/*
quack! {
    slider: Slider['a, T, F]
    get:
        fn () -> Size [] { Size(slider.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::Slider(State::Normal))
        }
        fn () -> Id [] { Id(slider.ui_id) }
    set:
        fn (val: LabelText<'a>) [] { slider.maybe_label = Some(val.0) }
        fn (val: LabelColor) [] { slider.maybe_label_color = Some(val.0) }
        fn (val: LabelFontSize) [] { slider.maybe_label_font_size = Some(val.0) }
        fn (val: Position) [] { slider.pos = val.0 }
        fn (val: Size) [] { slider.dim = val.0 }
    action:
}
*/

impl<'a, T, F> ::draw::Drawable for Slider<'a, T, F>
    where
        T: Float + FromPrimitive + ToPrimitive,
        F: FnMut(T) + 'a
{

    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {

        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let is_over = rectangle::is_over(self.pos, mouse.pos, self.dim);
        let new_state = get_new_state(is_over, state, mouse);

        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let frame_w2 = frame_w * 2.0;
        let frame_color = self.maybe_frame_color.unwrap_or(uic.theme.frame_color);

        let is_horizontal = self.dim[0] > self.dim[1];
        let (new_value, pad_pos, pad_dim) = if is_horizontal {
            // Horizontal.
            let p = vec2_add(self.pos, [frame_w, frame_w]);
            let max_w = self.dim[0] - frame_w2;
            let w = match (is_over, state, new_state) {
                (true, State::Highlighted, State::Clicked) | (_, State::Clicked, State::Clicked)  =>
                     clamp(mouse.pos[0] - p[0], 0f64, max_w),
                _ => clamp(percentage(self.value, self.min, self.max) as f64 * max_w, 0f64, max_w),
            };
            let h = self.dim[1] - frame_w2;
            let new_value = value_from_perc((w / max_w) as f32, self.min, self.max);
            (new_value, p, [w, h])
        } else {
            // Vertical.
            let max_h = self.dim[1] - frame_w2;
            let corner = vec2_add(self.pos, [frame_w, frame_w]);
            let y_max = corner[1] + max_h;
            let (h, p) = match (is_over, state, new_state) {
                (true, State::Highlighted, State::Clicked) | (_, State::Clicked, State::Clicked) => {
                    let p = [corner[0], clamp(mouse.pos[1], corner[1], y_max)];
                    let h = clamp(max_h - (p[1] - corner[1]), 0.0, max_h);
                    (h, p)
                },
                _ => {
                    let h = clamp(percentage(self.value, self.min, self.max) as f64 * max_h, 0.0, max_h);
                    let p = [corner[0], corner[1] + max_h - h];
                    (h, p)
                },
            };
            let w = self.dim[0] - frame_w2;
            let new_value = value_from_perc((h / max_h) as f32, self.min, self.max);
            (new_value, p, [w, h])
        };

        // Callback.
        match self.maybe_callback {
            Some(ref mut callback) => {
                if self.value != new_value || match (state, new_state) {
                    (State::Highlighted, State::Clicked) | (State::Clicked, State::Highlighted) => true,
                    _ => false,
                } { (*callback)(new_value) }
            }, None => (),
        }

        // Draw.
        let rect_state = new_state.as_rectangle_state();
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);

        // Rectangle frame / backdrop.
        rectangle::draw(uic.win_w, uic.win_h, graphics, rect_state,
                        self.pos, self.dim, None, frame_color);
        // Slider rectangle.
        rectangle::draw(uic.win_w, uic.win_h, graphics, rect_state,
                        pad_pos, pad_dim, None, color);

        // If there's a label, draw it.
        if let Some(text) = self.maybe_label {
            let text_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
            let size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
            let is_horizontal = self.dim[0] > self.dim[1];
            let l_pos = if is_horizontal {
                let x = pad_pos[0] + (pad_dim[1] - size as f64) / 2.0;
                let y = pad_pos[1] + (pad_dim[1] - size as f64) / 2.0;
                [x, y]
            } else {
                let label_w = label::width(uic, size, &text);
                let x = pad_pos[0] + (pad_dim[0] - label_w) / 2.0;
                let y = pad_pos[1] + pad_dim[1] - pad_dim[0] - frame_w;
                [x, y]
            };
            // Draw the label.
            uic.draw_text(graphics, l_pos, size, text_color, &text);
        }

        set_state(uic, self.ui_id, Widget::Slider(new_state), self.pos, self.dim);

    }
}
<|endoftext|>


<commit_before>use nom::{
  Consumer, ConsumerState,
  ErrorKind,
  HexDisplay,
  Input, IResult,
  Move, Needed,
};

use metadata;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  pub info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
  consumer_state: ConsumerState<(), ErrorKind, Move>,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      let consumed = Move::Consume(0);

      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        consumer_state: ConsumerState::Continue(consumed),
      }
    }
  )
);

impl Stream {
  fn handle_marker(&mut self, input: &[u8]) {
    match tag!(input, "fLaC") {
      IResult::Done(i, _)       => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);

        self.state          = ParserState::Metadata;
        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)         => {
        let kind = ErrorKind::Custom(0);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(size) => {
        let needed = Move::Await(size);

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }

  fn handle_metadata(&mut self, input: &[u8]) {
    match metadata::block(input) {
      IResult::Done(i, block) => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);
        let is_last  = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)       => {
        let kind = ErrorKind::Custom(1);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(s)  => {
        let size = if let Needed::Size(length) = s {
          length
        } else {
          1024
        };
        let needed = Move::Await(Needed::Size(size));

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }

  fn handle_frame(&mut self, input: &[u8]) {
    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);

        self.frames.push(frame);

        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)       => {
        let kind = ErrorKind::Custom(2);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(s)  => {
        let size = if let Needed::Size(length) = s {
          length
        } else {
          self.info.max_frame_size as usize
        };
        let needed = Move::Await(Needed::Size(size));

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }
}

impl<'a> Consumer<&'a [u8], (), ErrorKind, Move> for Stream {
  fn state(&self) -> &ConsumerState<(), ErrorKind, Move> {
    &self.consumer_state
  }

  fn handle(&mut self, input: Input<&'a [u8]>)
            -> &ConsumerState<(), ErrorKind, Move> {
    match input {
      Input::Element(i) | Input::Eof(Some(i)) => {
        match self.state {
          ParserState::Marker   => self.handle_marker(i),
          ParserState::Metadata => self.handle_metadata(i),
          ParserState::Frame    => self.handle_frame(i),
        }
      }
      Input::Empty | Input::Eof(None)         => {
        self.consumer_state = match self.state {
          ParserState::Marker   => ConsumerState::Error(ErrorKind::Custom(0)),
          ParserState::Metadata => ConsumerState::Error(ErrorKind::Custom(1)),
          ParserState::Frame    => ConsumerState::Done(Move::Consume(0), ()),
        };
      }
    }

    &self.consumer_state
  }
}
<commit_msg>Add `Stream::new` for simple initialization<commit_after>use nom::{
  Consumer, ConsumerState,
  ErrorKind,
  HexDisplay,
  Input, IResult,
  Move, Needed,
};

use metadata;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  pub info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
  consumer_state: ConsumerState<(), ErrorKind, Move>,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      let consumed = Move::Consume(0);

      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        consumer_state: ConsumerState::Continue(consumed),
      }
    }
  )
);

impl Stream {
  pub fn new() -> Stream {
    let consumed = Move::Consume(0);

    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      consumer_state: ConsumerState::Continue(consumed),
    }
  }

  fn handle_marker(&mut self, input: &[u8]) {
    match tag!(input, "fLaC") {
      IResult::Done(i, _)       => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);

        self.state          = ParserState::Metadata;
        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)         => {
        let kind = ErrorKind::Custom(0);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(size) => {
        let needed = Move::Await(size);

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }

  fn handle_metadata(&mut self, input: &[u8]) {
    match metadata::block(input) {
      IResult::Done(i, block) => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);
        let is_last  = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)       => {
        let kind = ErrorKind::Custom(1);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(s)  => {
        let size = if let Needed::Size(length) = s {
          length
        } else {
          1024
        };
        let needed = Move::Await(Needed::Size(size));

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }

  fn handle_frame(&mut self, input: &[u8]) {
    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);

        self.frames.push(frame);

        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)       => {
        let kind = ErrorKind::Custom(2);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(s)  => {
        let size = if let Needed::Size(length) = s {
          length
        } else {
          self.info.max_frame_size as usize
        };
        let needed = Move::Await(Needed::Size(size));

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }
}

impl<'a> Consumer<&'a [u8], (), ErrorKind, Move> for Stream {
  fn state(&self) -> &ConsumerState<(), ErrorKind, Move> {
    &self.consumer_state
  }

  fn handle(&mut self, input: Input<&'a [u8]>)
            -> &ConsumerState<(), ErrorKind, Move> {
    match input {
      Input::Element(i) | Input::Eof(Some(i)) => {
        match self.state {
          ParserState::Marker   => self.handle_marker(i),
          ParserState::Metadata => self.handle_metadata(i),
          ParserState::Frame    => self.handle_frame(i),
        }
      }
      Input::Empty | Input::Eof(None)         => {
        self.consumer_state = match self.state {
          ParserState::Marker   => ConsumerState::Error(ErrorKind::Custom(0)),
          ParserState::Metadata => ConsumerState::Error(ErrorKind::Custom(1)),
          ParserState::Frame    => ConsumerState::Done(Move::Consume(0), ()),
        };
      }
    }

    &self.consumer_state
  }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::cmp::Ordering;
use stem;
use tokenize::tokenize;

pub struct TfIdf {
	//token counts for inverse document frequency
	doc_freqs: HashMap<String, usize>,

	//documents joined into a single HashMap
	pub term_freqs: HashMap<String, usize>,

	//total count of documents inserted
	doc_count: usize,

	//total count of words inserted
	word_count: usize
}

impl TfIdf {
	pub fn new() -> TfIdf {
		TfIdf {
			doc_freqs: HashMap::new(),
			term_freqs: HashMap::new(),
			doc_count: 0,
			word_count: 0
		}
	}

	//Add documents to test frequency against
	pub fn add(&mut self, corpus: &str) {
		let mut tokens = get_tokenized_and_stemmed(corpus);
		let tokens_ref = &mut tokens;

		for token in tokens_ref.into_iter() {
			let entry = self.term_freqs.entry(token.to_owned()).or_insert(0);

			*entry += 1;
			self.word_count += 1;
		}

		tokens_ref.sort();
		tokens_ref.dedup();

		for token in tokens_ref.into_iter() {
			let entry = self.doc_freqs.entry(token.to_owned()).or_insert(0);

			*entry += 1;
		}

		self.doc_count += 1;
	}

	//Calculate term frequency for one term
	fn tf(&self, term: &str) -> f32 {
		match self.term_freqs.get(term) {
			Some(freq) => freq.clone() as f32 / self.word_count as f32,
			None => 0.0f32
		}
	}

	//Calculate inverse document frequency for one term
	fn idf(&self, term: &str) -> f32 {
		let doc_freq = match self.doc_freqs.get(term) {
			Some(freq) => freq.clone() as f32,
			None => 0.0f32
		};

		let ratio = self.doc_count as f32 / 1.0f32 + doc_freq;

		ratio.ln()
	}

	//Calculate tf-idf for one term
	fn tf_idf(&self, term: &str) -> f32 {
		let tf = self.tf(term);
		let idf = self.idf(term);

		println!("{:?}", tf);
		println!("{:?}", idf);

		tf * idf
	}

	//Get tf-idf of a string of one or more terms
	pub fn get(&self, terms: &str) -> f32 {
		let tokens = get_tokenized_and_stemmed(terms);
		let token_ref = &tokens;

		let score: f32 = token_ref.into_iter()
			    .map(|x| self.tf_idf(&x))
			    .fold(0.0f32, |acc, x| acc + x); //add together to later divide by token length to get an average

	  //average the scores
		score / tokens.len() as f32
	}
}

fn get_tokenized_and_stemmed(text: &str) -> Vec<String> {
  let tokenized_text = tokenize(text);
  tokenized_text.into_iter()
                .map(|text| stem::get(text))
                .collect()
}<commit_msg>remove debug printing in tf_idf.rs<commit_after>use std::collections::HashMap;
use std::cmp::Ordering;
use stem;
use tokenize::tokenize;

pub struct TfIdf {
	//token counts for inverse document frequency
	doc_freqs: HashMap<String, usize>,

	//documents joined into a single HashMap
	pub term_freqs: HashMap<String, usize>,

	//total count of documents inserted
	doc_count: usize,

	//total count of words inserted
	word_count: usize
}

impl TfIdf {
	pub fn new() -> TfIdf {
		TfIdf {
			doc_freqs: HashMap::new(),
			term_freqs: HashMap::new(),
			doc_count: 0,
			word_count: 0
		}
	}

	//Add documents to test frequency against
	pub fn add(&mut self, corpus: &str) {
		let mut tokens = get_tokenized_and_stemmed(corpus);
		let tokens_ref = &mut tokens;

		for token in tokens_ref.into_iter() {
			let entry = self.term_freqs.entry(token.to_owned()).or_insert(0);

			*entry += 1;
			self.word_count += 1;
		}

		tokens_ref.sort();
		tokens_ref.dedup();

		for token in tokens_ref.into_iter() {
			let entry = self.doc_freqs.entry(token.to_owned()).or_insert(0);

			*entry += 1;
		}

		self.doc_count += 1;
	}

	//Calculate term frequency for one term
	fn tf(&self, term: &str) -> f32 {
		match self.term_freqs.get(term) {
			Some(freq) => freq.clone() as f32 / self.word_count as f32,
			None => 0.0f32
		}
	}

	//Calculate inverse document frequency for one term
	fn idf(&self, term: &str) -> f32 {
		let doc_freq = match self.doc_freqs.get(term) {
			Some(freq) => freq.clone() as f32,
			None => 0.0f32
		};

		let ratio = self.doc_count as f32 / 1.0f32 + doc_freq;

		ratio.ln()
	}

	//Calculate tf-idf for one term
	fn tf_idf(&self, term: &str) -> f32 {
		let tf = self.tf(term);
		let idf = self.idf(term);

		tf * idf
	}

	//Get tf-idf of a string of one or more terms
	pub fn get(&self, terms: &str) -> f32 {
		let tokens = get_tokenized_and_stemmed(terms);
		let token_ref = &tokens;

		let score: f32 = token_ref.into_iter()
			    .map(|x| self.tf_idf(&x))
			    .fold(0.0f32, |acc, x| acc + x); //add together to later divide by token length to get an average

	  //average the scores
		score / tokens.len() as f32
	}
}

fn get_tokenized_and_stemmed(text: &str) -> Vec<String> {
  let tokenized_text = tokenize(text);
  tokenized_text.into_iter()
                .map(|text| stem::get(text))
                .collect()
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ffi::CStr;
use std::fmt;
use super::event::SBEvent;
use super::frame::SBFrame;
use super::process::SBProcess;
use super::stream::SBStream;
use super::value::SBValue;
use super::{lldb_tid_t, StopReason};
use sys;

/// A thread of execution.
///
/// `SBThread`s can be referred to by their ID, which maps to the system
/// specific thread identifier, or by `IndexID`.  The ID may or may not
/// be unique depending on whether the system reuses its thread identifiers.
/// The `IndexID` is a monotonically increasing identifier that will always
/// uniquely reference a particular thread, and when that thread goes
/// away it will not be reused.
///
/// # Thread State
///
/// ...
///
/// # Execution Control
///
/// ...
///
/// # Frames
///
/// The thread contains [stack frames]. These can be iterated
/// over with [`frames`]:
///
/// ```no_run
/// # use lldb::{SBFrame, SBThread};
/// # fn look_at_frames(thread: SBThread) {
/// // Iterate over the frames...
/// for frame in thread.frames() {
///     println!("Hello {:?}!", frame);
/// }
/// // Or collect them into a vector!
/// let frames = thread.frames().collect::<Vec<SBFrame>>();
/// # }
/// ```
///
/// Some functions operate on the 'currently selected frame'. This can
/// retrieved via [`selected_frame`] and set via [`set_selected_frame`].
///
///
/// # Events
///
/// ...
///
/// [stack frames]: struct.SBFrame.html
/// [`frames`]: #method.frames
/// [`selected_frame`]: #method.selected_frame
/// [`set_selected_frame`]: #method.set_selected_frame
pub struct SBThread {
    /// The underlying raw `SBThreadRef`.
    pub raw: sys::SBThreadRef,
}

impl SBThread {
    /// Construct a new `SBThread`.
    pub fn wrap(raw: sys::SBThreadRef) -> SBThread {
        SBThread { raw: raw }
    }

    /// Construct a new `Some(SBThread)` or `None`.
    pub fn maybe_wrap(raw: sys::SBThreadRef) -> Option<SBThread> {
        if unsafe { sys::SBThreadIsValid(raw) != 0 } {
            Some(SBThread { raw: raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBThread` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBThreadIsValid(self.raw) != 0 }
    }

    #[allow(missing_docs)]
    pub fn broadcaster_class_name() -> &'static str {
        unsafe {
            match CStr::from_ptr(sys::SBThreadGetBroadcasterClassName()).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Get the stop reason for this thread.
    pub fn stop_reason(&self) -> StopReason {
        unsafe { sys::SBThreadGetStopReason(self.raw) }
    }

    /// The return value from the last stop if we just stopped due
    /// to stepping out of a function
    pub fn stop_return_value(&self) -> Option<SBValue> {
        SBValue::maybe_wrap(unsafe { sys::SBThreadGetStopReturnValue(self.raw) })
    }

    /// Returns a unique thread identifier for the current `SBThread`
    /// that will remain constant throughout the thread's lifetime in
    /// this process and will not be reused by another thread during this
    /// process lifetime.  On Mac OS X systems, this is a system-wide
    /// unique thread identifier; this identifier is also used by
    /// other tools like sample which helps to associate data from
    /// those tools with lldb.  See related `SBThread::index_id`.
    pub fn thread_id(&self) -> lldb_tid_t {
        unsafe { sys::SBThreadGetThreadID(self.raw) }
    }

    /// Return the index number for this `SBThread`.  The index
    /// number is the same thing that a user gives as an argument
    /// to `thread select` in the command line lldb.
    ///
    /// These numbers start at `1` (for the first thread lldb sees
    /// in a debug session) and increments up throughout the process
    /// lifetime.  An index number will not be reused for a different
    /// thread later in a process - thread 1 will always be associated
    /// with the same thread.  See related `SBThread::thread_id`.
    pub fn index_id(&self) -> u32 {
        unsafe { sys::SBThreadGetIndexID(self.raw) }
    }

    /// Get an iterator over the [frames] known to this thread instance.
    ///
    /// [frames]: struct.SBFrame.html
    pub fn frames(&self) -> SBThreadFrameIter {
        SBThreadFrameIter {
            thread: self,
            idx: 0,
        }
    }

    /// Get the currently selected frame for this thread.
    pub fn selected_frame(&self) -> SBFrame {
        SBFrame::wrap(unsafe { sys::SBThreadGetSelectedFrame(self.raw) })
    }

    /// Set the currently selected frame for this thread. This takes a frame index.
    pub fn set_selected_frame(&self, frame_index: u32) -> Option<SBFrame> {
        SBFrame::maybe_wrap(unsafe { sys::SBThreadSetSelectedFrame(self.raw, frame_index) })
    }

    /// Get the process in which this thread is running.
    pub fn process(&self) -> SBProcess {
        SBProcess::wrap(unsafe { sys::SBThreadGetProcess(self.raw) })
    }

    #[allow(missing_docs)]
    pub fn event_as_thread_event(event: &SBEvent) -> Option<SBThreadEvent> {
        if unsafe { sys::SBThreadEventIsThreadEvent(event.raw) != 0 } {
            Some(SBThreadEvent::new(event))
        } else {
            None
        }
    }
}

/// Iterate over the [frames] in a [thread].
///
/// [frames]: struct.SBFrame.html
/// [thread]: struct.SBThread.html
pub struct SBThreadFrameIter<'d> {
    thread: &'d SBThread,
    idx: usize,
}

impl<'d> Iterator for SBThreadFrameIter<'d> {
    type Item = SBFrame;

    fn next(&mut self) -> Option<SBFrame> {
        if self.idx < unsafe { sys::SBThreadGetNumFrames(self.thread.raw) as usize } {
            let r = Some(SBFrame::wrap(unsafe {
                sys::SBThreadGetFrameAtIndex(self.thread.raw, self.idx as u32)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }
}

impl fmt::Debug for SBThread {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBThreadGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBThread {{ {} }}", stream.data())
    }
}

impl Drop for SBThread {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBThread(self.raw) };
    }
}

#[allow(missing_docs)]
pub struct SBThreadEvent<'e> {
    event: &'e SBEvent,
}

#[allow(missing_docs)]
impl<'e> SBThreadEvent<'e> {
    pub fn new(event: &'e SBEvent) -> Self {
        SBThreadEvent { event: event }
    }

    pub fn thread(&self) -> SBThread {
        SBThread::wrap(unsafe { sys::SBThreadGetThreadFromEvent(self.event.raw) })
    }

    pub fn frame(&self) -> Option<SBFrame> {
        SBFrame::maybe_wrap(unsafe { sys::SBThreadGetStackFrameFromEvent(self.event.raw) })
    }
}
<commit_msg>Fill in some missing SBThread doc comments.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ffi::CStr;
use std::fmt;
use super::event::SBEvent;
use super::frame::SBFrame;
use super::process::SBProcess;
use super::stream::SBStream;
use super::value::SBValue;
use super::{lldb_tid_t, StopReason};
use sys;

/// A thread of execution.
///
/// `SBThread`s can be referred to by their ID, which maps to the system
/// specific thread identifier, or by `IndexID`.  The ID may or may not
/// be unique depending on whether the system reuses its thread identifiers.
/// The `IndexID` is a monotonically increasing identifier that will always
/// uniquely reference a particular thread, and when that thread goes
/// away it will not be reused.
///
/// # Thread State
///
/// ...
///
/// # Execution Control
///
/// ...
///
/// # Frames
///
/// The thread contains [stack frames]. These can be iterated
/// over with [`frames`]:
///
/// ```no_run
/// # use lldb::{SBFrame, SBThread};
/// # fn look_at_frames(thread: SBThread) {
/// // Iterate over the frames...
/// for frame in thread.frames() {
///     println!("Hello {:?}!", frame);
/// }
/// // Or collect them into a vector!
/// let frames = thread.frames().collect::<Vec<SBFrame>>();
/// # }
/// ```
///
/// Some functions operate on the 'currently selected frame'. This can
/// retrieved via [`selected_frame`] and set via [`set_selected_frame`].
///
///
/// # Events
///
/// ...
///
/// [stack frames]: struct.SBFrame.html
/// [`frames`]: #method.frames
/// [`selected_frame`]: #method.selected_frame
/// [`set_selected_frame`]: #method.set_selected_frame
pub struct SBThread {
    /// The underlying raw `SBThreadRef`.
    pub raw: sys::SBThreadRef,
}

impl SBThread {
    /// Construct a new `SBThread`.
    pub fn wrap(raw: sys::SBThreadRef) -> SBThread {
        SBThread { raw: raw }
    }

    /// Construct a new `Some(SBThread)` or `None`.
    pub fn maybe_wrap(raw: sys::SBThreadRef) -> Option<SBThread> {
        if unsafe { sys::SBThreadIsValid(raw) != 0 } {
            Some(SBThread { raw: raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBThread` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBThreadIsValid(self.raw) != 0 }
    }

    #[allow(missing_docs)]
    pub fn broadcaster_class_name() -> &'static str {
        unsafe {
            match CStr::from_ptr(sys::SBThreadGetBroadcasterClassName()).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Get the stop reason for this thread.
    pub fn stop_reason(&self) -> StopReason {
        unsafe { sys::SBThreadGetStopReason(self.raw) }
    }

    /// The return value from the last stop if we just stopped due
    /// to stepping out of a function
    pub fn stop_return_value(&self) -> Option<SBValue> {
        SBValue::maybe_wrap(unsafe { sys::SBThreadGetStopReturnValue(self.raw) })
    }

    /// Returns a unique thread identifier for the current `SBThread`
    /// that will remain constant throughout the thread's lifetime in
    /// this process and will not be reused by another thread during this
    /// process lifetime.  On Mac OS X systems, this is a system-wide
    /// unique thread identifier; this identifier is also used by
    /// other tools like sample which helps to associate data from
    /// those tools with lldb.  See related `SBThread::index_id`.
    pub fn thread_id(&self) -> lldb_tid_t {
        unsafe { sys::SBThreadGetThreadID(self.raw) }
    }

    /// Return the index number for this `SBThread`.  The index
    /// number is the same thing that a user gives as an argument
    /// to `thread select` in the command line lldb.
    ///
    /// These numbers start at `1` (for the first thread lldb sees
    /// in a debug session) and increments up throughout the process
    /// lifetime.  An index number will not be reused for a different
    /// thread later in a process - thread 1 will always be associated
    /// with the same thread.  See related `SBThread::thread_id`.
    pub fn index_id(&self) -> u32 {
        unsafe { sys::SBThreadGetIndexID(self.raw) }
    }

    /// Get an iterator over the [frames] known to this thread instance.
    ///
    /// [frames]: struct.SBFrame.html
    pub fn frames(&self) -> SBThreadFrameIter {
        SBThreadFrameIter {
            thread: self,
            idx: 0,
        }
    }

    /// Get the currently selected frame for this thread.
    pub fn selected_frame(&self) -> SBFrame {
        SBFrame::wrap(unsafe { sys::SBThreadGetSelectedFrame(self.raw) })
    }

    /// Set the currently selected frame for this thread. This takes a frame index.
    pub fn set_selected_frame(&self, frame_index: u32) -> Option<SBFrame> {
        SBFrame::maybe_wrap(unsafe { sys::SBThreadSetSelectedFrame(self.raw, frame_index) })
    }

    /// Get the process in which this thread is running.
    pub fn process(&self) -> SBProcess {
        SBProcess::wrap(unsafe { sys::SBThreadGetProcess(self.raw) })
    }

    /// If the given event is a thread event, return it as an
    /// `SBThreadEvent`. Otherwise, return `None`.
    pub fn event_as_thread_event(event: &SBEvent) -> Option<SBThreadEvent> {
        if unsafe { sys::SBThreadEventIsThreadEvent(event.raw) != 0 } {
            Some(SBThreadEvent::new(event))
        } else {
            None
        }
    }
}

/// Iterate over the [frames] in a [thread].
///
/// [frames]: struct.SBFrame.html
/// [thread]: struct.SBThread.html
pub struct SBThreadFrameIter<'d> {
    thread: &'d SBThread,
    idx: usize,
}

impl<'d> Iterator for SBThreadFrameIter<'d> {
    type Item = SBFrame;

    fn next(&mut self) -> Option<SBFrame> {
        if self.idx < unsafe { sys::SBThreadGetNumFrames(self.thread.raw) as usize } {
            let r = Some(SBFrame::wrap(unsafe {
                sys::SBThreadGetFrameAtIndex(self.thread.raw, self.idx as u32)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }
}

impl fmt::Debug for SBThread {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBThreadGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBThread {{ {} }}", stream.data())
    }
}

impl Drop for SBThread {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBThread(self.raw) };
    }
}

/// A thread event.
pub struct SBThreadEvent<'e> {
    event: &'e SBEvent,
}

impl<'e> SBThreadEvent<'e> {
    /// Construct a new `SBThreadEvent`.
    pub fn new(event: &'e SBEvent) -> Self {
        SBThreadEvent { event: event }
    }

    /// Get the thread from this thread event.
    pub fn thread(&self) -> SBThread {
        SBThread::wrap(unsafe { sys::SBThreadGetThreadFromEvent(self.event.raw) })
    }

    /// Get the frame from this thread event.
    pub fn frame(&self) -> Option<SBFrame> {
        SBFrame::maybe_wrap(unsafe { sys::SBThreadGetStackFrameFromEvent(self.event.raw) })
    }
}
<|endoftext|>


<commit_before>use ast::{Expr, ExprItem, Term};
use math::rich_number::RichNumber;
use eval::fixity::Fixity;
use eval::context_item::ContextItem;
use eval::eval_context::{EvalContext, EvalError};

#[derive(Debug, PartialEq, Clone)]
pub struct EvalTreeNode {
    item: ContextItem,
    children: Vec<EvalTreeNode>,
}

impl EvalTreeNode {
    pub fn new(item: ContextItem) -> EvalTreeNode {
        EvalTreeNode {
            item: item,
            children: Vec::new(),
        }
    }

    pub fn with_children(item: ContextItem, children: Vec<EvalTreeNode>) -> EvalTreeNode {
        let mut node = EvalTreeNode::new(item);
        node.children = children;

        node
    }

    pub fn from_expr(context: &EvalContext, expr: Expr) -> Result<EvalTreeNode, EvalError> {
        let mut nodes = try!(EvalTreeNode::convert_to_nodes(context, expr));

        while nodes.len() != 1 {
            let node_index = EvalTreeNode::left_highest_precedence(&nodes);
            if node_index.is_none() {
                return Err(EvalError::UnexpectedSymbols);
            }
            let node_index = node_index.unwrap();

            let params = try!(EvalTreeNode::drain_params(&mut nodes, node_index));

            let mut node = &mut nodes[node_index];
            node.children = params;
        }

        debug_assert!(nodes.len() == 1);
        Ok(nodes.pop().unwrap())
    }

    fn convert_to_nodes(context: &EvalContext, expr: Expr) -> Result<Vec<EvalTreeNode>, EvalError> {
        let mut nodes: Vec<EvalTreeNode> = Vec::new();

        for item in expr.into_iter() {
            nodes.push(match item {
                ExprItem::AnonymousFunction(function) => {
                    EvalTreeNode::new(ContextItem::function_defaults(function))
                },
                ExprItem::SingleTerm(term) => match term {
                    Term::Symbol(sym) => {
                        let item = context.get(&sym);
                        if item.is_none() {
                            return Err(EvalError::UndefinedSymbol(sym));
                        }
                        EvalTreeNode::new(item.unwrap())
                    },
                    Term::Number(num) => {
                        EvalTreeNode::new(
                            ContextItem::Number(
                                RichNumber::from(num)
                            )
                        )
                    },
                    Term::StringLiteral(value) => {
                        EvalTreeNode::new(
                            ContextItem::Constant(value)
                        )
                    },
                },
                ExprItem::Group(expr) => try!(EvalTreeNode::from_expr(context, expr)),
            });
        }

        Ok(nodes)
    }

    /// Returns the index of the leftmost node with the highest precedence
    /// Only returns ContextItems with precedence
    fn left_highest_precedence(nodes: &Vec<EvalTreeNode>) -> Option<usize> {
        // (index, precedence)
        let mut highest: Option<(usize, u8)> = None;

        for (i, node) in nodes.iter().enumerate() {
            // This node has already been taken care of
            if !node.children.is_empty() {
                continue;
            }

            let precedence = node.item.resolve_precedence();
            if precedence.is_none() {
                continue;
            }
            let precedence = *precedence.unwrap();

            // This MUST be less than, NOT less than or equal to to get the
            // leftmost item
            if highest.is_none() || highest.unwrap().1 < precedence {
                highest = Some((i, precedence));
            }
        }

        highest.map(|x| x.0)
    }

    // Removes the nodes adjacent to the node_index (but not including the
    // node_index) that correspond to the number of parameters expected
    // by that node in the direction specified by that node's fixity
    fn drain_params(nodes: &mut Vec<EvalTreeNode>, node_index: usize) -> Result<Vec<EvalTreeNode>, EvalError> {
        let fixity;
        let params;
        {
            let node = &nodes[node_index];

            // unwrap() is safe here because node item should be a definition or built in
            fixity = node.item.resolve_fixity().unwrap();
            params = node.item.resolve_params().unwrap();
            debug_assert!(params != 0);
        }

        Ok(match fixity {
            Fixity::Infix => {
                // Infix functions MUST have 2 parameters
                if params != 2 {
                    return Err(EvalError::InvalidSymbolDefinition {
                        expected_params: 2,
                        actual_params: params,
                    });
                }

                // It is vital that the second remove happen before the
                // first because this operation shifts all indexes to the left
                let second = nodes.remove(node_index + 1);
                let first = nodes.remove(node_index - 1);

                vec![first, second]
            },
            Fixity::Prefix => {
                let start;
                let end = node_index;

                // params > node_index would result in a negative sum
                if params > node_index || end >= nodes.len() {
                    return Err(EvalError::ExpectedParams(params));
                }
                // need to declare this here to avoid overflow
                start = node_index - params;

                nodes.drain(start..end).collect()
            },
            Fixity::Postfix => {
                // No need to worry about node_index being less than zero because we
                // are adding 1 here
                let start = node_index + 1;
                // The +1 in the end of the range is because ranges stop
                // at the index 1 before the end
                let end = node_index + params + 1;
                if end >= nodes.len() {
                    return Err(EvalError::ExpectedParams(params));
                }
                nodes.drain(start..end).collect()
            },
        })
    }
}

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

    use eval::fixity::Fixity;
    use eval::context_item::ContextItem;
    use eval::eval_context::EvalContext;
    use math::rich_number::RichNumber;

    #[test]
    fn creates_tree_with_correct_precedence() {
        // f 3 + (4 * 8 + 99 - x) - ((67)) / (x - g 4) + 32
        let expr: Expr = vec![
            ExprItem::SingleTerm(Term::Symbol("f".to_owned())),
            ExprItem::SingleTerm(Term::Number(3f64)),
            ExprItem::SingleTerm(Term::Symbol("+".to_owned())),
            ExprItem::Group(vec![
                ExprItem::SingleTerm(Term::Number(4f64)),
                ExprItem::SingleTerm(Term::Symbol("*".to_owned())),
                ExprItem::SingleTerm(Term::Number(8f64)),
                ExprItem::SingleTerm(Term::Symbol("+".to_owned())),
                ExprItem::SingleTerm(Term::Number(99f64)),
                ExprItem::SingleTerm(Term::Symbol("-".to_owned())),
                ExprItem::SingleTerm(Term::Symbol("x".to_owned())),
            ]),
            ExprItem::SingleTerm(Term::Symbol("-".to_owned())),
            ExprItem::Group(vec![
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(Term::Number(67f64)),
                ])
            ]),
            ExprItem::SingleTerm(Term::Symbol("/".to_owned())),
            ExprItem::Group(vec![
                ExprItem::SingleTerm(Term::Symbol("x".to_owned())),
                ExprItem::SingleTerm(Term::Symbol("-".to_owned())),
                ExprItem::SingleTerm(Term::Symbol("g".to_owned())),
                ExprItem::SingleTerm(Term::Number(4f64)),
            ]),
            ExprItem::SingleTerm(Term::Symbol("+".to_owned())),
            ExprItem::SingleTerm(Term::Number(32f64)),
        ];

        let mut context = basic_context();

        let expected_tree = {
            let nleaf = |n| EvalTreeNode::new(ContextItem::Number(RichNumber::from(n)));
            let lookup = |name| context.get(name).unwrap();

            EvalTreeNode::with_children(lookup("-"), vec![
                EvalTreeNode::with_children(lookup("+"), vec![
                    EvalTreeNode::with_children(lookup("f"), vec![
                        nleaf(3),
                    ]),
                    EvalTreeNode::with_children(lookup("+"), vec![
                        EvalTreeNode::with_children(lookup("*"), vec![
                            nleaf(4),
                            nleaf(8),
                        ]),
                        EvalTreeNode::with_children(lookup("-"), vec![
                            nleaf(99),
                            EvalTreeNode::new(lookup("x")),
                        ]),
                    ]),
                ]),
                EvalTreeNode::with_children(lookup("+"), vec![
                    EvalTreeNode::with_children(lookup("/"), vec![
                        nleaf(67),
                        EvalTreeNode::with_children(lookup("-"), vec![
                            EvalTreeNode::new(lookup("x")),
                            EvalTreeNode::with_children(lookup("g"), vec![
                                nleaf(4),
                            ]),
                        ]),
                    ]),
                    nleaf(32),
                ]),
            ])
        };

        let tree = EvalTreeNode::from_expr(&mut context, expr).unwrap();

        assert_eq!(tree, expected_tree);
    }

    /// Defines a basic context with the operators: + - / * %
    /// with their normal, mathematical precedence
    /// as well as two functions f and g as well as a number x
    /// None of these definitions have a real, evaluatable function
    fn basic_context() -> EvalContext {
        let mut context = EvalContext::new();

        let fake_unary: Function = Function {
            params: vec!["a".to_owned()],
            body: Expr::new(),
        };

        let fake_binary: Function = Function {
            params: vec!["a".to_owned(), "b".to_owned()],
            body: Expr::new(),
        };

        context.set_number("x", RichNumber::from(3875f64));

        context.define_defaults("f", fake_unary.clone());
        context.define_defaults("g", fake_unary.clone());

        context.define("+", Fixity::Infix, 6, fake_binary.clone());
        context.define("-", Fixity::Infix, 6, fake_binary.clone());

        context.define("*", Fixity::Infix, 7, fake_binary.clone());
        context.define("/", Fixity::Infix, 7, fake_binary.clone());
        context.define("%", Fixity::Infix, 7, fake_binary.clone());

        context
    }
}

<commit_msg>Checking for overflow or invalid index in the Fixity::Infix drain function<commit_after>use ast::{Expr, ExprItem, Term};
use math::rich_number::RichNumber;
use eval::fixity::Fixity;
use eval::context_item::ContextItem;
use eval::eval_context::{EvalContext, EvalError};

#[derive(Debug, PartialEq, Clone)]
pub struct EvalTreeNode {
    item: ContextItem,
    children: Vec<EvalTreeNode>,
}

impl EvalTreeNode {
    pub fn new(item: ContextItem) -> EvalTreeNode {
        EvalTreeNode {
            item: item,
            children: Vec::new(),
        }
    }

    pub fn with_children(item: ContextItem, children: Vec<EvalTreeNode>) -> EvalTreeNode {
        let mut node = EvalTreeNode::new(item);
        node.children = children;

        node
    }

    pub fn from_expr(context: &EvalContext, expr: Expr) -> Result<EvalTreeNode, EvalError> {
        let mut nodes = try!(EvalTreeNode::convert_to_nodes(context, expr));

        while nodes.len() != 1 {
            let node_index = EvalTreeNode::left_highest_precedence(&nodes);
            if node_index.is_none() {
                return Err(EvalError::UnexpectedSymbols);
            }
            let node_index = node_index.unwrap();

            let params = try!(EvalTreeNode::drain_params(&mut nodes, node_index));

            let mut node = &mut nodes[node_index];
            node.children = params;
        }

        debug_assert!(nodes.len() == 1);
        Ok(nodes.pop().unwrap())
    }

    fn convert_to_nodes(context: &EvalContext, expr: Expr) -> Result<Vec<EvalTreeNode>, EvalError> {
        let mut nodes: Vec<EvalTreeNode> = Vec::new();

        for item in expr.into_iter() {
            nodes.push(match item {
                ExprItem::AnonymousFunction(function) => {
                    EvalTreeNode::new(ContextItem::function_defaults(function))
                },
                ExprItem::SingleTerm(term) => match term {
                    Term::Symbol(sym) => {
                        let item = context.get(&sym);
                        if item.is_none() {
                            return Err(EvalError::UndefinedSymbol(sym));
                        }
                        EvalTreeNode::new(item.unwrap())
                    },
                    Term::Number(num) => {
                        EvalTreeNode::new(
                            ContextItem::Number(
                                RichNumber::from(num)
                            )
                        )
                    },
                    Term::StringLiteral(value) => {
                        EvalTreeNode::new(
                            ContextItem::Constant(value)
                        )
                    },
                },
                ExprItem::Group(expr) => try!(EvalTreeNode::from_expr(context, expr)),
            });
        }

        Ok(nodes)
    }

    /// Returns the index of the leftmost node with the highest precedence
    /// Only returns ContextItems with precedence
    fn left_highest_precedence(nodes: &Vec<EvalTreeNode>) -> Option<usize> {
        // (index, precedence)
        let mut highest: Option<(usize, u8)> = None;

        for (i, node) in nodes.iter().enumerate() {
            // This node has already been taken care of
            if !node.children.is_empty() {
                continue;
            }

            let precedence = node.item.resolve_precedence();
            if precedence.is_none() {
                continue;
            }
            let precedence = *precedence.unwrap();

            // This MUST be less than, NOT less than or equal to to get the
            // leftmost item
            if highest.is_none() || highest.unwrap().1 < precedence {
                highest = Some((i, precedence));
            }
        }

        highest.map(|x| x.0)
    }

    // Removes the nodes adjacent to the node_index (but not including the
    // node_index) that correspond to the number of parameters expected
    // by that node in the direction specified by that node's fixity
    fn drain_params(nodes: &mut Vec<EvalTreeNode>, node_index: usize) -> Result<Vec<EvalTreeNode>, EvalError> {
        let fixity;
        let params;
        {
            let node = &nodes[node_index];

            // unwrap() is safe here because node item should be a definition or built in
            fixity = node.item.resolve_fixity().unwrap();
            params = node.item.resolve_params().unwrap();
            debug_assert!(params != 0);
        }

        Ok(match fixity {
            Fixity::Infix => {
                // Infix functions MUST have 2 parameters
                if params != 2 {
                    return Err(EvalError::InvalidSymbolDefinition {
                        expected_params: 2,
                        actual_params: params,
                    });
                }

                // if either of these conditions is true, the following calculation
                // would result in either overflow or an index error
                if node_index == 0 || node_index >= nodes.len() - 1 {
                    return Err(EvalError::ExpectedParams(params));
                }

                // It is vital that the second remove happen before the
                // first because this operation shifts all indexes to the left
                let second = nodes.remove(node_index + 1);
                let first = nodes.remove(node_index - 1);

                vec![first, second]
            },
            Fixity::Prefix => {
                let start;
                let end = node_index;

                // params > node_index would result in a negative sum
                if params > node_index || end >= nodes.len() {
                    return Err(EvalError::ExpectedParams(params));
                }
                // need to declare this here to avoid overflow
                start = node_index - params;

                nodes.drain(start..end).collect()
            },
            Fixity::Postfix => {
                // No need to worry about node_index being less than zero because we
                // are adding 1 here
                let start = node_index + 1;
                // The +1 in the end of the range is because ranges stop
                // at the index 1 before the end
                let end = node_index + params + 1;
                if end >= nodes.len() {
                    return Err(EvalError::ExpectedParams(params));
                }
                nodes.drain(start..end).collect()
            },
        })
    }
}

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

    use eval::fixity::Fixity;
    use eval::context_item::ContextItem;
    use eval::eval_context::EvalContext;
    use math::rich_number::RichNumber;

    #[test]
    fn creates_tree_with_correct_precedence() {
        // f 3 + (4 * 8 + 99 - x) - ((67)) / (x - g 4) + 32
        let expr: Expr = vec![
            ExprItem::SingleTerm(Term::Symbol("f".to_owned())),
            ExprItem::SingleTerm(Term::Number(3f64)),
            ExprItem::SingleTerm(Term::Symbol("+".to_owned())),
            ExprItem::Group(vec![
                ExprItem::SingleTerm(Term::Number(4f64)),
                ExprItem::SingleTerm(Term::Symbol("*".to_owned())),
                ExprItem::SingleTerm(Term::Number(8f64)),
                ExprItem::SingleTerm(Term::Symbol("+".to_owned())),
                ExprItem::SingleTerm(Term::Number(99f64)),
                ExprItem::SingleTerm(Term::Symbol("-".to_owned())),
                ExprItem::SingleTerm(Term::Symbol("x".to_owned())),
            ]),
            ExprItem::SingleTerm(Term::Symbol("-".to_owned())),
            ExprItem::Group(vec![
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(Term::Number(67f64)),
                ])
            ]),
            ExprItem::SingleTerm(Term::Symbol("/".to_owned())),
            ExprItem::Group(vec![
                ExprItem::SingleTerm(Term::Symbol("x".to_owned())),
                ExprItem::SingleTerm(Term::Symbol("-".to_owned())),
                ExprItem::SingleTerm(Term::Symbol("g".to_owned())),
                ExprItem::SingleTerm(Term::Number(4f64)),
            ]),
            ExprItem::SingleTerm(Term::Symbol("+".to_owned())),
            ExprItem::SingleTerm(Term::Number(32f64)),
        ];

        let mut context = basic_context();

        let expected_tree = {
            let nleaf = |n| EvalTreeNode::new(ContextItem::Number(RichNumber::from(n)));
            let lookup = |name| context.get(name).unwrap();

            EvalTreeNode::with_children(lookup("-"), vec![
                EvalTreeNode::with_children(lookup("+"), vec![
                    EvalTreeNode::with_children(lookup("f"), vec![
                        nleaf(3),
                    ]),
                    EvalTreeNode::with_children(lookup("+"), vec![
                        EvalTreeNode::with_children(lookup("*"), vec![
                            nleaf(4),
                            nleaf(8),
                        ]),
                        EvalTreeNode::with_children(lookup("-"), vec![
                            nleaf(99),
                            EvalTreeNode::new(lookup("x")),
                        ]),
                    ]),
                ]),
                EvalTreeNode::with_children(lookup("+"), vec![
                    EvalTreeNode::with_children(lookup("/"), vec![
                        nleaf(67),
                        EvalTreeNode::with_children(lookup("-"), vec![
                            EvalTreeNode::new(lookup("x")),
                            EvalTreeNode::with_children(lookup("g"), vec![
                                nleaf(4),
                            ]),
                        ]),
                    ]),
                    nleaf(32),
                ]),
            ])
        };

        let tree = EvalTreeNode::from_expr(&mut context, expr).unwrap();

        assert_eq!(tree, expected_tree);
    }

    /// Defines a basic context with the operators: + - / * %
    /// with their normal, mathematical precedence
    /// as well as two functions f and g as well as a number x
    /// None of these definitions have a real, evaluatable function
    fn basic_context() -> EvalContext {
        let mut context = EvalContext::new();

        let fake_unary: Function = Function {
            params: vec!["a".to_owned()],
            body: Expr::new(),
        };

        let fake_binary: Function = Function {
            params: vec!["a".to_owned(), "b".to_owned()],
            body: Expr::new(),
        };

        context.set_number("x", RichNumber::from(3875f64));

        context.define_defaults("f", fake_unary.clone());
        context.define_defaults("g", fake_unary.clone());

        context.define("+", Fixity::Infix, 6, fake_binary.clone());
        context.define("-", Fixity::Infix, 6, fake_binary.clone());

        context.define("*", Fixity::Infix, 7, fake_binary.clone());
        context.define("/", Fixity::Infix, 7, fake_binary.clone());
        context.define("%", Fixity::Infix, 7, fake_binary.clone());

        context
    }
}

<|endoftext|>


<commit_before>
use inefficient_flat_time_steward as s;
use ::{TimeSteward, DeterministicRandomId, Column, ColumnId, RowId, Mutator,
       TimeStewardLifetimedMethods, Accessor, MomentaryAccessor, PredictorAccessor};
use std::rc::Rc;
use rand::Rng;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

type Time = i64;

const HOW_MANY_PHILOSOPHERS: i32 = 7;

#[derive(Clone)]
struct Basics;
impl ::Basics for Basics {
  type Time = Time;
  type Constants = ();
}

#[derive(Clone)]
struct Philosopher {
  // This is sometimes in the future because
  // they muse philosophically about handshakes
  // for a while, whenever one of them happens.
  time_when_next_initiates_handshake: Time,
}
impl Column for Philosopher {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x4084d1501468b6dd)
  }
}

type Steward = s::Steward<Basics>;

fn get_philosopher_id(index: i32) -> RowId {
  DeterministicRandomId::new(&(0x2302c38efb47e0d0u64, index))
}

pub fn testfunc() {

  let mut stew: Steward = ::TimeSteward::new_empty((),
                                                   vec![s::Predictor {
                                                          predictor_id: 0x0e7f27c7643f8167,
                                                          column_id: Philosopher::column_id(),
                                                          function: Rc::new(|pa, whodunnit| {
      printlnerr!("Planning {}", whodunnit);
      let me = pa.get::<Philosopher>(whodunnit).unwrap().clone();
      pa.predict_at_time(&me.time_when_next_initiates_handshake,
                         Rc::new(move |m| {
        let now = *m.now();
        let friend_id = get_philosopher_id(m.rng().gen_range(0, HOW_MANY_PHILOSOPHERS));
        let awaken_time_1 = now + m.rng().gen_range(-1, 4);
        let awaken_time_2 = now + m.rng().gen_range(-1, 7);
        printlnerr!("SHAKE!!! {}={}; {}={}", whodunnit, awaken_time_2, friend_id, awaken_time_1);
        // IF YOU SHAKE YOUR OWN HAND YOU RECOVER
        // IN THE SECOND TIME APPARENTLY
        m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_1,
                             }));
        m.set::<Philosopher>(whodunnit,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_2,
                             }));
      }));
    }),
                                                        }]);

  stew.insert_fiat_event(0,
                         DeterministicRandomId::new(&0x32e1570766e768a7u64),
                         Rc::new(|m| {
    printlnerr!("FIAT!!!!!");
    for i in 0..HOW_MANY_PHILOSOPHERS {
      m.set::<Philosopher>(get_philosopher_id(i),
                           Some(Philosopher {
                             time_when_next_initiates_handshake: (i + 1) as Time,
                           }));
    }
  }));

  stew.snapshot_before(&50);

  // panic!("anyway")
}

#[test]
fn actuallytest() {
  testfunc();
}
<commit_msg>augment debug logging<commit_after>
use inefficient_flat_time_steward as s;
use ::{TimeSteward, DeterministicRandomId, Column, ColumnId, RowId, Mutator,
       TimeStewardLifetimedMethods, Accessor, MomentaryAccessor, PredictorAccessor};
use std::rc::Rc;
use rand::Rng;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

type Time = i64;

const HOW_MANY_PHILOSOPHERS: i32 = 7;

#[derive(Clone)]
struct Basics;
impl ::Basics for Basics {
  type Time = Time;
  type Constants = ();
}

#[derive(Clone)]
struct Philosopher {
  // This is sometimes in the future because
  // they muse philosophically about handshakes
  // for a while, whenever one of them happens.
  time_when_next_initiates_handshake: Time,
}
impl Column for Philosopher {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x4084d1501468b6dd)
  }
}

type Steward = s::Steward<Basics>;

fn get_philosopher_id(index: i32) -> RowId {
  DeterministicRandomId::new(&(0x2302c38efb47e0d0u64, index))
}

pub fn testfunc() {

  let mut stew: Steward = ::TimeSteward::new_empty((),
                                                   vec![s::Predictor {
                                                          predictor_id: 0x0e7f27c7643f8167,
                                                          column_id: Philosopher::column_id(),
                                                          function: Rc::new(|pa, whodunnit| {
      printlnerr!("Planning {}", whodunnit);
      let me = pa.get::<Philosopher>(whodunnit).unwrap().clone();
      pa.predict_at_time(&me.time_when_next_initiates_handshake,
                         Rc::new(move |m| {
        let now = *m.now();
        let friend_id = get_philosopher_id(m.rng().gen_range(0, HOW_MANY_PHILOSOPHERS));
        let awaken_time_1 = now + m.rng().gen_range(-1, 4);
        let awaken_time_2 = now + m.rng().gen_range(-1, 7);
        printlnerr!("SHAKE!!! @{}. {}={}; {}={}", now, whodunnit, awaken_time_2, friend_id, awaken_time_1);
        // IF YOU SHAKE YOUR OWN HAND YOU RECOVER
        // IN THE SECOND TIME APPARENTLY
        m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_1,
                             }));
        m.set::<Philosopher>(whodunnit,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_2,
                             }));
      }));
    }),
                                                        }]);

  stew.insert_fiat_event(0,
                         DeterministicRandomId::new(&0x32e1570766e768a7u64),
                         Rc::new(|m| {
    printlnerr!("FIAT!!!!!");
    for i in 0..HOW_MANY_PHILOSOPHERS {
      m.set::<Philosopher>(get_philosopher_id(i),
                           Some(Philosopher {
                             time_when_next_initiates_handshake: (i + 1) as Time,
                           }));
    }
  }));

  stew.snapshot_before(&50);

  // panic!("anyway")
}

#[test]
fn actuallytest() {
  testfunc();
}
<|endoftext|>


<commit_before>//! Create and manage persistent storage that can be attached to containers.
//!
//! API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Volume>

use std::{
    collections::{BTreeMap, HashMap},
    hash::Hash,
};

use hyper::Body;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

use crate::{
    errors::{Error, Result},
    Docker,
};

#[cfg(feature = "chrono")]
use chrono::{DateTime, Utc};

/// Interface for docker volumes
///
/// API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Volume>
pub struct Volumes<'docker> {
    docker: &'docker Docker,
}

impl<'docker> Volumes<'docker> {
    /// Exports an interface for interacting with docker volumes
    pub fn new(docker: &'docker Docker) -> Self {
        Volumes { docker }
    }

    /// Creates a new docker volume.
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/VolumeCreate>
    pub async fn create(
        &self,
        opts: &VolumeCreateOptions,
    ) -> Result<VolumeCreateInfo> {
        let body: Body = opts.serialize()?.into();
        let path = vec!["/volumes/create".to_owned()];

        self.docker
            .post_json(&path.join("?"), Some((body, mime::APPLICATION_JSON)))
            .await
    }

    /// Lists the docker volumes on the current docker host
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/VolumeList>
    pub async fn list(&self) -> Result<Vec<VolumeInfo>> {
        let path = vec!["/volumes".to_owned()];

        let volumes_rep = self.docker.get_json::<VolumesInfo>(&path.join("?")).await?;
        Ok(match volumes_rep.volumes {
            Some(volumes) => volumes,
            None => vec![],
        })
    }

    /// Returns a reference to a set of operations available for a named volume
    pub fn get(
        &self,
        name: &str,
    ) -> Volume<'docker> {
        Volume::new(self.docker, name)
    }
}

/// Interface for accessing and manipulating a named docker volume
///
/// API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Volume>
pub struct Volume<'docker> {
    docker: &'docker Docker,
    name: String,
}

impl<'docker> Volume<'docker> {
    /// Exports an interface for operations that may be performed against a named volume
    pub fn new<S>(
        docker: &'docker Docker,
        name: S,
    ) -> Self
    where
        S: Into<String>,
    {
        Volume {
            docker,
            name: name.into(),
        }
    }

    /// Deletes a volume
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/VolumeDelete>
    pub async fn delete(&self) -> Result<()> {
        self.docker
            .delete(&format!("/volumes/{}", self.name)[..])
            .await?;
        Ok(())
    }
}

/// Interface for creating volumes
#[derive(Serialize, Debug)]
pub struct VolumeCreateOptions {
    params: HashMap<&'static str, Value>,
}

impl VolumeCreateOptions {
    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Result<String> {
        serde_json::to_string(&self.params).map_err(Error::from)
    }

    pub fn parse_from<'a, K, V>(
        &self,
        params: &'a HashMap<K, V>,
        body: &mut BTreeMap<String, Value>,
    ) where
        &'a HashMap<K, V>: IntoIterator,
        K: ToString + Eq + Hash,
        V: Serialize,
    {
        for (k, v) in params.iter() {
            let key = k.to_string();
            let value = serde_json::to_value(v).unwrap();

            body.insert(key, value);
        }
    }

    /// return a new instance of a builder for options
    pub fn builder() -> VolumeCreateOptionsBuilder {
        VolumeCreateOptionsBuilder::new()
    }
}

#[derive(Default)]
pub struct VolumeCreateOptionsBuilder {
    params: HashMap<&'static str, Value>,
}

impl VolumeCreateOptionsBuilder {
    pub(crate) fn new() -> Self {
        let params = HashMap::new();
        VolumeCreateOptionsBuilder { params }
    }

    pub fn name(
        &mut self,
        name: &str,
    ) -> &mut Self {
        self.params.insert("Name", json!(name));
        self
    }

    pub fn labels(
        &mut self,
        labels: &HashMap<&str, &str>,
    ) -> &mut Self {
        self.params.insert("Labels", json!(labels));
        self
    }

    pub fn build(&self) -> VolumeCreateOptions {
        VolumeCreateOptions {
            params: self.params.clone(),
        }
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VolumeCreateInfo {
    pub name: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VolumesInfo {
    pub volumes: Option<Vec<VolumeInfo>>,
    pub warnings: Option<Vec<String>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VolumeInfo {
    #[cfg(feature = "chrono")]
    pub created_at: DateTime<Utc>,
    #[cfg(not(feature = "chrono"))]
    pub created_at: String,
    pub driver: String,
    pub labels: Option<HashMap<String, String>>,
    pub name: String,
    pub mountpoint: String,
    pub options: Option<HashMap<String, String>>,
    pub scope: String,
}
<commit_msg>Added volume driver support<commit_after>//! Create and manage persistent storage that can be attached to containers.
//!
//! API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Volume>

use std::{
    collections::{BTreeMap, HashMap},
    hash::Hash,
};

use hyper::Body;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

use crate::{
    errors::{Error, Result},
    Docker,
};

#[cfg(feature = "chrono")]
use chrono::{DateTime, Utc};

/// Interface for docker volumes
///
/// API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Volume>
pub struct Volumes<'docker> {
    docker: &'docker Docker,
}

impl<'docker> Volumes<'docker> {
    /// Exports an interface for interacting with docker volumes
    pub fn new(docker: &'docker Docker) -> Self {
        Volumes { docker }
    }

    /// Creates a new docker volume.
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/VolumeCreate>
    pub async fn create(
        &self,
        opts: &VolumeCreateOptions,
    ) -> Result<VolumeCreateInfo> {
        let body: Body = opts.serialize()?.into();
        let path = vec!["/volumes/create".to_owned()];

        self.docker
            .post_json(&path.join("?"), Some((body, mime::APPLICATION_JSON)))
            .await
    }

    /// Lists the docker volumes on the current docker host
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/VolumeList>
    pub async fn list(&self) -> Result<Vec<VolumeInfo>> {
        let path = vec!["/volumes".to_owned()];

        let volumes_rep = self.docker.get_json::<VolumesInfo>(&path.join("?")).await?;
        Ok(match volumes_rep.volumes {
            Some(volumes) => volumes,
            None => vec![],
        })
    }

    /// Returns a reference to a set of operations available for a named volume
    pub fn get(
        &self,
        name: &str,
    ) -> Volume<'docker> {
        Volume::new(self.docker, name)
    }
}

/// Interface for accessing and manipulating a named docker volume
///
/// API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Volume>
pub struct Volume<'docker> {
    docker: &'docker Docker,
    name: String,
}

impl<'docker> Volume<'docker> {
    /// Exports an interface for operations that may be performed against a named volume
    pub fn new<S>(
        docker: &'docker Docker,
        name: S,
    ) -> Self
    where
        S: Into<String>,
    {
        Volume {
            docker,
            name: name.into(),
        }
    }

    /// Deletes a volume
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/VolumeDelete>
    pub async fn delete(&self) -> Result<()> {
        self.docker
            .delete(&format!("/volumes/{}", self.name)[..])
            .await?;
        Ok(())
    }
}

/// Interface for creating volumes
#[derive(Serialize, Debug)]
pub struct VolumeCreateOptions {
    params: HashMap<&'static str, Value>,
}

impl VolumeCreateOptions {
    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Result<String> {
        serde_json::to_string(&self.params).map_err(Error::from)
    }

    pub fn parse_from<'a, K, V>(
        &self,
        params: &'a HashMap<K, V>,
        body: &mut BTreeMap<String, Value>,
    ) where
        &'a HashMap<K, V>: IntoIterator,
        K: ToString + Eq + Hash,
        V: Serialize,
    {
        for (k, v) in params.iter() {
            let key = k.to_string();
            let value = serde_json::to_value(v).unwrap();

            body.insert(key, value);
        }
    }

    /// return a new instance of a builder for options
    pub fn builder() -> VolumeCreateOptionsBuilder {
        VolumeCreateOptionsBuilder::new()
    }
}

#[derive(Default)]
pub struct VolumeCreateOptionsBuilder {
    params: HashMap<&'static str, Value>,
}

impl VolumeCreateOptionsBuilder {
    pub(crate) fn new() -> Self {
        let params = HashMap::new();
        VolumeCreateOptionsBuilder { params }
    }

    pub fn driver(
        &mut self,
        driver_name: &str,
        driver_opts: Option<&HashMap<&str, &str>>,
    ) -> &mut Self {
        self.params.insert("Driver", json!(driver_name));
        if let Some(opts) = driver_opts {
            self.params.insert("DriverOpts", json!(opts));
        }
        self
    }

    pub fn name(
        &mut self,
        name: &str,
    ) -> &mut Self {
        self.params.insert("Name", json!(name));
        self
    }

    pub fn labels(
        &mut self,
        labels: &HashMap<&str, &str>,
    ) -> &mut Self {
        self.params.insert("Labels", json!(labels));
        self
    }

    pub fn build(&self) -> VolumeCreateOptions {
        VolumeCreateOptions {
            params: self.params.clone(),
        }
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VolumeCreateInfo {
    pub name: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VolumesInfo {
    pub volumes: Option<Vec<VolumeInfo>>,
    pub warnings: Option<Vec<String>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VolumeInfo {
    #[cfg(feature = "chrono")]
    pub created_at: DateTime<Utc>,
    #[cfg(not(feature = "chrono"))]
    pub created_at: String,
    pub driver: String,
    pub labels: Option<HashMap<String, String>>,
    pub name: String,
    pub mountpoint: String,
    pub options: Option<HashMap<String, String>>,
    pub scope: String,
}

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

    #[derive(Deserialize)]
    #[serde(rename_all = "PascalCase")]
    pub struct VolumeTestInfo {
        pub driver: Option<String>,
        pub name: Option<String>,
        pub driver_opts: Option<HashMap<String, String>>,
    }

    #[test]
    fn test_volumecreateoptionsbuilder_driver() {
        let volume = VolumeCreateOptions::builder()
            .driver("my_driver", None)
            .build();

        let serialized = volume.serialize().unwrap();
        let volume_info: VolumeTestInfo = serde_json::from_str(&serialized).unwrap();

        assert_eq!(volume_info.driver, Some("my_driver".to_string()));
        assert_eq!(volume_info.name, None);
        assert_eq!(volume_info.driver_opts, None)
    }

    #[test]
    fn test_volumecreateoptionsbuilder_driver_opts() {
        let opts: HashMap<&str, &str> = [("option", "value")].iter().cloned().collect();
        let volume = VolumeCreateOptions::builder()
            .driver("my_driver", Some(&opts))
            .build();

        let serialized = volume.serialize().unwrap();
        let volume_info: VolumeTestInfo = serde_json::from_str(&serialized).unwrap();
        let mut driver_options = HashMap::new();
        driver_options.insert("option".to_string(), "value".to_string());

        assert_eq!(volume_info.driver, Some("my_driver".to_string()));
        assert_eq!(volume_info.name, None);
        assert_eq!(volume_info.driver_opts, Some(driver_options))
    }
}
<|endoftext|>