<commit_before>use util::get_unique_varname;
use parser::SExpr;

#[derive(Clone, Debug, PartialEq)]
pub enum Flat {
    Symbol(String),
    Number(i32),
    Bool(bool),
    Assign(String, Box<Flat>),
    Return(Box<Flat>),
    If(Box<Flat>, Vec<Flat>, Vec<Flat>),
    EqP(Box<Flat>, Box<Flat>),
    Prim(String, Vec<Flat>),
}

// This function does and ANF transformation. The output is a Flat
// expression.
pub fn flatten(expr: SExpr) -> (Flat, Vec<Flat>, Vec<String>) {
    match expr {
        SExpr::Symbol(name) => (Flat::Symbol(name.clone()),
                                vec![],
                                vec![name]),
        SExpr::Number(n) => (Flat::Number(n), vec![], vec![]),
        SExpr::Bool(b) => (Flat::Bool(b), vec![], vec![]),
        SExpr::Let(bindings, body) => {
            let (flat_body, body_assigns, body_vars) = flatten(*body);

            let mut bindings_assigns = vec![];
            let mut bindings_vars = vec![];
            for (k, v) in bindings {
                let (flat_v, v_assigns, v_vars) = flatten(v);
                println!("{:?}", flat_v);
                match flat_v.clone() {
                    Flat::Symbol(name) => bindings_vars.push(name),
                    _ => (),
                };
                bindings_assigns.extend_from_slice(&v_assigns);
                bindings_assigns.extend_from_slice(
                    &[Flat::Assign(k.clone(), Box::new(flat_v))]
                    );
                bindings_vars.extend_from_slice(&v_vars);
                bindings_vars.push(k);
            }
            bindings_assigns.extend_from_slice(&body_assigns);
            bindings_vars.extend_from_slice(&body_vars);
            return (flat_body,
                    bindings_assigns,
                    bindings_vars);
        },
        SExpr::List(elts) => {
            panic!("NYI");
        },
        SExpr::Define(name, val) => {
            // TODO: FIXME
            return (Flat::Symbol("".to_string()), vec![], vec![]);
        },
        SExpr::If(cnd, thn, els) => {
            let (flat_cnd, mut cnd_assigns, mut cnd_vars) =
                flatten(*cnd);
            let (flat_thn, mut thn_assigns, mut thn_vars) =
                flatten(*thn);
            let (flat_els, mut els_assigns, mut els_vars) =
                flatten(*els);

            let if_temp = get_unique_varname("if");

            thn_assigns.extend_from_slice(&[Flat::Assign(if_temp.clone(),
                                                         Box::new(flat_thn))]);
            els_assigns.extend_from_slice(&[Flat::Assign(if_temp.clone(),
                                                         Box::new(flat_els))]);
            let flat_if = Flat::If(Box::new(Flat::EqP(Box::new(flat_cnd),
                                                      Box::new(Flat::Bool(true)))),
                                   thn_assigns,
                                   els_assigns);

            cnd_assigns.extend_from_slice(&[flat_if]);
            cnd_vars.append(&mut thn_vars);
            cnd_vars.append(&mut els_vars);
            cnd_vars.extend_from_slice(&[if_temp.clone()]);
            return (Flat::Symbol(if_temp),
                    cnd_assigns,
                    cnd_vars);

        },
        SExpr::App(f, args) => {
            match *f {
                SExpr::Symbol(fname) => {
                    match &fname[..] {
                        "-" => {
                            // TODO: check no. of args
                            let (flat_e, mut e_assigns, mut e_vars) = flatten(args[0].clone());
                            let neg_temp = get_unique_varname("tmp");
                            let flat_neg = Flat::Assign(neg_temp.clone(),
                                                        Box::new(Flat::Prim("-".to_string(), vec![flat_e])));
                            e_assigns.extend_from_slice(&[flat_neg]);
                            e_vars.extend_from_slice(&[neg_temp.clone()]);
                            return (Flat::Symbol(neg_temp),
                                    e_assigns,
                                    e_vars);
                        },
                        "+" => {
                            let (flat_e1, mut e1_assigns, mut e1_vars) = flatten(args[0].clone());
                            let (flat_e2, mut e2_assigns, mut e2_vars) = flatten(args[1].clone());

                            let plus_temp = get_unique_varname("tmp");

                            let flat_plus = Flat::Assign(plus_temp.clone(),
                                                         Box::new(Flat::Prim("+".to_string(), vec![flat_e1, flat_e2])));
                            e1_assigns.append(&mut e2_assigns);
                            e1_assigns.extend_from_slice(&[flat_plus]);

                            e1_vars.append(&mut e2_vars);
                            e1_vars.extend_from_slice(&[plus_temp.clone()]);

                            return (Flat::Symbol(plus_temp),
                                    e1_assigns,
                                    e1_vars);
                        },
                        &_ => panic!("NYI!"),
                    }
                },
                _ => panic!("not a function!"),
            }
        },
        SExpr::Prog(e) => {
            let (flat_e, mut e_assigns, mut e_vars) = flatten(*e);
            let return_e = Flat::Return(Box::new(flat_e));

            e_assigns.extend_from_slice(&[return_e]);
            e_vars.dedup();

            return (Flat::Symbol("<PROGRAM>".to_string()),
                    e_assigns,
                    e_vars);
        },
        SExpr::EOF => panic!("Don't know what to do with EOF"),
    }
}

#[test]
fn test_flatten() {
    use lexer::LexerState;
    use parser::read;

    let mut input = String::from("(+ 12 (+ 13 14))");
    let mut lexer = LexerState {
        s: input,
        pos: 0,
        col: 1,
        line_num: 1,
        tok_buf: None,
    };

    assert_eq!(
        flatten(SExpr::Prog(Box::new(read(&mut lexer)))),
        (Flat::Symbol("<PROGRAM>".to_string()),
         vec![Flat::Assign("tmp1".to_string(), Box::new(Flat::Prim("+".to_string(), vec![Flat::Number(13), Flat::Number(14)]))),
              Flat::Assign("tmp2".to_string(), Box::new(Flat::Prim("+".to_string(), vec![Flat::Number(12), Flat::Symbol("tmp1".to_string())]))),
              Flat::Return(Box::new(Flat::Symbol("tmp2".to_string())))
         ], vec!["tmp1".to_string(), "tmp2".to_string()])
    );
}
<commit_msg>Remove println<commit_after>use util::get_unique_varname;
use parser::SExpr;

#[derive(Clone, Debug, PartialEq)]
pub enum Flat {
    Symbol(String),
    Number(i32),
    Bool(bool),
    Assign(String, Box<Flat>),
    Return(Box<Flat>),
    If(Box<Flat>, Vec<Flat>, Vec<Flat>),
    EqP(Box<Flat>, Box<Flat>),
    Prim(String, Vec<Flat>),
}

// This function does and ANF transformation. The output is a Flat
// expression.
pub fn flatten(expr: SExpr) -> (Flat, Vec<Flat>, Vec<String>) {
    match expr {
        SExpr::Symbol(name) => (Flat::Symbol(name.clone()),
                                vec![],
                                vec![name]),
        SExpr::Number(n) => (Flat::Number(n), vec![], vec![]),
        SExpr::Bool(b) => (Flat::Bool(b), vec![], vec![]),
        SExpr::Let(bindings, body) => {
            let (flat_body, body_assigns, body_vars) = flatten(*body);

            let mut bindings_assigns = vec![];
            let mut bindings_vars = vec![];
            for (k, v) in bindings {
                let (flat_v, v_assigns, v_vars) = flatten(v);
                match flat_v.clone() {
                    Flat::Symbol(name) => bindings_vars.push(name),
                    _ => (),
                };
                bindings_assigns.extend_from_slice(&v_assigns);
                bindings_assigns.extend_from_slice(
                    &[Flat::Assign(k.clone(), Box::new(flat_v))]
                    );
                bindings_vars.extend_from_slice(&v_vars);
                bindings_vars.push(k);
            }
            bindings_assigns.extend_from_slice(&body_assigns);
            bindings_vars.extend_from_slice(&body_vars);
            return (flat_body,
                    bindings_assigns,
                    bindings_vars);
        },
        SExpr::List(elts) => {
            panic!("NYI");
        },
        SExpr::Define(name, val) => {
            // TODO: FIXME
            return (Flat::Symbol("".to_string()), vec![], vec![]);
        },
        SExpr::If(cnd, thn, els) => {
            let (flat_cnd, mut cnd_assigns, mut cnd_vars) =
                flatten(*cnd);
            let (flat_thn, mut thn_assigns, mut thn_vars) =
                flatten(*thn);
            let (flat_els, mut els_assigns, mut els_vars) =
                flatten(*els);

            let if_temp = get_unique_varname("if");

            thn_assigns.extend_from_slice(&[Flat::Assign(if_temp.clone(),
                                                         Box::new(flat_thn))]);
            els_assigns.extend_from_slice(&[Flat::Assign(if_temp.clone(),
                                                         Box::new(flat_els))]);
            let flat_if = Flat::If(Box::new(Flat::EqP(Box::new(flat_cnd),
                                                      Box::new(Flat::Bool(true)))),
                                   thn_assigns,
                                   els_assigns);

            cnd_assigns.extend_from_slice(&[flat_if]);
            cnd_vars.append(&mut thn_vars);
            cnd_vars.append(&mut els_vars);
            cnd_vars.extend_from_slice(&[if_temp.clone()]);
            return (Flat::Symbol(if_temp),
                    cnd_assigns,
                    cnd_vars);

        },
        SExpr::App(f, args) => {
            match *f {
                SExpr::Symbol(fname) => {
                    match &fname[..] {
                        "-" => {
                            // TODO: check no. of args
                            let (flat_e, mut e_assigns, mut e_vars) = flatten(args[0].clone());
                            let neg_temp = get_unique_varname("tmp");
                            let flat_neg = Flat::Assign(neg_temp.clone(),
                                                        Box::new(Flat::Prim("-".to_string(), vec![flat_e])));
                            e_assigns.extend_from_slice(&[flat_neg]);
                            e_vars.extend_from_slice(&[neg_temp.clone()]);
                            return (Flat::Symbol(neg_temp),
                                    e_assigns,
                                    e_vars);
                        },
                        "+" => {
                            let (flat_e1, mut e1_assigns, mut e1_vars) = flatten(args[0].clone());
                            let (flat_e2, mut e2_assigns, mut e2_vars) = flatten(args[1].clone());

                            let plus_temp = get_unique_varname("tmp");

                            let flat_plus = Flat::Assign(plus_temp.clone(),
                                                         Box::new(Flat::Prim("+".to_string(), vec![flat_e1, flat_e2])));
                            e1_assigns.append(&mut e2_assigns);
                            e1_assigns.extend_from_slice(&[flat_plus]);

                            e1_vars.append(&mut e2_vars);
                            e1_vars.extend_from_slice(&[plus_temp.clone()]);

                            return (Flat::Symbol(plus_temp),
                                    e1_assigns,
                                    e1_vars);
                        },
                        &_ => panic!("NYI!"),
                    }
                },
                _ => panic!("not a function!"),
            }
        },
        SExpr::Prog(e) => {
            let (flat_e, mut e_assigns, mut e_vars) = flatten(*e);
            let return_e = Flat::Return(Box::new(flat_e));

            e_assigns.extend_from_slice(&[return_e]);
            e_vars.dedup();

            return (Flat::Symbol("<PROGRAM>".to_string()),
                    e_assigns,
                    e_vars);
        },
        SExpr::EOF => panic!("Don't know what to do with EOF"),
    }
}

#[test]
fn test_flatten() {
    use lexer::LexerState;
    use parser::read;

    let mut input = String::from("(+ 12 (+ 13 14))");
    let mut lexer = LexerState {
        s: input,
        pos: 0,
        col: 1,
        line_num: 1,
        tok_buf: None,
    };

    assert_eq!(
        flatten(SExpr::Prog(Box::new(read(&mut lexer)))),
        (Flat::Symbol("<PROGRAM>".to_string()),
         vec![Flat::Assign("tmp1".to_string(), Box::new(Flat::Prim("+".to_string(), vec![Flat::Number(13), Flat::Number(14)]))),
              Flat::Assign("tmp2".to_string(), Box::new(Flat::Prim("+".to_string(), vec![Flat::Number(12), Flat::Symbol("tmp1".to_string())]))),
              Flat::Return(Box::new(Flat::Symbol("tmp2".to_string())))
         ], vec!["tmp1".to_string(), "tmp2".to_string()])
    );
}
<|endoftext|>


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

use byteorder::{LittleEndian, WriteBytesExt};
use euclid::{Point2D, Size2D};
use ipc_channel::ipc::{self, IpcBytesSender, IpcSender};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, DisplayListId, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {StackingContext, StackingContextId, WebGLContextId, WebGLCommand};

impl RenderApiSender {
    pub fn new(api_sender: IpcSender<ApiMsg>,
               payload_sender: IpcBytesSender)
               -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: IpcSender<ApiMsg>,
    pub payload_sender: IpcBytesSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    pub fn delete_image(&self, key: ImageKey) {
        let msg = ApiMsg::DeleteImage(key);
        self.api_sender.send(msg).unwrap();
    }

    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Arguments:
    /// * `stacking_context_id`: The ID of the root stacking context.
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: A monotonically increasing timestamp.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `stacking_contexts`: Stacking contexts used in this frame.
    /// * `display_lists`: Display lists used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId,
                                     viewport_size: Size2D<f32>,
                                     stacking_contexts: Vec<(StackingContextId, StackingContext)>,
                                     display_lists: Vec<(DisplayListId, BuiltDisplayList)>,
                                     auxiliary_lists: AuxiliaryLists) {
        let display_list_descriptors = display_lists.iter().map(|&(display_list_id,
                                                                   ref built_display_list)| {
            (display_list_id, (*built_display_list.descriptor()).clone())
        }).collect();
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id,
                                                 viewport_size,
                                                 stacking_contexts,
                                                 display_list_descriptors,
                                                 *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        let mut payload = vec![];
        payload.write_u32::<LittleEndian>(stacking_context_id.0).unwrap();
        payload.write_u32::<LittleEndian>(epoch.0).unwrap();

        for &(_, ref built_display_list) in &display_lists {
            payload.extend_from_slice(built_display_list.data());
        }
        payload.extend_from_slice(auxiliary_lists.data());

        self.payload_sender.send(&payload[..]).unwrap();
    }

    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>)
                                          -> (Point2D<f32>, PipelineId) {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::GetScrollLayerState(tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    pub fn next_stacking_context_id(&self) -> StackingContextId {
        let new_id = self.next_unique_id();
        StackingContextId(new_id.0, new_id.1)
    }

    #[inline]
    pub fn next_display_list_id(&self) -> DisplayListId {
        let new_id = self.next_unique_id();
        DisplayListId(new_id.0, new_id.1)
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}

<commit_msg>Auto merge of #67 - MSleepyPanda:master, r=glennw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use byteorder::{LittleEndian, WriteBytesExt};
use euclid::{Point2D, Size2D};
use ipc_channel::ipc::{self, IpcBytesSender, IpcSender};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, DisplayListId, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {StackingContext, StackingContextId, WebGLContextId, WebGLCommand};

impl RenderApiSender {
    pub fn new(api_sender: IpcSender<ApiMsg>,
               payload_sender: IpcBytesSender)
               -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: IpcSender<ApiMsg>,
    pub payload_sender: IpcBytesSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Creates an `ImageKey`.
    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    /// Adds an image and returns the corresponding `ImageKey`.
    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Updates a specific image.
    ///
    /// Currently doesn't support changing dimensions or format by updating.
    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    /// Deletes the specific image.
    pub fn delete_image(&self, key: ImageKey) {
        let msg = ApiMsg::DeleteImage(key);
        self.api_sender.send(msg).unwrap();
    }

    /// Sets the root pipeline.
    ///
    /// # Examples
    ///
    /// ```
    /// let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
    /// let api = sender.create_api();
    /// ...
    /// let pipeline_id = PipelineId(0,0);
    /// api.set_root_pipeline(pipeline_id);
    /// ```
    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Non-blocking, it notifies a worker process which processes the stacking context.
    /// When it's done and a RenderNotifier has been set in `webrender::renderer::Renderer`,
    /// [new_frame_ready()][notifier] gets called.
    ///
    /// Note: Scrolling doesn't require an own Frame.
    ///
    /// Arguments:
    ///
    /// * `stacking_context_id`: The ID of the root stacking context.
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: The unique Frame ID, monotonically increasing.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `stacking_contexts`: Stacking contexts used in this frame.
    /// * `display_lists`: Display lists used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    ///
    /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId,
                                     viewport_size: Size2D<f32>,
                                     stacking_contexts: Vec<(StackingContextId, StackingContext)>,
                                     display_lists: Vec<(DisplayListId, BuiltDisplayList)>,
                                     auxiliary_lists: AuxiliaryLists) {
        let display_list_descriptors = display_lists.iter().map(|&(display_list_id,
                                                                   ref built_display_list)| {
            (display_list_id, (*built_display_list.descriptor()).clone())
        }).collect();
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id,
                                                 viewport_size,
                                                 stacking_contexts,
                                                 display_list_descriptors,
                                                 *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        let mut payload = vec![];
        payload.write_u32::<LittleEndian>(stacking_context_id.0).unwrap();
        payload.write_u32::<LittleEndian>(epoch.0).unwrap();

        for &(_, ref built_display_list) in &display_lists {
            payload.extend_from_slice(built_display_list.data());
        }
        payload.extend_from_slice(auxiliary_lists.data());

        self.payload_sender.send(&payload[..]).unwrap();
    }

    /// Scrolls the scrolling layer under the `cursor`
    ///
    /// Webrender looks for the layer closest to the user
    /// which has `ScrollPolicy::Scrollable` set.
    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    /// Translates a point from viewport coordinates to layer space
    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>)
                                          -> (Point2D<f32>, PipelineId) {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::GetScrollLayerState(tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    pub fn next_stacking_context_id(&self) -> StackingContextId {
        let new_id = self.next_unique_id();
        StackingContextId(new_id.0, new_id.1)
    }

    #[inline]
    pub fn next_display_list_id(&self) -> DisplayListId {
        let new_id = self.next_unique_id();
        DisplayListId(new_id.0, new_id.1)
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}

<|endoftext|>


<commit_before>/// Endpoints that cannot change with new versions of the Matrix specification.
pub mod unversioned {
    /// [GET /_matrix/client/versions](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-versions)
    pub mod get_supported_versions {
        use futures::Future;
        use hyper::client::Connect;
        use ruma_client_api::unversioned::get_supported_versions::Endpoint;
        pub use ruma_client_api::unversioned::get_supported_versions::{Request, Response};

        use {Client, Error};

        /// Make a request to this API endpoint.
        pub fn call<'a, C>(
            client: &'a Client<C>,
            request: Request,
        ) -> impl Future<Item = Response, Error = Error> + 'a
        where
            C: Connect,
        {
            client.request::<Endpoint>(request)
        }
    }
}
<commit_msg>Expose all endpoints from ruma-client-api.<commit_after>macro_rules! endpoint {
    // No reexports besides `Request` and `Response`.
    ($(#[$attr:meta])+ [$($outer_mod:ident),*], $inner_mod:ident) => {
        endpoint!($(#[$attr])+ [$($outer_mod),*], $inner_mod, []);
    };

    // No imports from super.
    ($(#[$attr:meta])+ [$($outer_mod:ident),*], $inner_mod:ident, [$($import:ident),*]) => {
        endpoint!($(#[$attr])+ [$($outer_mod),*], $inner_mod, [], []);
    };

    // Explicit case.
    (
        $(#[$attr:meta])+
        [$($outer_mod:ident),*],
        $inner_mod:ident,
        [$($import:ident),*],
        [$($super_import:ident),*]
    ) => {
        #[$($attr)+]
        pub mod $inner_mod {
            use futures::Future;
            use hyper::client::Connect;
            use ruma_client_api::$($outer_mod::)*$inner_mod::Endpoint;
            $(use super::$super_import;)*
            pub use ruma_client_api::$($outer_mod::)*$inner_mod::{
                Request,
                Response,
                $($import),*
            };

            use {Client, Error};

            /// Make a request to this API endpoint.
            pub fn call<'a, C>(
                client: &'a Client<C>,
                request: Request,
            ) -> impl Future<Item = Response, Error = Error> + 'a
            where
                C: Connect,
            {
                client.request::<Endpoint>(request)
            }
        }
    };
}

/// Endpoints for the r0.x.x versions of the client API specification.
pub mod r0 {
    /// Account registration and management.
    pub mod account {
        endpoint!(
            /// Change the password for an account on this homeserver.
            [r0, account],
            change_password
        );

        endpoint!(
            /// Deactivate the user's account, removing all ability for the user to log in again.
            [r0, account],
            deactivate
        );

        endpoint!(
            /// Register for an account on this homeserver.
            [r0, account],
            register,
            [AuthenticationData, RegistrationKind]
        );

        endpoint!(
            /// Request a password change token by email.
            [r0, account],
            request_password_change_token
        );

        endpoint!(
            /// Request an account registration token by email.
            [r0, account],
            request_register_token
        );
    }

    /// Room aliases.
    pub mod alias {
        endpoint!(
            /// Create a new mapping from a room alias to a room ID.
            [r0, alias],
            create_alias
        );

        endpoint!(
            /// Remove a mapping from a room alias to a room ID.
            [r0, alias],
            delete_alias
        );

        endpoint!(
            /// Resolve a room alias to the corresponding room ID.
            [r0, alias],
            get_alias
        );
    }

    /// Client configuration.
    pub mod config {
        endpoint!(
            /// Set account data for the user.
            [r0, config],
            set_global_account_data
        );

        endpoint!(
            /// Set account data scoped to a room for the user.
            [r0, config],
            set_room_account_data
        );
    }

    /// Account contact information.
    pub mod contact {
        endpoint!(
            /// Add contact information to the user's account.
            [r0, contact],
            create_contact,
            [ThreePidCredentials]
        );

        endpoint!(
            /// Get a list of the third party identifiers that the homeserver has associated with the user's account.
            [r0, contact],
            get_contacts,
            [Medium, ThirdPartyIdentifier]
        );

        endpoint!(
            /// Request an email address verification token by email.
            [r0, contact],
            request_contact_verification_token
        );
    }

    /// Event context.
    pub mod context {
        endpoint!(
            /// Get a number of events that happened just before and after a given event.
            [r0, context],
            get_context
        );
    }

    /// The public room directory.
    pub mod directory {
        endpoint!(
            /// Get a number of events that happened just before and after a given event.
            [r0, directory],
            get_public_rooms,
            [PublicRoomsChunk]
        );
    }

    /// Event filters.
    pub mod filter {
        pub use ruma_client_api::r0::filter::{
            EventFormat,
            Filter,
            FilterDefinition,
            RoomEventFilter,
            RoomFilter,
        };

        endpoint!(
            /// Create a new filter.
            [r0, filter],
            create_filter
        );

        endpoint!(
            /// Get a filter.
            [r0, filter],
            get_filter
        );
    }

    /// Media repository.
    pub mod media {
        endpoint!(
            /// Upload media to the media repository.
            [r0, media],
            create_content
        );

        endpoint!(
            /// Download media from the media repository.
            [r0, media],
            get_content
        );

        endpoint!(
            /// Download a thumbnail image  for the media in the media repository.
            [r0, media],
            get_content_thumbnail,
            [Method]
        );
    }

    /// Room membership.
    pub mod membership {
        pub use ruma_client_api::r0::membership::ThirdPartySigned;

        endpoint!(
            /// Ban a user from a room.
            [r0, membership],
            ban_user
        );

        endpoint!(
            /// Permanently forget a room.
            [r0, membership],
            forget_room
        );

        endpoint!(
            /// Invite a user to a room.
            [r0, membership],
            invite_user
        );

        endpoint!(
            /// Join a room using its ID.
            [r0, membership],
            join_room_by_id
        );

        endpoint!(
            /// Join a room using its ID or an alias.
            [r0, membership],
            join_room_by_id_or_alias
        );

        endpoint!(
            /// Kick a user from a room.
            [r0, membership],
            kick_user
        );

        endpoint!(
            /// Leave a room.
            [r0, membership],
            leave_room
        );

        endpoint!(
            /// Unban a user from a room.
            [r0, membership],
            unban_user
        );
    }

    /// User presence.
    pub mod presence {
        endpoint!(
            /// Get a user's presence state.
            [r0, presence],
            get_presence
        );

        endpoint!(
            /// Get a list of presence events for users on the presence subscription list.
            [r0, presence],
            get_subscribed_presences
        );

        endpoint!(
            /// Set a user's presence state.
            [r0, presence],
            set_presence
        );

        endpoint!(
            /// Add or remove users from the presence subscription list.
            [r0, presence],
            update_presence_subscriptions
        );
    }

    /// User profiles.
    pub mod profile {
        endpoint!(
            /// Get the URL for a user's avatar.
            [r0, profile],
            get_avatar_url
        );

        endpoint!(
            /// Get a user's display name.
            [r0, profile],
            get_display_name
        );

        endpoint!(
            /// Get a user's full profile.
            [r0, profile],
            get_profile
        );

        endpoint!(
            /// Set the URL to the user's avatar.
            [r0, profile],
            set_avatar_url
        );

        endpoint!(
            /// Set the user's display name.
            [r0, profile],
            set_display_name
        );
    }

    /// Push notifications.
    pub mod push {
    }

    /// Event receipts.
    pub mod receipt {
        endpoint!(
            /// Update a receipt marker to point to a given event.
            [r0, receipt],
            create_receipt,
            [ReceiptType]
        );
    }

    /// Event redaction.
    pub mod redact {
        endpoint!(
            /// Redact an event from a room.
            [r0, redact],
            redact_event
        );
    }

    /// Room creation.
    pub mod room {
        endpoint!(
            /// Create a room.
            [r0, room],
            create_room,
            [CreationContent, RoomPreset, Visibility]
        );
    }

    /// Event searches.
    pub mod search {
        endpoint!(
            /// Search for events.
            [r0, search],
            search_events,
            [
                Categories,
                Criteria,
                EventContext,
                EventContextResult,
                Grouping,
                Groupings,
                ResultCategories,
                ResultGroup,
                RoomEventResults,
                SearchResult,
                UserProfile,
                GroupingKey,
                OrderBy,
                SearchKeys
            ]
        );
    }

    /// Sending events.
    pub mod send {
        endpoint!(
            /// Send a message to a room.
            [r0, send],
            send_message_event
        );

        endpoint!(
            /// Send a state event with an empty state key.
            [r0, send],
            send_state_event_for_empty_key
        );

        endpoint!(
            /// Send a state event with a particular state key.
            [r0, send],
            send_state_event_for_key
        );
    }

    /// Server administration.
    pub mod server {
        endpoint!(
            /// Get administrative information about a user.
            [r0, server],
            get_user_info,
            [ConnectionInfo, DeviceInfo, SessionInfo]
        );
    }

    /// User session management.
    pub mod session {
        endpoint!(
            /// Log in to an account, creating an access token.
            [r0, session],
            login,
            [LoginType, Medium]
        );

        endpoint!(
            /// Log out of an account by invalidating the access token.
            [r0, session],
            logout
        );
    }

    /// Getting and synchronizing events.
    pub mod sync {
        endpoint!(
            /// Get the list of members for a room.
            [r0, sync],
            get_member_events
        );

        endpoint!(
            /// Get message and state events for a room.
            [r0, sync],
            get_message_events,
            [Direction]
        );

        endpoint!(
            /// Get the state events for the current state of a room.
            [r0, sync],
            get_state_events
        );

        endpoint!(
            /// Get a particular state event with an empty state key for a room.
            [r0, sync],
            get_state_events_for_empty_key
        );

        endpoint!(
            /// Get a particular state event with a particular state key for a room.
            [r0, sync],
            get_state_events_for_key
        );

        endpoint!(
            /// Synchronize the client's state with the latest state on the homeserver.
            [r0, sync],
            sync_events,
            [
                AccountData,
                Ephemeral,
                Filter,
                InviteState,
                InvitedRoom,
                JoinedRoom,
                LeftRoom,
                Presence,
                Rooms,
                SetPresence,
                State,
                Timeline,
                UnreadNotificationsCount
            ]
        );
    }

    /// Tagging rooms.
    pub mod tag {
        endpoint!(
            /// Create a tag on a room.
            [r0, tag],
            create_tag
        );

        endpoint!(
            /// Delete a tag on a room.
            [r0, tag],
            delete_tag
        );

        endpoint!(
            /// Get the user's tags for a room.
            [r0, tag],
            get_tags
        );
    }

    /// Typing notifications.
    pub mod typing {
        endpoint!(
            /// Indicate that the user is currently typing.
            [r0, typing],
            create_typing_event
        );
    }

    /// Voice over IP.
    pub mod voip {
        endpoint!(
            /// Get credentials for initiating voice over IP calls via a TURN server.
            [r0, voip],
            get_turn_server_info
        );
    }
}

/// Endpoints that cannot change with new versions of the Matrix specification.
pub mod unversioned {
    endpoint!(
        /// Get the versions of the specification supported by this homeserver.
        [unversioned],
        get_supported_versions
    );
}
<|endoftext|>


<commit_before>
use std::io::Cursor;

use rustc_serialize::json;
use rustc_serialize::json::Json;
use tiny_http::{Response, StatusCode};

use http::{ok, okJson, http_response};

use table::Tables;
use table::TableError;

pub fn post_table(tables: &mut Tables, table: &str) -> Response<Cursor<Vec<u8>>> {
    println!("Creating Table: {}", table);
    match tables.create_table(table) {
        Err(e) => handle_table_error(e),
        Ok(_) => ok(format!("Successfully Created Table: {}", table))
    }
//    ok(format!("Creating table {}", table))
}

pub fn post_key_to_table(tables: &mut Tables, table: &str, key: &str, data: Json) -> Response<Cursor<Vec<u8>>> {
    ok(format!("Creating key {} on table: {} with data: {:?}", key, table, data))
}

//pub fn post_table(table: &str) -> Response<Cursor<Vec<u8>>> {
//    ok(format!("Creating table {}", table))
//}

pub fn get_key(tables: &mut Tables, table: &str, key: &str) -> Response<Cursor<Vec<u8>>> {
    okJson(Json::from_str("{\"foo\":\"bar\"}").unwrap())
}

fn handle_table_error(error: TableError) -> Response<Cursor<Vec<u8>>> {
    match error {
        TableError::TableDoesNotExist => http_response(StatusCode(400), "Table does not exist"),
        TableError::TableAlreadyExists => http_response(StatusCode(400), "Table already exists"),
        TableError::KeyAlreadyPresent => http_response(StatusCode(400), "Key already present"),
        TableError::KeyDoesNotExist => http_response(StatusCode(400), "Key does not exist"),
    }
}
<commit_msg>Finishing more of the api<commit_after>
use std::io::Cursor;

use rustc_serialize::json;
use rustc_serialize::json::Json;
use tiny_http::{Response, StatusCode};

use http::{ok, okJson, http_response};

use table::Tables;
use table::TableError;

pub fn post_table(tables: &mut Tables, table: &str) -> Response<Cursor<Vec<u8>>> {
    println!("Creating Table: {}", table);
    match tables.create_table(table) {
        Err(e) => handle_table_error(e),
        Ok(_) => ok(format!("Successfully Created Table: {}", table))
    }
}

pub fn post_key_to_table(tables: &mut Tables, table: &str, key: &str, data: Json) -> Response<Cursor<Vec<u8>>> {
    match tables.put(table, key, data) {
        Err(e) => handle_table_error(e),
        Ok(_) => ok(format!("Successfully added key: {} to table {}", key, table))
    }
}

pub fn get_key(tables: &mut Tables, table: &str, key: &str) -> Response<Cursor<Vec<u8>>> {
    match tables.get(table, key) {
        Err(e) => handle_table_error(e),
        Ok(json) => okJson(json),
    }
//    okJson(Json::from_str("{\"foo\":\"bar\"}").unwrap())
}

fn handle_table_error(error: TableError) -> Response<Cursor<Vec<u8>>> {
    match error {
        TableError::TableDoesNotExist => http_response(StatusCode(400), "Table does not exist"),
        TableError::TableAlreadyExists => http_response(StatusCode(400), "Table already exists"),
        TableError::KeyAlreadyPresent => http_response(StatusCode(400), "Key already present"),
        TableError::KeyDoesNotExist => http_response(StatusCode(400), "Key does not exist"),
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate dent;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{SigLevel, TTest, welch_t_test};

use std::fs::File;
use std::path::Path;
use std::io::{self, BufRead, BufReader};

fn print_summary(s: &Summary) {
    println!("N\tMin\tMax\tMedian\tMean\tStdDev\tStdErr");
    println!(
        "{}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}",
        s.size(),
        s.min(),
        s.max(),
        s.median(),
        s.mean(),
        s.standard_deviation(),
        s.standard_error(),
    );
}

fn print_t_test(t_test: &TTest) {
    println!("T\tDF\tAlpha\tCrit\tRejectNull");
    println!(
        "{:0.3}\t{}\t{:0.3}\t{:0.3}\t{}",
        t_test.t,
        t_test.df,
        t_test.alpha,
        t_test.crit,
        t_test.reject,
    );
}

fn read_file(path: &str) -> Summary {
    let p = Path::new(path);
    let f = File::open(p).unwrap();
    let r = BufReader::new(f);

    let data: Vec<f64> = r
        .lines()
        .map(|l| l.unwrap().parse().unwrap())
        .collect();

    Summary::new(&data).unwrap()
}

fn parse_alpha(arg: &str) -> SigLevel {
    match arg {
        ".001" => SigLevel::Alpha001,
        ".005" => SigLevel::Alpha005,
        ".01"  => SigLevel::Alpha010,
        ".025" => SigLevel::Alpha025,
        ".05"  => SigLevel::Alpha050,
        ".1"   => SigLevel::Alpha100,
        _ => panic!(),
    }
}

fn summarize_stdin(draw_plot: bool, width: usize, ascii: bool) {
    let stdin = io::stdin();

    let data: Vec<f64> = stdin
        .lock()
        .lines()
        .map(|l| l.unwrap().parse().unwrap())
        .collect();

    let s = Summary::new(&data).unwrap();

    if draw_plot {
        println!("{}\n", plot::summary_plot(&s, width, ascii));
    }

    print_summary(&s);
}

fn t_test_files(
    file1: &str,
    file2: &str,
    alpha: SigLevel,
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    let s1 = read_file(file1);
    let s2 = read_file(file2);

    let t_test = welch_t_test(&s1, &s2, alpha);

    if draw_plot {
        println!("{}\n", plot::comparison_plot(&s1, &s2, width, ascii, true));
    }

    print_summary(&s1);
    println!();
    print_summary(&s2);
    println!();
    print_t_test(&t_test);
}

fn main() {
    let matches = App::new("dent")
        .version("0.1.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin."))
        .arg(Arg::with_name("file1")
             .index(1)
             .value_name("FILE1")
             .takes_value(true)
             .required_unless("stdin")
             .help("1st file of sample data."))
        .arg(Arg::with_name("file2")
             .index(2)
             .value_name("FILE2")
             .takes_value(true)
             .required_unless("stdin")
             .help("2nd file of sample data."))
        .arg(Arg::with_name("alpha")
             .short("a")
             .long("alpha")
             .value_name("ALPHA")
             .help("Significance level α")
             .takes_value(true)
             .default_value(".05"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Draw a box-and-whisker plot."))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in plots."))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    if use_stdin {
        summarize_stdin(draw_plot, width, ascii);
    } else {
        let alpha = parse_alpha(matches.value_of("alpha").unwrap());
        let file1 = matches.value_of("file1").unwrap();
        let file2 = matches.value_of("file2").unwrap();

        t_test_files(file1, file2, alpha, draw_plot, width, ascii);
    }
}
<commit_msg>Update help text for command-line args<commit_after>extern crate clap;
extern crate dent;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{SigLevel, TTest, welch_t_test};

use std::fs::File;
use std::path::Path;
use std::io::{self, BufRead, BufReader};

fn print_summary(s: &Summary) {
    println!("N\tMin\tMax\tMedian\tMean\tStdDev\tStdErr");
    println!(
        "{}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}",
        s.size(),
        s.min(),
        s.max(),
        s.median(),
        s.mean(),
        s.standard_deviation(),
        s.standard_error(),
    );
}

fn print_t_test(t_test: &TTest) {
    println!("T\tDF\tAlpha\tCrit\tRejectNull");
    println!(
        "{:0.3}\t{}\t{:0.3}\t{:0.3}\t{}",
        t_test.t,
        t_test.df,
        t_test.alpha,
        t_test.crit,
        t_test.reject,
    );
}

fn read_file(path: &str) -> Summary {
    let p = Path::new(path);
    let f = File::open(p).unwrap();
    let r = BufReader::new(f);

    let data: Vec<f64> = r
        .lines()
        .map(|l| l.unwrap().parse().unwrap())
        .collect();

    Summary::new(&data).unwrap()
}

fn parse_alpha(arg: &str) -> SigLevel {
    match arg {
        ".001" => SigLevel::Alpha001,
        ".005" => SigLevel::Alpha005,
        ".01"  => SigLevel::Alpha010,
        ".025" => SigLevel::Alpha025,
        ".05"  => SigLevel::Alpha050,
        ".1"   => SigLevel::Alpha100,
        _ => panic!(),
    }
}

fn summarize_stdin(draw_plot: bool, width: usize, ascii: bool) {
    let stdin = io::stdin();

    let data: Vec<f64> = stdin
        .lock()
        .lines()
        .map(|l| l.unwrap().parse().unwrap())
        .collect();

    let s = Summary::new(&data).unwrap();

    if draw_plot {
        println!("{}\n", plot::summary_plot(&s, width, ascii));
    }

    print_summary(&s);
}

fn t_test_files(
    file1: &str,
    file2: &str,
    alpha: SigLevel,
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    let s1 = read_file(file1);
    let s2 = read_file(file2);

    let t_test = welch_t_test(&s1, &s2, alpha);

    if draw_plot {
        println!("{}\n", plot::comparison_plot(&s1, &s2, width, ascii, true));
    }

    print_summary(&s1);
    println!();
    print_summary(&s2);
    println!();
    print_t_test(&t_test);
}

fn main() {
    let matches = App::new("dent")
        .version("0.1.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("file1")
             .index(1)
             .value_name("FILE1")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to 1st file of sample data"))
        .arg(Arg::with_name("file2")
             .index(2)
             .value_name("FILE2")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to 2nd file of sample data"))
        .arg(Arg::with_name("alpha")
             .short("a")
             .long("alpha")
             .value_name("ALPHA")
             .help("Significance level α")
             .takes_value(true)
             .default_value(".05"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    if use_stdin {
        summarize_stdin(draw_plot, width, ascii);
    } else {
        let alpha = parse_alpha(matches.value_of("alpha").unwrap());
        let file1 = matches.value_of("file1").unwrap();
        let file2 = matches.value_of("file2").unwrap();

        t_test_files(file1, file2, alpha, draw_plot, width, ascii);
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate dent;
extern crate term;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{TTest, welch_t_test};

use std::error;
use std::fs::File;
use std::io::{self, BufRead, BufReader};

mod fmt;
mod log;

macro_rules! ok {
    ($r: expr) => {
        match $r {
            Ok(t) => t,
            Err(e) => {
                log::error(&format!("{}", e));
                std::process::exit(1);
            }
        }
    }
}

fn print_summary(s: &Summary, outliers: bool) {
    let width = 10;
    let size_width = 6;

    if outliers {
        println!(
            "{n:>nw$}  {min:>w$}  {q1:>w$}  {med:>w$}  {q3:>w$}  {max:>w$}  {mean:>w$}  {std:>w$}",
            w = width,
            nw = size_width,
            n = "Size",
            min = "Min",
            q1 = "Q1",
            med = "Median",
            q3 = "Q3",
            max = "Max",
            mean = "Mean",
            std = "Std Dev",
        );
        println!(
            "{n:>nw$}  {min:>w$}  {q1:>w$}  {med:>w$}  {q3:>w$}  {max:>w$}  {mean:>w$}  {std:>w$}",
            w = width,
            nw = size_width,
            n = fmt::f(s.size(), width),
            min = fmt::f(s.min(), width),
            q1 = fmt::f(s.lower_quartile(), width),
            med = fmt::f(s.median(), width),
            q3 = fmt::f(s.upper_quartile(), width),
            max = fmt::f(s.max(), width),
            mean = fmt::f(s.mean(), width),
            std = fmt::f(s.standard_deviation(), width),
        );
    } else {
        println!(
            "{n:>nw$}  {min:>w$}  {q1:>w$}  {med:>w$}  {q3:>w$}  {max:>w$}  {mean:>w$}  {std:>w$}",
            w = width,
            nw = size_width,
            n = "Size",
            min = "Min Adj",
            q1 = "Q1",
            med = "Median",
            q3 = "Q3",
            max = "Max Adj",
            mean = "Mean",
            std = "Std Dev",
        );
        println!(
            "{n:>nw$}  {min:>w$}  {q1:>w$}  {med:>w$}  {q3:>w$}  {max:>w$}  {mean:>w$}  {std:>w$}",
            w = width,
            nw = size_width,
            n = fmt::f(s.size(), width),
            min = fmt::f(s.min_adjacent(), width),
            q1 = fmt::f(s.lower_quartile(), width),
            med = fmt::f(s.median(), width),
            q3 = fmt::f(s.upper_quartile(), width),
            max = fmt::f(s.max_adjacent(), width),
            mean = fmt::f(s.mean(), width),
            std = fmt::f(s.standard_deviation(), width),
        );
    }
}

fn print_t_test(t_test: &TTest) {
    let width = 12;

    println!("{l:>w$} = {v}", w = width, l = "t", v = t_test.t);
    println!("{l:>w$} = {v}", w = width, l = "p", v = t_test.p);
    println!("{l:>w$} = {v}", w = width, l = "DF", v = t_test.df);
}

fn summarize_file(path: &str, lax_parsing: bool) -> Result<Summary, Box<error::Error>> {
    let f = File::open(path).or_else(|e| {
        log::error(&format!("Could not open file: {:?}", path));
        Err(e)
    })?;
    let reader = BufReader::new(f);

    let data = read_data(reader, lax_parsing)?;

    Ok(Summary::new(&data)?)
}

fn read_data<R>(reader: R, lax_parsing: bool) -> Result<Vec<f64>, Box<error::Error>>
    where R: BufRead {
    let mut data: Vec<f64> = vec![];

    for l in reader.lines() {
        let s = l?.trim().to_string();

        if s.is_empty() {
            continue;
        }

        match s.parse() {
            Ok(d) => data.push(d),
            err => if !lax_parsing { err?; }
        }
    }

    Ok(data)
}

fn summarize_stdin(lax_parsing: bool) -> Result<Summary, Box<error::Error>> {
    let stdin = io::stdin();
    let data = read_data(stdin.lock(), lax_parsing)?;

    Ok(Summary::new(&data)?)
}

fn display_t_test(
    summary1: &Summary,
    summary2: &Summary,
    draw_plot: bool,
    width: usize,
    ascii: bool,
    outliers: bool,
) {
    let t_test = ok!(welch_t_test(&summary1, &summary2));

    if draw_plot {
        let p = ok!(plot::comparison_plot(&[summary1, summary2], width, ascii, true, outliers));
        println!("{}\n", p);
    }

    print_summary(&summary1, outliers);
    println!();
    print_summary(&summary2, outliers);
    println!();
    print_t_test(&t_test);
}

fn display_summaries(
    summaries: &[Summary],
    draw_plot: bool,
    width: usize,
    ascii: bool,
    outliers: bool,
) {
    if draw_plot {
        let summary_refs: Vec<&Summary> = summaries
            .iter()
            .collect();

        let plot = ok!(plot::comparison_plot(&summary_refs, width, ascii, true, true));
        println!("{}\n", plot);
    }

    for i in 0..summaries.len() {
        if i > 0 {
            println!();
        }
        print_summary(&summaries[i], outliers);
    }
}

fn main() {
    let matches = App::new("dent")
        .version("0.3.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("files")
             .multiple(true)
             .value_name("FILES")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to one or more files of sample data"))
        .arg(Arg::with_name("lax")
             .long("lax")
             .help("Ignore non-numeric input lines"))
        .arg(Arg::with_name("plot_outliers")
             .long("outliers")
             .help("Include outliers and use min/max for outer fences of boxplot"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let lax_parsing = matches.is_present("lax");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");
    let outliers = matches.is_present("plot_outliers");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    let summaries = if use_stdin {
        vec![ok!(summarize_stdin(lax_parsing))]
    } else {
        // Required if `stdin` is not present, so we can unwrap.
        matches.values_of("files")
            .unwrap_or_else(|| unreachable!())
            .map(|f| ok!(summarize_file(f, lax_parsing)))
            .collect()
    };

    match summaries.len() {
        0 => unreachable!(),
        // We want match 1 with the case `len()` > 2.
        2 => {
            display_t_test(
                &summaries[0],
                &summaries[1],
                draw_plot,
                width,
                ascii,
                outliers,
            );
        }
        _ => {
            display_summaries(
                &summaries,
                draw_plot,
                width,
                ascii,
                outliers,
            );
        },
    };
}
<commit_msg>Restate means with standard errors in comparison table<commit_after>extern crate clap;
extern crate dent;
extern crate term;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{TTest, welch_t_test};

use std::error;
use std::fs::File;
use std::io::{self, BufRead, BufReader};

mod fmt;
mod log;

macro_rules! ok {
    ($r: expr) => {
        match $r {
            Ok(t) => t,
            Err(e) => {
                log::error(&format!("{}", e));
                std::process::exit(1);
            }
        }
    }
}

fn print_summary(s: &Summary, outliers: bool) {
    let width = 10;
    let size_width = 6;

    if outliers {
        println!(
            "{n:>nw$}  {min:>w$}  {q1:>w$}  {med:>w$}  {q3:>w$}  {max:>w$}  {mean:>w$}  {std:>w$}",
            w = width,
            nw = size_width,
            n = "Size",
            min = "Min",
            q1 = "Q1",
            med = "Median",
            q3 = "Q3",
            max = "Max",
            mean = "Mean",
            std = "Std Dev",
        );
        println!(
            "{n:>nw$}  {min:>w$}  {q1:>w$}  {med:>w$}  {q3:>w$}  {max:>w$}  {mean:>w$}  {std:>w$}",
            w = width,
            nw = size_width,
            n = fmt::f(s.size(), width),
            min = fmt::f(s.min(), width),
            q1 = fmt::f(s.lower_quartile(), width),
            med = fmt::f(s.median(), width),
            q3 = fmt::f(s.upper_quartile(), width),
            max = fmt::f(s.max(), width),
            mean = fmt::f(s.mean(), width),
            std = fmt::f(s.standard_deviation(), width),
        );
    } else {
        println!(
            "{n:>nw$}  {min:>w$}  {q1:>w$}  {med:>w$}  {q3:>w$}  {max:>w$}  {mean:>w$}  {std:>w$}",
            w = width,
            nw = size_width,
            n = "Size",
            min = "Min Adj",
            q1 = "Q1",
            med = "Median",
            q3 = "Q3",
            max = "Max Adj",
            mean = "Mean",
            std = "Std Dev",
        );
        println!(
            "{n:>nw$}  {min:>w$}  {q1:>w$}  {med:>w$}  {q3:>w$}  {max:>w$}  {mean:>w$}  {std:>w$}",
            w = width,
            nw = size_width,
            n = fmt::f(s.size(), width),
            min = fmt::f(s.min_adjacent(), width),
            q1 = fmt::f(s.lower_quartile(), width),
            med = fmt::f(s.median(), width),
            q3 = fmt::f(s.upper_quartile(), width),
            max = fmt::f(s.max_adjacent(), width),
            mean = fmt::f(s.mean(), width),
            std = fmt::f(s.standard_deviation(), width),
        );
    }
}

fn print_t_test(t_test: &TTest, s1: &Summary, s2: &Summary) {
    let width = 12;

    println!("{l:>w$} = {v} ± {se}", w = width, l = "m₁ ± SE", v = s1.mean(), se = s1.standard_error());
    println!("{l:>w$} = {v} ± {se}", w = width, l = "m₂ ± SE", v = s2.mean(), se = s2.standard_error());
    println!("{l:>w$} = {v}", w = width, l = "t", v = t_test.t);
    println!("{l:>w$} = {v}", w = width, l = "p", v = t_test.p);
    println!("{l:>w$} = {v}", w = width, l = "DF", v = t_test.df);
}

fn summarize_file(path: &str, lax_parsing: bool) -> Result<Summary, Box<error::Error>> {
    let f = File::open(path).or_else(|e| {
        log::error(&format!("Could not open file: {:?}", path));
        Err(e)
    })?;
    let reader = BufReader::new(f);

    let data = read_data(reader, lax_parsing)?;

    Ok(Summary::new(&data)?)
}

fn read_data<R>(reader: R, lax_parsing: bool) -> Result<Vec<f64>, Box<error::Error>>
    where R: BufRead {
    let mut data: Vec<f64> = vec![];

    for l in reader.lines() {
        let s = l?.trim().to_string();

        if s.is_empty() {
            continue;
        }

        match s.parse() {
            Ok(d) => data.push(d),
            err => if !lax_parsing { err?; }
        }
    }

    Ok(data)
}

fn summarize_stdin(lax_parsing: bool) -> Result<Summary, Box<error::Error>> {
    let stdin = io::stdin();
    let data = read_data(stdin.lock(), lax_parsing)?;

    Ok(Summary::new(&data)?)
}

fn display_t_test(
    summary1: &Summary,
    summary2: &Summary,
    draw_plot: bool,
    width: usize,
    ascii: bool,
    outliers: bool,
) {
    let t_test = ok!(welch_t_test(&summary1, &summary2));

    if draw_plot {
        let p = ok!(plot::comparison_plot(&[summary1, summary2], width, ascii, true, outliers));
        println!("{}\n", p);
    }

    print_summary(&summary1, outliers);
    println!();
    print_summary(&summary2, outliers);
    println!();
    print_t_test(&t_test, &summary1, &summary2);
}

fn display_summaries(
    summaries: &[Summary],
    draw_plot: bool,
    width: usize,
    ascii: bool,
    outliers: bool,
) {
    if draw_plot {
        let summary_refs: Vec<&Summary> = summaries
            .iter()
            .collect();

        let plot = ok!(plot::comparison_plot(&summary_refs, width, ascii, true, true));
        println!("{}\n", plot);
    }

    for i in 0..summaries.len() {
        if i > 0 {
            println!();
        }
        print_summary(&summaries[i], outliers);
    }
}

fn main() {
    let matches = App::new("dent")
        .version("0.3.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("files")
             .multiple(true)
             .value_name("FILES")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to one or more files of sample data"))
        .arg(Arg::with_name("lax")
             .long("lax")
             .help("Ignore non-numeric input lines"))
        .arg(Arg::with_name("plot_outliers")
             .long("outliers")
             .help("Include outliers and use min/max for outer fences of boxplot"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let lax_parsing = matches.is_present("lax");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");
    let outliers = matches.is_present("plot_outliers");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    let summaries = if use_stdin {
        vec![ok!(summarize_stdin(lax_parsing))]
    } else {
        // Required if `stdin` is not present, so we can unwrap.
        matches.values_of("files")
            .unwrap_or_else(|| unreachable!())
            .map(|f| ok!(summarize_file(f, lax_parsing)))
            .collect()
    };

    match summaries.len() {
        0 => unreachable!(),
        // We want match 1 with the case `len()` > 2.
        2 => {
            display_t_test(
                &summaries[0],
                &summaries[1],
                draw_plot,
                width,
                ascii,
                outliers,
            );
        }
        _ => {
            display_summaries(
                &summaries,
                draw_plot,
                width,
                ascii,
                outliers,
            );
        },
    };
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate tokio_process;

use self::futures::future::Future;
use self::futures::Stream;
use self::hyper::header::ContentEncoding;
use self::hyper::header::ContentLength;
use self::hyper::header::ContentType;
use self::hyper::server::{Request, Response};
use cgi::tokio_process::CommandExt;
use std::io;
use std::io::BufRead;
use std::io::Read;
use std::io::Write;
use std::process::Command;
use std::process::Stdio;
use std::str::FromStr;

pub fn do_cgi(
    req: Request,
    cmd: Command,
    handle: tokio_core::reactor::Handle,
) -> Box<Future<Item = Response, Error = hyper::Error>> {
    trace_scoped!("do_cgi");
    let mut cmd = cmd;
    cmd.stdout(Stdio::piped());
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::piped());
    println!("REQUEST_METHOD {:?}", req.method());
    cmd.env("SERVER_SOFTWARE", "hyper")
        .env("SERVER_NAME", "localhost") // TODO
        .env("GATEWAY_INTERFACE", "CGI/1.1")
        .env("SERVER_PROTOCOL", "HTTP/1.1") // TODO
        .env("SERVER_PORT", "80") // TODO
        .env("REQUEST_METHOD", format!("{}", req.method()))
        .env("SCRIPT_NAME", "") // TODO
        .env("QUERY_STRING", req.query().unwrap_or(""))
        .env("REMOTE_ADDR", "") // TODO
        .env("AUTH_TYPE", "") // TODO
        .env("REMOTE_USER", "") // TODO
        .env(
            "CONTENT_TYPE",
            &format!(
                "{}",
                req.headers().get().unwrap_or(&ContentType::plaintext())
            ),
        )
        .env(
            "HTTP_CONTENT_ENCODING",
            &format!(
                "{}",
                req.headers().get().unwrap_or(&ContentEncoding(vec![]))
            ),
        )
        .env(
            "CONTENT_LENGTH",
            &format!("{}", req.headers().get().unwrap_or(&ContentLength(0))),
        );

    let mut child = cmd
        .spawn_async_with_handle(&handle.new_tokio_handle())
        .expect("can't spawn CGI command");

    Box::new(req.body().concat2().and_then(move |body| {
        if !child.stdin().take().unwrap().write_all(&body).is_ok() {
            debug!("write_all(body) failed");
        }

        child
            .wait_with_output()
            .map(build_response)
            .map_err(|e| e.into())
    }))
}

fn build_response(command_result: std::process::Output) -> Response {
    trace_begin!("build_response");
    let mut stdout = io::BufReader::new(command_result.stdout.as_slice());
    let mut stderr = io::BufReader::new(command_result.stderr.as_slice());

    let mut response = Response::new();

    let mut headers = vec![];
    for line in stdout.by_ref().lines() {
        println!("STDOUT line: {:?}", line);
        if line.as_ref().unwrap().is_empty() {
            break;
        }
        let l: Vec<&str> = line.as_ref().unwrap().as_str().splitn(2, ": ").collect();
        for x in &l {
            headers.push(x.to_string());
        }
        if l[0] == "Status" {
            response.set_status(hyper::StatusCode::Unregistered(
                u16::from_str(l[1].split(" ").next().unwrap()).unwrap(),
            ));
        } else {
            response
                .headers_mut()
                .set_raw(l[0].to_string(), l[1].to_string());
        }
    }

    let mut data = vec![];
    stdout
        .read_to_end(&mut data)
        .expect("can't read command output");

    let mut stderrdata = vec![];
    stderr
        .read_to_end(&mut stderrdata)
        .expect("can't read command output");

    let out = String::from_utf8_lossy(&data).to_string();
    let err = String::from_utf8_lossy(&stderrdata);

    println!("build_response out {:?}", &out);
    println!("build_response err {:?}", &err);

    trace_end!(
        "build_response",
        "stdout": out,
        "stderr": err,
        "headers": headers
    );
    response.set_body(hyper::Chunk::from(data));

    response
}
<commit_msg>dont put whole repo into trace<commit_after>extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate tokio_process;

use self::futures::future::Future;
use self::futures::Stream;
use self::hyper::header::ContentEncoding;
use self::hyper::header::ContentLength;
use self::hyper::header::ContentType;
use self::hyper::server::{Request, Response};
use cgi::tokio_process::CommandExt;
use std::io;
use std::io::BufRead;
use std::io::Read;
use std::io::Write;
use std::process::Command;
use std::process::Stdio;
use std::str::FromStr;

pub fn do_cgi(
    req: Request,
    cmd: Command,
    handle: tokio_core::reactor::Handle,
) -> Box<Future<Item = Response, Error = hyper::Error>> {
    trace_scoped!("do_cgi");
    let mut cmd = cmd;
    cmd.stdout(Stdio::piped());
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::piped());
    println!("REQUEST_METHOD {:?}", req.method());
    cmd.env("SERVER_SOFTWARE", "hyper")
        .env("SERVER_NAME", "localhost") // TODO
        .env("GATEWAY_INTERFACE", "CGI/1.1")
        .env("SERVER_PROTOCOL", "HTTP/1.1") // TODO
        .env("SERVER_PORT", "80") // TODO
        .env("REQUEST_METHOD", format!("{}", req.method()))
        .env("SCRIPT_NAME", "") // TODO
        .env("QUERY_STRING", req.query().unwrap_or(""))
        .env("REMOTE_ADDR", "") // TODO
        .env("AUTH_TYPE", "") // TODO
        .env("REMOTE_USER", "") // TODO
        .env(
            "CONTENT_TYPE",
            &format!(
                "{}",
                req.headers().get().unwrap_or(&ContentType::plaintext())
            ),
        )
        .env(
            "HTTP_CONTENT_ENCODING",
            &format!(
                "{}",
                req.headers().get().unwrap_or(&ContentEncoding(vec![]))
            ),
        )
        .env(
            "CONTENT_LENGTH",
            &format!("{}", req.headers().get().unwrap_or(&ContentLength(0))),
        );

    let mut child = cmd
        .spawn_async_with_handle(&handle.new_tokio_handle())
        .expect("can't spawn CGI command");

    Box::new(req.body().concat2().and_then(move |body| {
        if !child.stdin().take().unwrap().write_all(&body).is_ok() {
            debug!("write_all(body) failed");
        }

        child
            .wait_with_output()
            .map(build_response)
            .map_err(|e| e.into())
    }))
}

fn build_response(command_result: std::process::Output) -> Response {
    trace_begin!("build_response");
    let mut stdout = io::BufReader::new(command_result.stdout.as_slice());
    let mut stderr = io::BufReader::new(command_result.stderr.as_slice());

    let mut response = Response::new();

    let mut headers = vec![];
    for line in stdout.by_ref().lines() {
        println!("STDOUT line: {:?}", line);
        if line.as_ref().unwrap().is_empty() {
            break;
        }
        let l: Vec<&str> = line.as_ref().unwrap().as_str().splitn(2, ": ").collect();
        for x in &l {
            headers.push(x.to_string());
        }
        if l[0] == "Status" {
            response.set_status(hyper::StatusCode::Unregistered(
                u16::from_str(l[1].split(" ").next().unwrap()).unwrap(),
            ));
        } else {
            response
                .headers_mut()
                .set_raw(l[0].to_string(), l[1].to_string());
        }
    }

    let mut data = vec![];
    stdout
        .read_to_end(&mut data)
        .expect("can't read command output");

    let mut stderrdata = vec![];
    stderr
        .read_to_end(&mut stderrdata)
        .expect("can't read command output");

    /* let out = String::from_utf8_lossy(&data).to_string(); */
    let err = String::from_utf8_lossy(&stderrdata);

    /* println!("build_response out {:?}", &out); */
    println!("build_response err {:?}", &err);

    trace_end!(
        "build_response",
        /* "stdout": out, */
        "stderr": err,
        "headers": headers
    );
    response.set_body(hyper::Chunk::from(data));

    response
}
<|endoftext|>


<commit_before>//! Utilities for finding and working with `conductor` project directories.

use std::path::{Path, PathBuf};

use util::Error;

/// Walk up the directory tree until we find a directory that looks like a
/// `conductor` project.
pub fn find_project(start_dir: &Path) -> Result<PathBuf, Error> {
    // Do this as a loop, not recusively, so we can use `start_dir` in
    // error messages.
    let mut dir = start_dir;
    loop {
        if dir.join("pods").exists() {
            return Ok(dir.to_owned());
        } else {
            if let Some(parent) = dir.parent() {
                dir = parent;
            } else {
                let err = err!("could not find conductor project in {}", start_dir.display());
                return Err(err);
            }
        }
    }
}

#[test]
fn find_project_walks_up_directory_tree() {
    assert_eq!(find_project(Path::new("examples/hello")).unwrap(),
               Path::new("examples/hello"));
    assert_eq!(find_project(Path::new("examples/hello/pods")).unwrap(),
               Path::new("examples/hello"));
    assert!(find_project(Path::new("examples")).is_err());
}
<commit_msg>Clarify error message to mention project directory search<commit_after>//! Utilities for finding and working with `conductor` project directories.

use std::path::{Path, PathBuf};

use util::Error;

/// Walk up the directory tree until we find a directory that looks like a
/// `conductor` project.
pub fn find_project(start_dir: &Path) -> Result<PathBuf, Error> {
    // Do this as a loop, not recusively, so we can use `start_dir` in
    // error messages.
    let mut dir = start_dir;
    loop {
        if dir.join("pods").exists() {
            return Ok(dir.to_owned());
        } else {
            if let Some(parent) = dir.parent() {
                dir = parent;
            } else {
                let err = err!("could not find conductor project in {} or any directory above it", start_dir.display());
                return Err(err);
            }
        }
    }
}

#[test]
fn find_project_walks_up_directory_tree() {
    assert_eq!(find_project(Path::new("examples/hello")).unwrap(),
               Path::new("examples/hello"));
    assert_eq!(find_project(Path::new("examples/hello/pods")).unwrap(),
               Path::new("examples/hello"));
    assert!(find_project(Path::new("examples")).is_err());
}
<|endoftext|>


<commit_before>use {Int, LargeInt, U64};

/// Returns `n / d`
#[no_mangle]
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
    let u32_bits = u32::bits() as u32;

    // Special cases
    if d == 0 {
        return 0; // ?!
    }

    if n == 0 {
        return 0;
    }

    let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros());

    // d > n
    if sr > u32_bits - 1 {
        return 0;
    }

    // d == 1
    if sr == u32_bits - 1 {
        return n;
    }

    sr = sr + 1;

    // 1 <= sr <= u32_bits - 1
    let mut q = n << (u32_bits - sr);
    let mut r = n >> sr;

    let mut carry = 0;
    for _ in 0..sr {
        // r:q = ((r:q) << 1) | carry
        r = (r << 1) | (q >> (u32_bits - 1));
        q = (q << 1) | carry;

        // carry = 0;
        // if r > d {
        //     r -= d;
        //     carry = 1;
        // }

        let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32_bits - 1);
        carry = (s & 1) as u32;
        r -= d & s as u32;
    }

    q = (q << 1) | carry;
    q
}

/// Returns `n / d` and sets `*rem = n % d`
#[no_mangle]
pub extern "C" fn __udivmodsi4(a: u32, b: u32, rem: Option<&mut u32>) -> u32 {
    let d = __udivsi3(a, b);
    if let Some(rem) = rem {
        *rem = a - (d * b);
    }
    return d;
}

/// Returns `n / d` and sets `*rem = n % d`
#[no_mangle]
pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
    let u32_bits = u32::bits() as u32;
    let u64_bits = u64::bits() as u32;

    // NOTE X is unknown, K != 0
    if n.high() == 0 {
        if d.high() == 0 {
            // 0 X
            // ---
            // 0 X

            if let Some(rem) = rem {
                *rem = u64::from(n.low() % d.low());
            }
            return u64::from(n.low() / d.low());
        } else
        // d.high() != 0
        {
            // 0 X
            // ---
            // K X

            if let Some(rem) = rem {
                *rem = u64::from(n.low());
            }
            return 0;
        };
    }

    let mut sr;
    let mut q = U64 { low: 0, high: 0 };
    let mut r = U64 { low: 0, high: 0 };

    // n.high() != 0
    if d.low() == 0 {
        if d.high() == 0 {
            // K X
            // ---
            // 0 0

            // NOTE copied verbatim from compiler-rt. This probably lets the intrinsic decide how to
            // handle the division by zero (SIGFPE, 0, etc.). But this part shouldn't be reachable
            // from safe code.
            if let Some(rem) = rem {
                *rem = u64::from(n.high() % d.low());
            }
            return u64::from(n.high() / d.low());
        }

        // d.high() != 0
        if n.low() == 0 {
            // K 0
            // ---
            // K 0

            if let Some(rem) = rem {
                *rem = U64 {
                    low: 0,
                    high: n.high() % d.high(),
                }[..];
            }
            return u64::from(n.high() / d.high());
        }

        // n.low() != 0
        // K K
        // ---
        // K 0

        if d.high().is_power_of_two() {
            if let Some(rem) = rem {
                *rem = U64 {
                    low: n.low(),
                    high: n.high() & (d.high() - 1),
                }[..];
            }

            return u64::from(n.high() >> d.high().trailing_zeros());
        }

        sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());

        // D > N
        if sr > u32_bits - 2 {
            if let Some(rem) = rem {
                *rem = n;
            }
            return 0;
        }

        sr = sr + 1;

        // 1 <= sr <= u32_bits - 1
        // q = n << (u64_bits - sr);
        q.low = 0;
        q.high = n.low() << (u32_bits - sr);
        // r = n >> sr
        r.high = n.high() >> sr;
        r.low = (n.high() << (u32_bits - sr)) | (n.low() >> sr);
    } else
    // d.low() != 0
    {
        if d.high() == 0 {
            // K X
            // ---
            // 0 K
            if d.low().is_power_of_two() {
                if let Some(rem) = rem {
                    *rem = u64::from(n.low() & (d.low() - 1));
                }

                if d.low() == 1 {
                    return n;
                } else {
                    let sr = d.low().trailing_zeros();
                    return U64 {
                        low: (n.high() << (u32_bits - sr)) | (n.low() >> sr),
                        high: n.high() >> sr,
                    }[..];
                };
            }

            sr = 1 + u32_bits + d.low().leading_zeros() - n.high().leading_zeros();

            // 2 <= sr <= u64_bits - 1
            // q = n << (u64_bits - sr)
            // r = n >> sr;
            if sr == u32_bits {
                q.low = 0;
                q.high = n.low();
                r.high = 0;
                r.low = n.high();
            } else if sr < u32_bits
            // 2 <= sr <= u32_bits - 1
            {
                q.low = 0;
                q.high = n.low() << (u32_bits - sr);
                r.high = n.high() >> sr;
                r.low = (n.high() << (u32_bits - sr)) | (n.low() >> sr);
            } else
            // u32_bits + 1 <= sr <= u64_bits - 1
            {
                q.low = n.low() << (u64_bits - sr);
                q.high = (n.high() << (u64_bits - sr)) | (n.low() >> (sr - u32_bits));
                r.high = 0;
                r.low = n.high() >> (sr - u32_bits);
            }

        } else
        // d.high() != 0
        {
            // K X
            // ---
            // K K

            sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());

            // D > N
            if sr > u32_bits - 1 {
                if let Some(rem) = rem {
                    *rem = n;
                    return 0;
                }
            }

            sr += 1;

            // 1 <= sr <= u32_bits
            // q = n << (u64_bits - sr)
            q.low = 0;
            if sr == u32_bits {
                q.high = n.low();
                r.high = 0;
                r.low = n.high();
            } else {
                q.high = n.low() << (u32_bits - sr);
                r.high = n.high() >> sr;
                r.low = (n.high() << (u32_bits - sr)) | (n.low() >> sr);
            }
        }
    }

    // Not a special case
    // q and r are initialized with
    // q = n << (u64_bits - sr)
    // r = n >> sr
    // 1 <= sr <= u64_bits - 1
    let mut carry = 0;

    for _ in 0..sr {
        // r:q = ((r:q) << 1) | carry
        r[..] = (r[..] << 1) | (q[..] >> 63);
        q[..] = (q[..] << 1) | carry as u64;

        // carry = 0
        // if r >= d {
        //     r -= d;
        //     carry = 1;
        // }

        let s = (d.wrapping_sub(r[..]).wrapping_sub(1)) as i64 >> (u64_bits - 1);
        carry = (s & 1) as u32;
        r[..] -= d & s as u64;
    }

    q[..] = (q[..] << 1) | carry as u64;
    if let Some(rem) = rem {
        *rem = r[..];
    }
    q[..]
}
<commit_msg>address second row of review<commit_after>use {Int, LargeInt, U64};

/// Returns `n / d`
#[no_mangle]
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
    let u32_bits = u32::bits() as u32;

    // Special cases
    if d == 0 {
        panic!("Division by zero");
    }

    if n == 0 {
        return 0;
    }

    let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros());

    // d > n
    if sr > u32_bits - 1 {
        return 0;
    }

    // d == 1
    if sr == u32_bits - 1 {
        return n;
    }

    sr = sr + 1;

    // 1 <= sr <= u32_bits - 1
    let mut q = n << (u32_bits - sr);
    let mut r = n >> sr;

    let mut carry = 0;
    for _ in 0..sr {
        // r:q = ((r:q) << 1) | carry
        r = (r << 1) | (q >> (u32_bits - 1));
        q = (q << 1) | carry;

        // carry = 0;
        // if r > d {
        //     r -= d;
        //     carry = 1;
        // }

        let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32_bits - 1);
        carry = (s & 1) as u32;
        r -= d & s as u32;
    }

    (q << 1) | carry
}

/// Returns `n / d` and sets `*rem = n % d`
#[no_mangle]
pub extern "C" fn __udivmodsi4(a: u32, b: u32, rem: Option<&mut u32>) -> u32 {
    let d = __udivsi3(a, b);
    if let Some(rem) = rem {
        *rem = a - (d * b);
    }
    return d;
}

/// Returns `n / d` and sets `*rem = n % d`
#[no_mangle]
pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
    let u32_bits = u32::bits() as u32;
    let u64_bits = u64::bits() as u32;

    // NOTE X is unknown, K != 0
    if n.high() == 0 {
        if d.high() == 0 {
            // 0 X
            // ---
            // 0 X

            if let Some(rem) = rem {
                *rem = u64::from(n.low() % d.low());
            }
            return u64::from(n.low() / d.low());
        } else
        // d.high() != 0
        {
            // 0 X
            // ---
            // K X

            if let Some(rem) = rem {
                *rem = u64::from(n.low());
            }
            return 0;
        };
    }

    let mut sr;
    let mut q = U64 { low: 0, high: 0 };
    let mut r = U64 { low: 0, high: 0 };

    // n.high() != 0
    if d.low() == 0 {
        if d.high() == 0 {
            // K X
            // ---
            // 0 0

            panic!("Division by zero");
        }

        // d.high() != 0
        if n.low() == 0 {
            // K 0
            // ---
            // K 0

            if let Some(rem) = rem {
                *rem = U64 {
                    low: 0,
                    high: n.high() % d.high(),
                }[..];
            }
            return u64::from(n.high() / d.high());
        }

        // n.low() != 0
        // K K
        // ---
        // K 0

        if d.high().is_power_of_two() {
            if let Some(rem) = rem {
                *rem = U64 {
                    low: n.low(),
                    high: n.high() & (d.high() - 1),
                }[..];
            }

            return u64::from(n.high() >> d.high().trailing_zeros());
        }

        sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());

        // D > N
        if sr > u32_bits - 2 {
            if let Some(rem) = rem {
                *rem = n;
            }
            return 0;
        }

        sr = sr + 1;

        // 1 <= sr <= u32_bits - 1
        // q = n << (u64_bits - sr);
        q.low = 0;
        q.high = n.low() << (u32_bits - sr);
        // r = n >> sr
        r.high = n.high() >> sr;
        r.low = (n.high() << (u32_bits - sr)) | (n.low() >> sr);
    } else
    // d.low() != 0
    {
        if d.high() == 0 {
            // K X
            // ---
            // 0 K
            if d.low().is_power_of_two() {
                if let Some(rem) = rem {
                    *rem = u64::from(n.low() & (d.low() - 1));
                }

                if d.low() == 1 {
                    return n;
                } else {
                    let sr = d.low().trailing_zeros();
                    return U64 {
                        low: (n.high() << (u32_bits - sr)) | (n.low() >> sr),
                        high: n.high() >> sr,
                    }[..];
                };
            }

            sr = 1 + u32_bits + d.low().leading_zeros() - n.high().leading_zeros();

            // 2 <= sr <= u64_bits - 1
            // q = n << (u64_bits - sr)
            // r = n >> sr;
            if sr == u32_bits {
                q.low = 0;
                q.high = n.low();
                r.high = 0;
                r.low = n.high();
            } else if sr < u32_bits
            // 2 <= sr <= u32_bits - 1
            {
                q.low = 0;
                q.high = n.low() << (u32_bits - sr);
                r.high = n.high() >> sr;
                r.low = (n.high() << (u32_bits - sr)) | (n.low() >> sr);
            } else
            // u32_bits + 1 <= sr <= u64_bits - 1
            {
                q.low = n.low() << (u64_bits - sr);
                q.high = (n.high() << (u64_bits - sr)) | (n.low() >> (sr - u32_bits));
                r.high = 0;
                r.low = n.high() >> (sr - u32_bits);
            }

        } else
        // d.high() != 0
        {
            // K X
            // ---
            // K K

            sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());

            // D > N
            if sr > u32_bits - 1 {
                if let Some(rem) = rem {
                    *rem = n;
                    return 0;
                }
            }

            sr += 1;

            // 1 <= sr <= u32_bits
            // q = n << (u64_bits - sr)
            q.low = 0;
            if sr == u32_bits {
                q.high = n.low();
                r.high = 0;
                r.low = n.high();
            } else {
                q.high = n.low() << (u32_bits - sr);
                r.high = n.high() >> sr;
                r.low = (n.high() << (u32_bits - sr)) | (n.low() >> sr);
            }
        }
    }

    // Not a special case
    // q and r are initialized with
    // q = n << (u64_bits - sr)
    // r = n >> sr
    // 1 <= sr <= u64_bits - 1
    let mut carry = 0;

    for _ in 0..sr {
        // r:q = ((r:q) << 1) | carry
        r[..] = (r[..] << 1) | (q[..] >> 63);
        q[..] = (q[..] << 1) | carry as u64;

        // carry = 0
        // if r >= d {
        //     r -= d;
        //     carry = 1;
        // }

        let s = (d.wrapping_sub(r[..]).wrapping_sub(1)) as i64 >> (u64_bits - 1);
        carry = (s & 1) as u32;
        r[..] -= d & s as u64;
    }

    q[..] = (q[..] << 1) | carry as u64;
    if let Some(rem) = rem {
        *rem = r[..];
    }
    q[..]
}
<|endoftext|>