<commit_before>#![allow(unused_variables, dead_code)] // macros

/// Dbus macro for Layout code

use std::process::{Command, Stdio};

use ::ipc::utils::{parse_edge, parse_uuid, parse_direction, parse_axis, lock_tree_dbus};

use dbus::tree::MethodErr;

use ::layout::{Layout, commands as layout_cmd};
use rustwlc::{ResizeEdge, Point};

dbus_interface! {
    path: "/org/way_cooler/Layout";
    name: "org.way_cooler.Layout";

    fn ActiveContainerId() -> container_id: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        match tree.active_id() {
            Some(id) => Ok(id.to_string()),
            None => Ok("".to_string())
        }
    }

    // TODO Make this optional, and actually do something with it!
    fn ToggleFloat(container_id: String) -> success: DBusResult<bool> {
        let maybe_uuid = try!(parse_uuid("container_id", &container_id));
        match maybe_uuid {
            Some(uuid) => {
                let mut tree = try!(lock_tree_dbus());
                tree.toggle_float()
                    .and(Ok(true))
                    .map_err(|err| {
                        MethodErr::failed(&format!("{:?}", err))
                    })
            },
            None => {
                layout_cmd::toggle_float();
                Ok(true)
            }
        }
    }

    fn MoveContainer(container_id: String, direction: String) -> success: DBusResult<bool> {
        let target_uuid = try!(parse_uuid("container_id", &container_id));
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_active(target_uuid, direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    // TODO Rename ChangeContainerLayout
    fn SplitContainer(container_id: String, split_axis: String) -> success: DBusResult<bool> {
        let uuid = try!(parse_uuid("container_id", &container_id));
        let axis = try!(parse_axis("split_direction", split_axis.as_str()));
        // TODO Tree commands need to have these defined on the Tree,
        // for now this is _ok_, but we are swallowing an potential Tree lock error here.
        match axis {
            Layout::Horizontal => layout_cmd::split_horizontal(),
            Layout::Vertical => layout_cmd::split_vertical(),
            Layout::Tabbed => layout_cmd::tile_tabbed(),
            Layout::Stacked => layout_cmd::tile_stacked()
        }
        Ok(true)
    }

    fn ToggleCardinalTiling(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.toggle_cardinal_tiling(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SetActiveLayout(layout: String) -> success: DBusResult<bool> {
        let mut tree = lock_tree_dbus()?;
        let layout = parse_axis("layout", layout.as_str())?;
        tree.set_active_layout(layout)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SwitchWorkspace(w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        tree.switch_to_workspace(w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SpawnProgram(prog_name: String) -> pid: DBusResult<u32> {
        Command::new(prog_name)
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .spawn()
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
            .map(|child| child.id())
    }

    fn CloseView(view_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("view_id", &view_id))
            .or_else(|| tree.active_id())
            .ok_or(MethodErr::failed(&"No active container")));
        tree.remove_view_by_id(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Focus(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));

        tree.focus(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn ToggleFloatingFocus() -> success: DBusResult<bool> {
        let mut tree = lock_tree_dbus()?;
        tree.toggle_floating_focus()
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn FocusDir(direction: String) -> success: DBusResult<bool> {
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_focus(direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SendToWorkspace(container_id: String, w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.send_to_workspace(uuid, w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    // TODO Remove
    fn Debug() -> success: DBusResult<String> {
        Ok(format!("{}", layout_cmd::tree_as_json()))
    }

    fn ContainerInActiveWorkspace(container_id: String) -> success: DBusResult<bool> {
        let tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.container_in_active_workspace(uuid)
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    // TODO Rename to Fullscreen
    fn FullScreen(container_id: String, toggle: bool) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.set_fullscreen(uuid, toggle)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SetPointerPos(x: i32, y: i32) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let point = Point { x: x, y: y};
        tree.set_pointer_pos(point)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    // TODO Remove
    fn GrabAtCorner(container_id: String, dir: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        let mut edge = ResizeEdge::empty();
        for word in dir.split(',') {
            edge |= try!(parse_edge(word))
        }
        tree.grab_at_corner(uuid, edge)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn ActiveWorkspace() -> name: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        tree.active_workspace()
            .map(|container| container.name())
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn LockScreen() -> success: DBusResult<bool> {
        use ::modes::spawn_lock_screen;
        spawn_lock_screen();
        Ok(true)
    }
}
<commit_msg>try! -> ? in SendToWorkspace in D-Bus interface<commit_after>#![allow(unused_variables, dead_code)] // macros

/// Dbus macro for Layout code

use std::process::{Command, Stdio};

use ::ipc::utils::{parse_edge, parse_uuid, parse_direction, parse_axis, lock_tree_dbus};

use dbus::tree::MethodErr;

use ::layout::{Layout, commands as layout_cmd};
use rustwlc::{ResizeEdge, Point};

dbus_interface! {
    path: "/org/way_cooler/Layout";
    name: "org.way_cooler.Layout";

    fn ActiveContainerId() -> container_id: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        match tree.active_id() {
            Some(id) => Ok(id.to_string()),
            None => Ok("".to_string())
        }
    }

    // TODO Make this optional, and actually do something with it!
    fn ToggleFloat(container_id: String) -> success: DBusResult<bool> {
        let maybe_uuid = try!(parse_uuid("container_id", &container_id));
        match maybe_uuid {
            Some(uuid) => {
                let mut tree = try!(lock_tree_dbus());
                tree.toggle_float()
                    .and(Ok(true))
                    .map_err(|err| {
                        MethodErr::failed(&format!("{:?}", err))
                    })
            },
            None => {
                layout_cmd::toggle_float();
                Ok(true)
            }
        }
    }

    fn MoveContainer(container_id: String, direction: String) -> success: DBusResult<bool> {
        let target_uuid = try!(parse_uuid("container_id", &container_id));
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_active(target_uuid, direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    // TODO Rename ChangeContainerLayout
    fn SplitContainer(container_id: String, split_axis: String) -> success: DBusResult<bool> {
        let uuid = try!(parse_uuid("container_id", &container_id));
        let axis = try!(parse_axis("split_direction", split_axis.as_str()));
        // TODO Tree commands need to have these defined on the Tree,
        // for now this is _ok_, but we are swallowing an potential Tree lock error here.
        match axis {
            Layout::Horizontal => layout_cmd::split_horizontal(),
            Layout::Vertical => layout_cmd::split_vertical(),
            Layout::Tabbed => layout_cmd::tile_tabbed(),
            Layout::Stacked => layout_cmd::tile_stacked()
        }
        Ok(true)
    }

    fn ToggleCardinalTiling(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.toggle_cardinal_tiling(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SetActiveLayout(layout: String) -> success: DBusResult<bool> {
        let mut tree = lock_tree_dbus()?;
        let layout = parse_axis("layout", layout.as_str())?;
        tree.set_active_layout(layout)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SwitchWorkspace(w_name: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        tree.switch_to_workspace(w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SpawnProgram(prog_name: String) -> pid: DBusResult<u32> {
        Command::new(prog_name)
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .spawn()
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
            .map(|child| child.id())
    }

    fn CloseView(view_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("view_id", &view_id))
            .or_else(|| tree.active_id())
            .ok_or(MethodErr::failed(&"No active container")));
        tree.remove_view_by_id(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn Focus(container_id: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));

        tree.focus(uuid)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn ToggleFloatingFocus() -> success: DBusResult<bool> {
        let mut tree = lock_tree_dbus()?;
        tree.toggle_floating_focus()
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn FocusDir(direction: String) -> success: DBusResult<bool> {
        let direction = try!(parse_direction("direction", direction.as_str()));
        let mut tree = try!(lock_tree_dbus());
        tree.move_focus(direction)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SendToWorkspace(container_id: String, w_name: String) -> success: DBusResult<bool> {
        let mut tree = lock_tree_dbus()?;
        let uuid = parse_uuid("container_id", &container_id)?
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container"))?;
        tree.send_to_workspace(uuid, w_name.as_str())
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    // TODO Remove
    fn Debug() -> success: DBusResult<String> {
        Ok(format!("{}", layout_cmd::tree_as_json()))
    }

    fn ContainerInActiveWorkspace(container_id: String) -> success: DBusResult<bool> {
        let tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.container_in_active_workspace(uuid)
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    // TODO Rename to Fullscreen
    fn FullScreen(container_id: String, toggle: bool) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        tree.set_fullscreen(uuid, toggle)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn SetPointerPos(x: i32, y: i32) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let point = Point { x: x, y: y};
        tree.set_pointer_pos(point)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    // TODO Remove
    fn GrabAtCorner(container_id: String, dir: String) -> success: DBusResult<bool> {
        let mut tree = try!(lock_tree_dbus());
        let uuid = try!(try!(parse_uuid("container_id", &container_id))
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container")));
        let mut edge = ResizeEdge::empty();
        for word in dir.split(',') {
            edge |= try!(parse_edge(word))
        }
        tree.grab_at_corner(uuid, edge)
            .and(Ok(true))
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn ActiveWorkspace() -> name: DBusResult<String> {
        let tree = try!(lock_tree_dbus());
        tree.active_workspace()
            .map(|container| container.name())
            .map_err(|err| MethodErr::failed(&format!("{:?}", err)))
    }

    fn LockScreen() -> success: DBusResult<bool> {
        use ::modes::spawn_lock_screen;
        spawn_lock_screen();
        Ok(true)
    }
}
<|endoftext|>


<commit_before>// const _GRAMMAR: &'static str = include_str!("grammar.pest");

#[derive(Parser)]
#[grammar = "grammar.pest"]
pub struct HandlebarsParser;

#[cfg(test)]
mod test {
    use super::{HandlebarsParser, Rule};
    use pest::Parser;

    macro_rules! assert_rule {
        ($rule:expr, $in:expr) => {
            assert_eq!(
                HandlebarsParser::parse($rule, $in)
                    .unwrap()
                    .last()
                    .unwrap()
                    .as_span()
                    .end(),
                $in.len()
            );
        };
    }

    macro_rules! assert_not_rule {
        ($rule:expr, $in:expr) => {
            assert!(
                HandlebarsParser::parse($rule, $in).is_err()
                    || HandlebarsParser::parse($rule, $in)
                        .unwrap()
                        .last()
                        .unwrap()
                        .as_span()
                        .end()
                        != $in.len()
            );
        };
    }

    macro_rules! assert_rule_match {
        ($rule:expr, $in:expr) => {
            assert!(HandlebarsParser::parse($rule, $in).is_ok());
        };
    }

    #[test]
    fn test_raw_text() {
        let s = vec![
            "
 helloworld
    ",
            r"hello\{{world}}",
            r"hello\{{#if world}}nice\{{/if}}",
            r"hello \{{{{raw}}}}hello\{{{{/raw}}}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::raw_text, i);
        }

        let s_not_escape = vec![r"\\{{hello}}"];
        for i in s_not_escape.iter() {
            assert_not_rule!(Rule::raw_text, i);
        }
    }

    #[test]
    fn test_raw_block_text() {
        let s = "
 {{hello}}
";
        assert_rule!(Rule::raw_block_text, s);
    }

    #[test]
    fn test_reference() {
        let s = vec![
            "a",
            "abc",
            "../a",
            "a.b",
            "@abc",
            "a.[abc]",
            "aBc.[abc]",
            "abc.[0].[nice]",
            "some-name",
            "this.[0].ok",
        ];
        for i in s.iter() {
            assert_rule!(Rule::reference, i);
        }
    }

    #[test]
    fn test_name() {
        let s = vec!["if", "(abc)"];
        for i in s.iter() {
            assert_rule!(Rule::name, i);
        }
    }

    #[test]
    fn test_param() {
        let s = vec!["hello", "\"json literal\""];
        for i in s.iter() {
            assert_rule!(Rule::param, i);
        }
    }

    #[test]
    fn test_hash() {
        let s = vec![
            "hello=world",
            "hello=\"world\"",
            "hello=(world)",
            "hello=(world 0)",
        ];
        for i in s.iter() {
            assert_rule!(Rule::hash, i);
        }
    }

    #[test]
    fn test_json_literal() {
        let s = vec![
            "\"json string\"",
            "\"quot: \\\"\"",
            "'json string'",
            "'quot: \\''",
            "[]",
            "[\"hello\"]",
            "[1,2,3,4,true]",
            "{\"hello\": \"world\"}",
            "{}",
            "{\"a\":1, \"b\":2 }",
        ];
        for i in s.iter() {
            assert_rule!(Rule::literal, i);
        }
    }

    #[test]
    fn test_comment() {
        let s = vec!["{{!-- <hello {{ a-b c-d}} {{d-c}} ok --}}",
                 "{{!--

{{this.title}}

                --}}"];
        for i in s.iter() {
            assert_rule!(Rule::hbs_comment, i);
        }
        let s2 = vec!["{{! hello }}", "{{! test me }}"];
        for i in s2.iter() {
            assert_rule!(Rule::hbs_comment_compact, i);
        }
    }

    #[test]
    fn test_subexpression() {
        let s = vec!["(sub)", "(sub 0)", "(sub a=1)"];
        for i in s.iter() {
            assert_rule!(Rule::subexpression, i);
        }
    }

    #[test]
    fn test_expression() {
        let s = vec![
            "{{exp}}",
            "{{(exp)}}",
            "{{../exp}}",
            "{{exp 1}}",
            "{{exp \"literal\"}}",
            "{{exp \"literal with space\"}}",
            "{{exp ref}}",
            "{{exp (sub)}}",
            "{{exp (sub 123)}}",
            "{{exp []}}",
            "{{exp {}}}",
            "{{exp key=1}}",
            "{{exp key=ref}}",
            "{{exp key=(sub)}}",
            "{{exp key=(sub 0)}}",
            "{{exp key=(sub 0 key=1)}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::expression, i);
        }
    }

    #[test]
    fn test_identifier_with_dash() {
        let s = vec!["{{exp-foo}}"];
        for i in s.iter() {
            assert_rule!(Rule::expression, i);
        }
    }

    #[test]
    fn test_html_expression() {
        let s = vec!["{{{html}}}", "{{{(html)}}}", "{{{(html)}}}", "{{$html}}"];
        for i in s.iter() {
            assert_rule!(Rule::html_expression, i);
        }
    }

    #[test]
    fn test_helper_start() {
        let s = vec![
            "{{#if hello}}",
            "{{#if (hello)}}",
            "{{#if hello=world}}",
            "{{#if hello hello=world}}",
            "{{#if []}}",
            "{{#if {}}}",
            "{{#if}}",
            "{{~#if hello~}}",
            "{{#each people as |person|}}",
            "{{#each-obj obj as |val key|}}",
            "{{#each assets}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::helper_block_start, i);
        }
    }

    #[test]
    fn test_helper_end() {
        let s = vec!["{{/if}}", "{{~/if}}", "{{~/if ~}}", "{{/if   ~}}"];
        for i in s.iter() {
            assert_rule!(Rule::helper_block_end, i);
        }
    }

    #[test]
    fn test_helper_block() {
        let s = vec![
            "{{#if hello}}hello{{/if}}",
            "{{#if true}}hello{{/if}}",
            "{{#if nice ok=1}}hello{{/if}}",
            "{{#if}}hello{{else}}world{{/if}}",
            "{{#if}}hello{{^}}world{{/if}}",
            "{{#if}}{{#if}}hello{{/if}}{{/if}}",
            "{{#if}}hello{{~else}}world{{/if}}",
            "{{#if}}hello{{else~}}world{{/if}}",
            "{{#if}}hello{{~^~}}world{{/if}}",
            "{{#if}}{{/if}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::helper_block, i);
        }
    }

    #[test]
    fn test_raw_block() {
        let s = vec![
            "{{{{if hello}}}}good {{hello}}{{{{/if}}}}",
            "{{{{if hello}}}}{{#if nice}}{{/if}}{{{{/if}}}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::raw_block, i);
        }
    }

    #[test]
    fn test_block_param() {
        let s = vec!["as |person|", "as |val key|"];
        for i in s.iter() {
            assert_rule!(Rule::block_param, i);
        }
    }

    #[test]
    fn test_path() {
        let s = vec![
            "a",
            "a.b.c.d",
            "a.[0].[1].[2]",
            "a.[abc]",
            "a/v/c.d.s",
            "a.[0]/b/c/d",
            "a.[bb c]/b/c/d",
            "a.[0].[#hello]",
            "../a/b.[0].[1]",
            "this.[0]/[1]/this/a",
            "./this_name",
            "./goo/[/bar]",
            "a.[你好]",
            "a.[10].[#comment]",
            "a.[]", // empty key
            "./[/foo]",
            "[foo]",
            "@root/a/b",
        ];
        for i in s.iter() {
            assert_rule_match!(Rule::path, i);
        }
    }

    #[test]
    fn test_decorator_expression() {
        let s = vec!["{{* ssh}}", "{{~* ssh}}"];
        for i in s.iter() {
            assert_rule!(Rule::decorator_expression, i);
        }
    }

    #[test]
    fn test_decorator_block() {
        let s = vec![
            "{{#* inline}}something{{/inline}}",
            "{{~#* inline}}hello{{/inline}}",
            "{{#* inline \"partialname\"}}something{{/inline}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::decorator_block, i);
        }
    }

    #[test]
    fn test_partial_expression() {
        let s = vec![
            "{{> hello}}",
            "{{> (hello)}}",
            "{{~> hello a}}",
            "{{> hello a=1}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::partial_expression, i);
        }
    }

    #[test]
    fn test_partial_block() {
        let s = vec!["{{#> hello}}nice{{/hello}}"];
        for i in s.iter() {
            assert_rule!(Rule::partial_block, i);
        }
    }
}
<commit_msg>(test) add test for property name starts with dollar<commit_after>// const _GRAMMAR: &'static str = include_str!("grammar.pest");

#[derive(Parser)]
#[grammar = "grammar.pest"]
pub struct HandlebarsParser;

#[cfg(test)]
mod test {
    use super::{HandlebarsParser, Rule};
    use pest::Parser;

    macro_rules! assert_rule {
        ($rule:expr, $in:expr) => {
            assert_eq!(
                HandlebarsParser::parse($rule, $in)
                    .unwrap()
                    .last()
                    .unwrap()
                    .as_span()
                    .end(),
                $in.len()
            );
        };
    }

    macro_rules! assert_not_rule {
        ($rule:expr, $in:expr) => {
            assert!(
                HandlebarsParser::parse($rule, $in).is_err()
                    || HandlebarsParser::parse($rule, $in)
                        .unwrap()
                        .last()
                        .unwrap()
                        .as_span()
                        .end()
                        != $in.len()
            );
        };
    }

    macro_rules! assert_rule_match {
        ($rule:expr, $in:expr) => {
            assert!(HandlebarsParser::parse($rule, $in).is_ok());
        };
    }

    #[test]
    fn test_raw_text() {
        let s = vec![
            "
 helloworld
    ",
            r"hello\{{world}}",
            r"hello\{{#if world}}nice\{{/if}}",
            r"hello \{{{{raw}}}}hello\{{{{/raw}}}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::raw_text, i);
        }

        let s_not_escape = vec![r"\\{{hello}}"];
        for i in s_not_escape.iter() {
            assert_not_rule!(Rule::raw_text, i);
        }
    }

    #[test]
    fn test_raw_block_text() {
        let s = "
 {{hello}}
";
        assert_rule!(Rule::raw_block_text, s);
    }

    #[test]
    fn test_reference() {
        let s = vec![
            "a",
            "abc",
            "../a",
            "a.b",
            "@abc",
            "a.[abc]",
            "aBc.[abc]",
            "abc.[0].[nice]",
            "some-name",
            "this.[0].ok",
            "[$id]",
        ];
        for i in s.iter() {
            assert_rule!(Rule::reference, i);
        }
    }

    #[test]
    fn test_name() {
        let s = vec!["if", "(abc)"];
        for i in s.iter() {
            assert_rule!(Rule::name, i);
        }
    }

    #[test]
    fn test_param() {
        let s = vec!["hello", "\"json literal\""];
        for i in s.iter() {
            assert_rule!(Rule::param, i);
        }
    }

    #[test]
    fn test_hash() {
        let s = vec![
            "hello=world",
            "hello=\"world\"",
            "hello=(world)",
            "hello=(world 0)",
        ];
        for i in s.iter() {
            assert_rule!(Rule::hash, i);
        }
    }

    #[test]
    fn test_json_literal() {
        let s = vec![
            "\"json string\"",
            "\"quot: \\\"\"",
            "'json string'",
            "'quot: \\''",
            "[]",
            "[\"hello\"]",
            "[1,2,3,4,true]",
            "{\"hello\": \"world\"}",
            "{}",
            "{\"a\":1, \"b\":2 }",
        ];
        for i in s.iter() {
            assert_rule!(Rule::literal, i);
        }
    }

    #[test]
    fn test_comment() {
        let s = vec!["{{!-- <hello {{ a-b c-d}} {{d-c}} ok --}}",
                 "{{!--

{{this.title}}

                --}}"];
        for i in s.iter() {
            assert_rule!(Rule::hbs_comment, i);
        }
        let s2 = vec!["{{! hello }}", "{{! test me }}"];
        for i in s2.iter() {
            assert_rule!(Rule::hbs_comment_compact, i);
        }
    }

    #[test]
    fn test_subexpression() {
        let s = vec!["(sub)", "(sub 0)", "(sub a=1)"];
        for i in s.iter() {
            assert_rule!(Rule::subexpression, i);
        }
    }

    #[test]
    fn test_expression() {
        let s = vec![
            "{{exp}}",
            "{{(exp)}}",
            "{{../exp}}",
            "{{exp 1}}",
            "{{exp \"literal\"}}",
            "{{exp \"literal with space\"}}",
            "{{exp ref}}",
            "{{exp (sub)}}",
            "{{exp (sub 123)}}",
            "{{exp []}}",
            "{{exp {}}}",
            "{{exp key=1}}",
            "{{exp key=ref}}",
            "{{exp key=(sub)}}",
            "{{exp key=(sub 0)}}",
            "{{exp key=(sub 0 key=1)}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::expression, i);
        }
    }

    #[test]
    fn test_identifier_with_dash() {
        let s = vec!["{{exp-foo}}"];
        for i in s.iter() {
            assert_rule!(Rule::expression, i);
        }
    }

    #[test]
    fn test_html_expression() {
        let s = vec!["{{{html}}}", "{{{(html)}}}", "{{{(html)}}}", "{{$html}}"];
        for i in s.iter() {
            assert_rule!(Rule::html_expression, i);
        }
    }

    #[test]
    fn test_helper_start() {
        let s = vec![
            "{{#if hello}}",
            "{{#if (hello)}}",
            "{{#if hello=world}}",
            "{{#if hello hello=world}}",
            "{{#if []}}",
            "{{#if {}}}",
            "{{#if}}",
            "{{~#if hello~}}",
            "{{#each people as |person|}}",
            "{{#each-obj obj as |val key|}}",
            "{{#each assets}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::helper_block_start, i);
        }
    }

    #[test]
    fn test_helper_end() {
        let s = vec!["{{/if}}", "{{~/if}}", "{{~/if ~}}", "{{/if   ~}}"];
        for i in s.iter() {
            assert_rule!(Rule::helper_block_end, i);
        }
    }

    #[test]
    fn test_helper_block() {
        let s = vec![
            "{{#if hello}}hello{{/if}}",
            "{{#if true}}hello{{/if}}",
            "{{#if nice ok=1}}hello{{/if}}",
            "{{#if}}hello{{else}}world{{/if}}",
            "{{#if}}hello{{^}}world{{/if}}",
            "{{#if}}{{#if}}hello{{/if}}{{/if}}",
            "{{#if}}hello{{~else}}world{{/if}}",
            "{{#if}}hello{{else~}}world{{/if}}",
            "{{#if}}hello{{~^~}}world{{/if}}",
            "{{#if}}{{/if}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::helper_block, i);
        }
    }

    #[test]
    fn test_raw_block() {
        let s = vec![
            "{{{{if hello}}}}good {{hello}}{{{{/if}}}}",
            "{{{{if hello}}}}{{#if nice}}{{/if}}{{{{/if}}}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::raw_block, i);
        }
    }

    #[test]
    fn test_block_param() {
        let s = vec!["as |person|", "as |val key|"];
        for i in s.iter() {
            assert_rule!(Rule::block_param, i);
        }
    }

    #[test]
    fn test_path() {
        let s = vec![
            "a",
            "a.b.c.d",
            "a.[0].[1].[2]",
            "a.[abc]",
            "a/v/c.d.s",
            "a.[0]/b/c/d",
            "a.[bb c]/b/c/d",
            "a.[0].[#hello]",
            "../a/b.[0].[1]",
            "this.[0]/[1]/this/a",
            "./this_name",
            "./goo/[/bar]",
            "a.[你好]",
            "a.[10].[#comment]",
            "a.[]", // empty key
            "./[/foo]",
            "[foo]",
            "@root/a/b",
        ];
        for i in s.iter() {
            assert_rule_match!(Rule::path, i);
        }
    }

    #[test]
    fn test_decorator_expression() {
        let s = vec!["{{* ssh}}", "{{~* ssh}}"];
        for i in s.iter() {
            assert_rule!(Rule::decorator_expression, i);
        }
    }

    #[test]
    fn test_decorator_block() {
        let s = vec![
            "{{#* inline}}something{{/inline}}",
            "{{~#* inline}}hello{{/inline}}",
            "{{#* inline \"partialname\"}}something{{/inline}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::decorator_block, i);
        }
    }

    #[test]
    fn test_partial_expression() {
        let s = vec![
            "{{> hello}}",
            "{{> (hello)}}",
            "{{~> hello a}}",
            "{{> hello a=1}}",
        ];
        for i in s.iter() {
            assert_rule!(Rule::partial_expression, i);
        }
    }

    #[test]
    fn test_partial_block() {
        let s = vec!["{{#> hello}}nice{{/hello}}"];
        for i in s.iter() {
            assert_rule!(Rule::partial_block, i);
        }
    }
}
<|endoftext|>


<commit_before>/// DrawObjectList interns shaders, brushes, and scripts, returning references that can be stored
/// in the event queue.
/// TODO: scripts
/// TODO: serialization
/// TODO: further backing store, caching init objs by sha1 or so
/// TODO: free shaders + textures on gl pause
/// TODO: cleanup, deduplication
///
/// more importantly, switch to a map and return keys, rather than using indices

use core::prelude::*;
use core::mem;
use collections::vec::Vec;
use collections::string::String;
use collections::{Map, MutableMap, MutableSeq};
use collections::hash::Hash;
use collections::hash::sip::SipHasher;
use std::collections::HashMap;
use copyshader::CopyShader;
use gltexture::{PixelFormat, Texture};
use pointshader::PointShader;
use glcommon::Shader;
use luascript::LuaScript;
use arena::TypedArena;
use glcommon::GLResult;

/// Holds GL objects that can be inited using the given keys.
/// The list is to avoid having to pass those keys around, and serialize more easily.
/// The arena doesn't relocate its entries, so we can pass back longer-lived pointers,
/// even if it needs some encouragement to do so.
/// There ought to be a better way.
pub struct DrawObjectList<'a, T: 'a, Init: Eq+Hash> {
    map: HashMap<Init, DrawObjectIndex<T>, SipHasher>,
    list: Vec<&'a T>,
    arena: TypedArena<T>,
}

#[deriving(Show)]
pub struct DrawObjectIndex<T>(i32);

impl<T> DrawObjectIndex<T> {
    pub fn error() -> DrawObjectIndex<T> {
        unsafe { mem::transmute(-1i) }
    }
}

pub type ShaderInitValues = (Option<String>, Option<String>);
pub type BrushInitValues = (PixelFormat, (i32, i32), Vec<u8>);
pub type LuaInitValues = Option<String>;
pub type PointShaderIndex = DrawObjectIndex<PointShader>;
pub type CopyShaderIndex = DrawObjectIndex<CopyShader>;
pub type BrushIndex = DrawObjectIndex<Texture>;
pub type LuaIndex = DrawObjectIndex<LuaScript>;

pub trait InitFromCache<Init> {
    fn init(&Init) -> Self;
}
pub trait MaybeInitFromCache<Init: Eq+Hash> {
    fn maybe_init(&Init) -> GLResult<Self>;
}
trait ToOwnedInit<Init> {
    fn to_owned(&Self) -> Init;
}

// this and the two shader impls were originally a single
// impl<T: Shader> InitFromCache<ShaderInitValues> for Option<T>
// but that counts as the impl for all of Option, not just Option<Shader>
fn _init_copy_shader<T: Shader>(value: &(Option<String>, Option<String>)) -> GLResult<T> {
    let &(ref frag, ref vert) = value;
    let (vertopt, fragopt) = (vert.as_ref().map(|x|x.as_slice()), frag.as_ref().map(|x|x.as_slice()));
    Shader::new(fragopt, vertopt)
}
impl MaybeInitFromCache<ShaderInitValues> for CopyShader {
    fn maybe_init(value: &(Option<String>, Option<String>)) -> GLResult<CopyShader> { _init_copy_shader(value) }
}
impl MaybeInitFromCache<ShaderInitValues> for PointShader {
    fn maybe_init(value: &(Option<String>, Option<String>)) -> GLResult<PointShader> { _init_copy_shader(value) }
}
// TODO: use this as the impl for all InitFromCache<Init>
impl MaybeInitFromCache<BrushInitValues> for Texture {
    fn maybe_init(value: &BrushInitValues) -> GLResult<Texture> {
        Ok(InitFromCache::init(value))
    }
}

impl InitFromCache<BrushInitValues> for Texture {
    fn init(value: &BrushInitValues) -> Texture {
        let &(format, (w, h), ref pixels) = value;
        Texture::with_image(w, h, Some(pixels.as_slice()), format)
    }
}

impl MaybeInitFromCache<LuaInitValues> for LuaScript {
    fn maybe_init(value: &Option<String>) -> GLResult<LuaScript> {
        LuaScript::new(value.as_ref().map(|x|x.as_slice()))
    }
}

impl<'a, T: MaybeInitFromCache<Init>, Init: Hash+Eq> DrawObjectList<'a, T, Init> {
    pub fn new() -> DrawObjectList<'a, T, Init> {
        // the default hasher is keyed off of the task-local rng,
        // which would blow up since we don't have a task
        //let mut rng = rand::weak_rng();
        //let hasher = SipHasher::new_with_keys(rng.next_u64(), rng.next_u64());
        // FIXME weak_rng also blows up? can it not find /dev/urandom?
        let hasher = SipHasher::new_with_keys(0, 0);
        let map = HashMap::with_hasher(hasher);
        DrawObjectList {
            map: map,
            list: Vec::new(),
            arena: TypedArena::new(),
        }
    }

    // TODO: avoid allocations just to see if the key is in the map
    pub fn push_object(&mut self, init: Init) -> GLResult<DrawObjectIndex<T>> {
        // Can't use map.entry() here as it consumes the key
        if self.map.contains_key(&init) {
            Ok(*self.map.find(&init).unwrap())
        } else {
            let inited = try!(MaybeInitFromCache::maybe_init(&init));
            // ptr's lifetime is limited to &self's, which is fair but not very useful.
            // smart ptrs involve individual allocs but are probably better
            let ptr = self.arena.alloc(inited);
            unsafe {
                self.list.push(mem::transmute(ptr));
            }
            let index = self.list.len() - 1;
            let objindex = DrawObjectIndex(index as i32);
            self.map.insert(init, objindex);
            Ok(objindex)
        }
    }

    pub fn get_object(&self, i: DrawObjectIndex<T>) -> &'a T {
        let DrawObjectIndex(idx) = i;
        self.list[idx as uint]
    }
}

impl<'a, T: InitFromCache<Init>+MaybeInitFromCache<Init>, Init: Hash+Eq> DrawObjectList<'a, T, Init> {
    pub fn safe_push_object(&mut self, init: Init) -> DrawObjectIndex<T> {
        self.push_object(init).unwrap()
    }
}

<commit_msg>try to update glstore<commit_after>/// DrawObjectList interns shaders, brushes, and scripts, returning references that can be stored
/// in the event queue.
/// TODO: scripts
/// TODO: serialization
/// TODO: further backing store, caching init objs by sha1 or so
/// TODO: free shaders + textures on gl pause
/// TODO: cleanup, deduplication
///
/// more importantly, switch to a map and return keys, rather than using indices

use core::prelude::*;
use core::mem;
use collections::vec::Vec;
use collections::string::String;
use collections::{Map, MutableMap, MutableSeq};
use collections::hash::Hash;
use collections::hash::sip::SipHasher;
use std::collections::HashMap;
use copyshader::CopyShader;
use gltexture::{PixelFormat, Texture};
use pointshader::PointShader;
use glcommon::Shader;
use luascript::LuaScript;
use arena::TypedArena;
use glcommon::GLResult;

/// Holds GL objects that can be inited using the given keys.
/// The list is to avoid having to pass those keys around, and serialize more easily.
/// The arena doesn't relocate its entries, so we can pass back longer-lived pointers,
/// even if it needs some encouragement to do so.
/// There ought to be a better way.
pub struct DrawObjectList<'a, T: 'a, Init: Eq+Hash> {
    map: HashMap<Init, DrawObjectIndex<T>, SipHasher>,
    list: Vec<&'a T>,
    arena: TypedArena<T>,
}

#[deriving(Show)]
pub struct DrawObjectIndex<T>(i32);

impl<T> DrawObjectIndex<T> {
    pub fn error() -> DrawObjectIndex<T> {
        unsafe { mem::transmute(-1i) }
    }
}

pub type ShaderInitValues = (Option<String>, Option<String>);
pub type BrushInitValues = (PixelFormat, (i32, i32), Vec<u8>);
pub type LuaInitValues = Option<String>;
pub type PointShaderIndex = DrawObjectIndex<PointShader>;
pub type CopyShaderIndex = DrawObjectIndex<CopyShader>;
pub type BrushIndex = DrawObjectIndex<Texture>;
pub type LuaIndex = DrawObjectIndex<LuaScript>;

pub trait InitFromCache<Init> {
    fn init(&Init) -> Self;
}
pub trait MaybeInitFromCache<Init: Eq+Hash> {
    fn maybe_init(&Init) -> GLResult<Self>;
}
trait ToOwnedInit<Init> {
    fn to_owned(&Self) -> Init;
}

// this and the two shader impls were originally a single
// impl<T: Shader> InitFromCache<ShaderInitValues> for Option<T>
// but that counts as the impl for all of Option, not just Option<Shader>
fn _init_copy_shader<T: Shader>(value: &(Option<String>, Option<String>)) -> GLResult<T> {
    let &(ref frag, ref vert) = value;
    let (vertopt, fragopt) = (vert.as_ref().map(|x|x.as_slice()), frag.as_ref().map(|x|x.as_slice()));
    Shader::new(fragopt, vertopt)
}
impl MaybeInitFromCache<ShaderInitValues> for CopyShader {
    fn maybe_init(value: &(Option<String>, Option<String>)) -> GLResult<CopyShader> { _init_copy_shader(value) }
}
impl MaybeInitFromCache<ShaderInitValues> for PointShader {
    fn maybe_init(value: &(Option<String>, Option<String>)) -> GLResult<PointShader> { _init_copy_shader(value) }
}
// TODO: use this as the impl for all InitFromCache<Init>
impl MaybeInitFromCache<BrushInitValues> for Texture {
    fn maybe_init(value: &BrushInitValues) -> GLResult<Texture> {
        Ok(InitFromCache::init(value))
    }
}

impl InitFromCache<BrushInitValues> for Texture {
    fn init(value: &BrushInitValues) -> Texture {
        let &(format, (w, h), ref pixels) = value;
        Texture::with_image(w, h, Some(pixels.as_slice()), format)
    }
}

impl MaybeInitFromCache<LuaInitValues> for LuaScript {
    fn maybe_init(value: &Option<String>) -> GLResult<LuaScript> {
        LuaScript::new(value.as_ref().map(|x|x.as_slice()))
    }
}

impl<'a, T: MaybeInitFromCache<Init>, Init: Hash+Eq> DrawObjectList<'a, T, Init> {
    pub fn new() -> DrawObjectList<'a, T, Init> {
        // the default hasher is keyed off of the task-local rng,
        // which would blow up since we don't have a task
        //let mut rng = rand::weak_rng();
        //let hasher = SipHasher::new_with_keys(rng.next_u64(), rng.next_u64());
        // FIXME weak_rng also blows up? can it not find /dev/urandom?
        let hasher = SipHasher::new_with_keys(0, 0);
        let map = HashMap::with_hasher(hasher);
        DrawObjectList {
            map: map,
            list: Vec::new(),
            arena: TypedArena::new(),
        }
    }

    pub fn push_object(&mut self, init: Init) -> GLResult<DrawObjectIndex<T>> {
        // Can't use map.entry() here as it consumes the key
        if self.map.contains_key(&init) {
            Ok(*self.map.find(&init).unwrap())
        } else {
            let inited = try!(MaybeInitFromCache::maybe_init(&init));
            // ptr's lifetime is limited to &self's, which is fair but not very useful.
            // smart ptrs involve individual allocs but are probably better
            let ptr = self.arena.alloc(inited);
            unsafe {
                self.list.push(mem::transmute(ptr));
            }
            let index = self.list.len() - 1;
            let objindex = DrawObjectIndex(index as i32);
            self.map.insert(init, objindex);
            Ok(objindex)
        }
    }

    pub fn get_object(&self, i: DrawObjectIndex<T>) -> &'a T {
        let DrawObjectIndex(idx) = i;
        self.list[idx as uint]
    }
}

impl<'a, T: InitFromCache<Init>+MaybeInitFromCache<Init>, Init: Hash+Eq> DrawObjectList<'a, T, Init> {
    pub fn safe_push_object(&mut self, init: Init) -> DrawObjectIndex<T> {
        self.push_object(init).unwrap()
    }
}

<|endoftext|>


<commit_before>use std::mem;

use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::mir;
use rustc::ty::{
    self,
    layout::{self, Align, Size, LayoutOf},
};

use rand::RngCore;

use crate::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Gets an instance for a path.
    fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
        let this = self.eval_context_ref();
        this.tcx
            .crates()
            .iter()
            .find(|&&krate| this.tcx.original_crate_name(krate).as_str() == path[0])
            .and_then(|krate| {
                let krate = DefId {
                    krate: *krate,
                    index: CRATE_DEF_INDEX,
                };
                let mut items = this.tcx.item_children(krate);
                let mut path_it = path.iter().skip(1).peekable();

                while let Some(segment) = path_it.next() {
                    for item in mem::replace(&mut items, Default::default()).iter() {
                        if item.ident.name.as_str() == *segment {
                            if path_it.peek().is_none() {
                                return Some(ty::Instance::mono(this.tcx.tcx, item.res.def_id()));
                            }

                            items = this.tcx.item_children(item.res.def_id());
                            break;
                        }
                    }
                }
                None
            })
            .ok_or_else(|| {
                let path = path.iter().map(|&s| s.to_owned()).collect();
                err_unsup!(PathNotFound(path)).into()
            })
    }

    /// Write a 0 of the appropriate size to `dest`.
    fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
        self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
    }

    /// Test if this immediate equals 0.
    fn is_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, bool> {
        let this = self.eval_context_ref();
        let null = Scalar::from_int(0, this.memory().pointer_size());
        this.ptr_eq(val, null)
    }

    /// Turn a Scalar into an Option<NonNullScalar>
    fn test_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, Option<Scalar<Tag>>> {
        let this = self.eval_context_ref();
        Ok(if this.is_null(val)? {
            None
        } else {
            Some(val)
        })
    }

    /// Get the `Place` for a local
    fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Tag>> {
        let this = self.eval_context_mut();
        let place = mir::Place { base: mir::PlaceBase::Local(local), projection: Box::new([]) };
        this.eval_place(&place)
    }

    /// Generate some random bytes, and write them to `dest`.
    fn gen_random(
        &mut self,
        ptr: Scalar<Tag>,
        len: usize,
    ) -> InterpResult<'tcx>  {
        // Some programs pass in a null pointer and a length of 0
        // to their platform's random-generation function (e.g. getrandom())
        // on Linux. For compatibility with these programs, we don't perform
        // any additional checks - it's okay if the pointer is invalid,
        // since we wouldn't actually be writing to it.
        if len == 0 {
            return Ok(());
        }
        let this = self.eval_context_mut();

        let ptr = this.memory().check_ptr_access(
            ptr,
            Size::from_bytes(len as u64),
            Align::from_bytes(1).unwrap()
        )?.expect("we already checked for size 0");

        let mut data = vec![0; len];

        if this.machine.communicate {
            // Fill the buffer using the host's rng.
            getrandom::getrandom(&mut data)
                .map_err(|err| err_unsup_format!("getrandom failed: {}", err))?;
        }
        else {
            let rng = this.memory_mut().extra.rng.get_mut();
            rng.fill_bytes(&mut data);
        }

        let tcx = &{this.tcx.tcx};
        this.memory_mut().get_mut(ptr.alloc_id)?.write_bytes(tcx, ptr, &data)
    }

    /// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
    /// will be true if this is frozen, false if this is in an `UnsafeCell`.
    fn visit_freeze_sensitive(
        &self,
        place: MPlaceTy<'tcx, Tag>,
        size: Size,
        mut action: impl FnMut(Pointer<Tag>, Size, bool) -> InterpResult<'tcx>,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_ref();
        trace!("visit_frozen(place={:?}, size={:?})", *place, size);
        debug_assert_eq!(size,
            this.size_and_align_of_mplace(place)?
            .map(|(size, _)| size)
            .unwrap_or_else(|| place.layout.size)
        );
        // Store how far we proceeded into the place so far. Everything to the left of
        // this offset has already been handled, in the sense that the frozen parts
        // have had `action` called on them.
        let mut end_ptr = place.ptr.assert_ptr();
        // Called when we detected an `UnsafeCell` at the given offset and size.
        // Calls `action` and advances `end_ptr`.
        let mut unsafe_cell_action = |unsafe_cell_ptr: Scalar<Tag>, unsafe_cell_size: Size| {
            let unsafe_cell_ptr = unsafe_cell_ptr.assert_ptr();
            debug_assert_eq!(unsafe_cell_ptr.alloc_id, end_ptr.alloc_id);
            debug_assert_eq!(unsafe_cell_ptr.tag, end_ptr.tag);
            // We assume that we are given the fields in increasing offset order,
            // and nothing else changes.
            let unsafe_cell_offset = unsafe_cell_ptr.offset;
            let end_offset = end_ptr.offset;
            assert!(unsafe_cell_offset >= end_offset);
            let frozen_size = unsafe_cell_offset - end_offset;
            // Everything between the end_ptr and this `UnsafeCell` is frozen.
            if frozen_size != Size::ZERO {
                action(end_ptr, frozen_size, /*frozen*/true)?;
            }
            // This `UnsafeCell` is NOT frozen.
            if unsafe_cell_size != Size::ZERO {
                action(unsafe_cell_ptr, unsafe_cell_size, /*frozen*/false)?;
            }
            // Update end end_ptr.
            end_ptr = unsafe_cell_ptr.wrapping_offset(unsafe_cell_size, this);
            // Done
            Ok(())
        };
        // Run a visitor
        {
            let mut visitor = UnsafeCellVisitor {
                ecx: this,
                unsafe_cell_action: |place| {
                    trace!("unsafe_cell_action on {:?}", place.ptr);
                    // We need a size to go on.
                    let unsafe_cell_size = this.size_and_align_of_mplace(place)?
                        .map(|(size, _)| size)
                        // for extern types, just cover what we can
                        .unwrap_or_else(|| place.layout.size);
                    // Now handle this `UnsafeCell`, unless it is empty.
                    if unsafe_cell_size != Size::ZERO {
                        unsafe_cell_action(place.ptr, unsafe_cell_size)
                    } else {
                        Ok(())
                    }
                },
            };
            visitor.visit_value(place)?;
        }
        // The part between the end_ptr and the end of the place is also frozen.
        // So pretend there is a 0-sized `UnsafeCell` at the end.
        unsafe_cell_action(place.ptr.ptr_wrapping_offset(size, this), Size::ZERO)?;
        // Done!
        return Ok(());

        /// Visiting the memory covered by a `MemPlace`, being aware of
        /// whether we are inside an `UnsafeCell` or not.
        struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
            where F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            ecx: &'ecx MiriEvalContext<'mir, 'tcx>,
            unsafe_cell_action: F,
        }

        impl<'ecx, 'mir, 'tcx, F>
            ValueVisitor<'mir, 'tcx, Evaluator<'tcx>>
        for
            UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
        where
            F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            type V = MPlaceTy<'tcx, Tag>;

            #[inline(always)]
            fn ecx(&self) -> &MiriEvalContext<'mir, 'tcx> {
                &self.ecx
            }

            // Hook to detect `UnsafeCell`.
            fn visit_value(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty);
                let is_unsafe_cell = match v.layout.ty.kind {
                    ty::Adt(adt, _) => Some(adt.did) == self.ecx.tcx.lang_items().unsafe_cell_type(),
                    _ => false,
                };
                if is_unsafe_cell {
                    // We do not have to recurse further, this is an `UnsafeCell`.
                    (self.unsafe_cell_action)(v)
                } else if self.ecx.type_is_freeze(v.layout.ty) {
                    // This is `Freeze`, there cannot be an `UnsafeCell`
                    Ok(())
                } else {
                    // We want to not actually read from memory for this visit. So, before
                    // walking this value, we have to make sure it is not a
                    // `Variants::Multiple`.
                    match v.layout.variants {
                        layout::Variants::Multiple { .. } => {
                            // A multi-variant enum, or generator, or so.
                            // Treat this like a union: without reading from memory,
                            // we cannot determine the variant we are in. Reading from
                            // memory would be subject to Stacked Borrows rules, leading
                            // to all sorts of "funny" recursion.
                            // We only end up here if the type is *not* freeze, so we just call the
                            // `UnsafeCell` action.
                            (self.unsafe_cell_action)(v)
                        }
                        layout::Variants::Single { .. } => {
                            // Proceed further, try to find where exactly that `UnsafeCell`
                            // is hiding.
                            self.walk_value(v)
                        }
                    }
                }
            }

            // Make sure we visit aggregrates in increasing offset order.
            fn visit_aggregate(
                &mut self,
                place: MPlaceTy<'tcx, Tag>,
                fields: impl Iterator<Item=InterpResult<'tcx, MPlaceTy<'tcx, Tag>>>,
            ) -> InterpResult<'tcx> {
                match place.layout.fields {
                    layout::FieldPlacement::Array { .. } => {
                        // For the array layout, we know the iterator will yield sorted elements so
                        // we can avoid the allocation.
                        self.walk_aggregate(place, fields)
                    }
                    layout::FieldPlacement::Arbitrary { .. } => {
                        // Gather the subplaces and sort them before visiting.
                        let mut places = fields.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Tag>>>>()?;
                        places.sort_by_key(|place| place.ptr.assert_ptr().offset);
                        self.walk_aggregate(place, places.into_iter().map(Ok))
                    }
                    layout::FieldPlacement::Union { .. } => {
                        // Uh, what?
                        bug!("a union is not an aggregate we should ever visit")
                    }
                }
            }

            // We have to do *something* for unions.
            fn visit_union(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                // With unions, we fall back to whatever the type says, to hopefully be consistent
                // with LLVM IR.
                // FIXME: are we consistent, and is this really the behavior we want?
                let frozen = self.ecx.type_is_freeze(v.layout.ty);
                if frozen {
                    Ok(())
                } else {
                    (self.unsafe_cell_action)(v)
                }
            }

            // We should never get to a primitive, but always short-circuit somewhere above.
            fn visit_primitive(&mut self, _v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                bug!("we should always short-circuit before coming to a primitive")
            }
        }
    }

    /// Helper function to get a `libc` constant as a `Scalar`.
    fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
        self.eval_context_mut()
            .eval_path_scalar(&["libc", name])?
            .ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
            .not_undef()
    }

    /// Helper function to get a `libc` constant as an `i32`.
    fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
        self.eval_libc(name)?.to_i32()
    }

    fn write_c_ints(
        &mut self,
        ptr: &Pointer<Tag>,
        bits: &[i128],
        ty_names: &[&str],
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        let tcx = &{ this.tcx.tcx };

        let mut sizes = Vec::new();

        for name in ty_names {
            let ty = this.resolve_path(&["libc", name])?.ty(*tcx);
            sizes.push(this.layout_of(ty)?.size);
        }

        let allocation = this.memory_mut().get_mut(ptr.alloc_id)?;
        let mut offset = Size::from_bytes(0);

        for (value, size) in bits.iter().zip(sizes) {
            allocation.write_scalar(
                tcx,
                ptr.offset(offset, tcx)?,
                Scalar::from_int(*value, size).into(),
                size,
            )?;
            offset += size;
        }

        Ok(())
    }
}
<commit_msg>Throw error instead of panicking for unfittable bits<commit_after>use std::mem;

use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::mir;
use rustc::ty::{
    self,
    layout::{self, Align, LayoutOf, Size},
};

use rand::RngCore;

use crate::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Gets an instance for a path.
    fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
        let this = self.eval_context_ref();
        this.tcx
            .crates()
            .iter()
            .find(|&&krate| this.tcx.original_crate_name(krate).as_str() == path[0])
            .and_then(|krate| {
                let krate = DefId {
                    krate: *krate,
                    index: CRATE_DEF_INDEX,
                };
                let mut items = this.tcx.item_children(krate);
                let mut path_it = path.iter().skip(1).peekable();

                while let Some(segment) = path_it.next() {
                    for item in mem::replace(&mut items, Default::default()).iter() {
                        if item.ident.name.as_str() == *segment {
                            if path_it.peek().is_none() {
                                return Some(ty::Instance::mono(this.tcx.tcx, item.res.def_id()));
                            }

                            items = this.tcx.item_children(item.res.def_id());
                            break;
                        }
                    }
                }
                None
            })
            .ok_or_else(|| {
                let path = path.iter().map(|&s| s.to_owned()).collect();
                err_unsup!(PathNotFound(path)).into()
            })
    }

    /// Write a 0 of the appropriate size to `dest`.
    fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
        self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
    }

    /// Test if this immediate equals 0.
    fn is_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, bool> {
        let this = self.eval_context_ref();
        let null = Scalar::from_int(0, this.memory().pointer_size());
        this.ptr_eq(val, null)
    }

    /// Turn a Scalar into an Option<NonNullScalar>
    fn test_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, Option<Scalar<Tag>>> {
        let this = self.eval_context_ref();
        Ok(if this.is_null(val)? {
            None
        } else {
            Some(val)
        })
    }

    /// Get the `Place` for a local
    fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Tag>> {
        let this = self.eval_context_mut();
        let place = mir::Place { base: mir::PlaceBase::Local(local), projection: Box::new([]) };
        this.eval_place(&place)
    }

    /// Generate some random bytes, and write them to `dest`.
    fn gen_random(
        &mut self,
        ptr: Scalar<Tag>,
        len: usize,
    ) -> InterpResult<'tcx>  {
        // Some programs pass in a null pointer and a length of 0
        // to their platform's random-generation function (e.g. getrandom())
        // on Linux. For compatibility with these programs, we don't perform
        // any additional checks - it's okay if the pointer is invalid,
        // since we wouldn't actually be writing to it.
        if len == 0 {
            return Ok(());
        }
        let this = self.eval_context_mut();

        let ptr = this.memory().check_ptr_access(
            ptr,
            Size::from_bytes(len as u64),
            Align::from_bytes(1).unwrap()
        )?.expect("we already checked for size 0");

        let mut data = vec![0; len];

        if this.machine.communicate {
            // Fill the buffer using the host's rng.
            getrandom::getrandom(&mut data)
                .map_err(|err| err_unsup_format!("getrandom failed: {}", err))?;
        }
        else {
            let rng = this.memory_mut().extra.rng.get_mut();
            rng.fill_bytes(&mut data);
        }

        let tcx = &{this.tcx.tcx};
        this.memory_mut().get_mut(ptr.alloc_id)?.write_bytes(tcx, ptr, &data)
    }

    /// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
    /// will be true if this is frozen, false if this is in an `UnsafeCell`.
    fn visit_freeze_sensitive(
        &self,
        place: MPlaceTy<'tcx, Tag>,
        size: Size,
        mut action: impl FnMut(Pointer<Tag>, Size, bool) -> InterpResult<'tcx>,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_ref();
        trace!("visit_frozen(place={:?}, size={:?})", *place, size);
        debug_assert_eq!(size,
            this.size_and_align_of_mplace(place)?
            .map(|(size, _)| size)
            .unwrap_or_else(|| place.layout.size)
        );
        // Store how far we proceeded into the place so far. Everything to the left of
        // this offset has already been handled, in the sense that the frozen parts
        // have had `action` called on them.
        let mut end_ptr = place.ptr.assert_ptr();
        // Called when we detected an `UnsafeCell` at the given offset and size.
        // Calls `action` and advances `end_ptr`.
        let mut unsafe_cell_action = |unsafe_cell_ptr: Scalar<Tag>, unsafe_cell_size: Size| {
            let unsafe_cell_ptr = unsafe_cell_ptr.assert_ptr();
            debug_assert_eq!(unsafe_cell_ptr.alloc_id, end_ptr.alloc_id);
            debug_assert_eq!(unsafe_cell_ptr.tag, end_ptr.tag);
            // We assume that we are given the fields in increasing offset order,
            // and nothing else changes.
            let unsafe_cell_offset = unsafe_cell_ptr.offset;
            let end_offset = end_ptr.offset;
            assert!(unsafe_cell_offset >= end_offset);
            let frozen_size = unsafe_cell_offset - end_offset;
            // Everything between the end_ptr and this `UnsafeCell` is frozen.
            if frozen_size != Size::ZERO {
                action(end_ptr, frozen_size, /*frozen*/true)?;
            }
            // This `UnsafeCell` is NOT frozen.
            if unsafe_cell_size != Size::ZERO {
                action(unsafe_cell_ptr, unsafe_cell_size, /*frozen*/false)?;
            }
            // Update end end_ptr.
            end_ptr = unsafe_cell_ptr.wrapping_offset(unsafe_cell_size, this);
            // Done
            Ok(())
        };
        // Run a visitor
        {
            let mut visitor = UnsafeCellVisitor {
                ecx: this,
                unsafe_cell_action: |place| {
                    trace!("unsafe_cell_action on {:?}", place.ptr);
                    // We need a size to go on.
                    let unsafe_cell_size = this.size_and_align_of_mplace(place)?
                        .map(|(size, _)| size)
                        // for extern types, just cover what we can
                        .unwrap_or_else(|| place.layout.size);
                    // Now handle this `UnsafeCell`, unless it is empty.
                    if unsafe_cell_size != Size::ZERO {
                        unsafe_cell_action(place.ptr, unsafe_cell_size)
                    } else {
                        Ok(())
                    }
                },
            };
            visitor.visit_value(place)?;
        }
        // The part between the end_ptr and the end of the place is also frozen.
        // So pretend there is a 0-sized `UnsafeCell` at the end.
        unsafe_cell_action(place.ptr.ptr_wrapping_offset(size, this), Size::ZERO)?;
        // Done!
        return Ok(());

        /// Visiting the memory covered by a `MemPlace`, being aware of
        /// whether we are inside an `UnsafeCell` or not.
        struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
            where F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            ecx: &'ecx MiriEvalContext<'mir, 'tcx>,
            unsafe_cell_action: F,
        }

        impl<'ecx, 'mir, 'tcx, F>
            ValueVisitor<'mir, 'tcx, Evaluator<'tcx>>
        for
            UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
        where
            F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            type V = MPlaceTy<'tcx, Tag>;

            #[inline(always)]
            fn ecx(&self) -> &MiriEvalContext<'mir, 'tcx> {
                &self.ecx
            }

            // Hook to detect `UnsafeCell`.
            fn visit_value(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty);
                let is_unsafe_cell = match v.layout.ty.kind {
                    ty::Adt(adt, _) => Some(adt.did) == self.ecx.tcx.lang_items().unsafe_cell_type(),
                    _ => false,
                };
                if is_unsafe_cell {
                    // We do not have to recurse further, this is an `UnsafeCell`.
                    (self.unsafe_cell_action)(v)
                } else if self.ecx.type_is_freeze(v.layout.ty) {
                    // This is `Freeze`, there cannot be an `UnsafeCell`
                    Ok(())
                } else {
                    // We want to not actually read from memory for this visit. So, before
                    // walking this value, we have to make sure it is not a
                    // `Variants::Multiple`.
                    match v.layout.variants {
                        layout::Variants::Multiple { .. } => {
                            // A multi-variant enum, or generator, or so.
                            // Treat this like a union: without reading from memory,
                            // we cannot determine the variant we are in. Reading from
                            // memory would be subject to Stacked Borrows rules, leading
                            // to all sorts of "funny" recursion.
                            // We only end up here if the type is *not* freeze, so we just call the
                            // `UnsafeCell` action.
                            (self.unsafe_cell_action)(v)
                        }
                        layout::Variants::Single { .. } => {
                            // Proceed further, try to find where exactly that `UnsafeCell`
                            // is hiding.
                            self.walk_value(v)
                        }
                    }
                }
            }

            // Make sure we visit aggregrates in increasing offset order.
            fn visit_aggregate(
                &mut self,
                place: MPlaceTy<'tcx, Tag>,
                fields: impl Iterator<Item=InterpResult<'tcx, MPlaceTy<'tcx, Tag>>>,
            ) -> InterpResult<'tcx> {
                match place.layout.fields {
                    layout::FieldPlacement::Array { .. } => {
                        // For the array layout, we know the iterator will yield sorted elements so
                        // we can avoid the allocation.
                        self.walk_aggregate(place, fields)
                    }
                    layout::FieldPlacement::Arbitrary { .. } => {
                        // Gather the subplaces and sort them before visiting.
                        let mut places = fields.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Tag>>>>()?;
                        places.sort_by_key(|place| place.ptr.assert_ptr().offset);
                        self.walk_aggregate(place, places.into_iter().map(Ok))
                    }
                    layout::FieldPlacement::Union { .. } => {
                        // Uh, what?
                        bug!("a union is not an aggregate we should ever visit")
                    }
                }
            }

            // We have to do *something* for unions.
            fn visit_union(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                // With unions, we fall back to whatever the type says, to hopefully be consistent
                // with LLVM IR.
                // FIXME: are we consistent, and is this really the behavior we want?
                let frozen = self.ecx.type_is_freeze(v.layout.ty);
                if frozen {
                    Ok(())
                } else {
                    (self.unsafe_cell_action)(v)
                }
            }

            // We should never get to a primitive, but always short-circuit somewhere above.
            fn visit_primitive(&mut self, _v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                bug!("we should always short-circuit before coming to a primitive")
            }
        }
    }

    /// Helper function to get a `libc` constant as a `Scalar`.
    fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
        self.eval_context_mut()
            .eval_path_scalar(&["libc", name])?
            .ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
            .not_undef()
    }

    /// Helper function to get a `libc` constant as an `i32`.
    fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
        self.eval_libc(name)?.to_i32()
    }

    fn write_c_ints(
        &mut self,
        ptr: &Pointer<Tag>,
        bits: &[i128],
        ty_names: &[&str],
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        let tcx = &{ this.tcx.tcx };

        let mut sizes = Vec::new();

        for name in ty_names {
            let ty = this.resolve_path(&["libc", name])?.ty(*tcx);
            sizes.push(this.layout_of(ty)?.size);
        }

        let allocation = this.memory_mut().get_mut(ptr.alloc_id)?;
        let mut offset = Size::from_bytes(0);

        for (&value, size) in bits.iter().zip(sizes) {
            // If `value` does not fit in `size` bits, we error instead of letting
            // `Scalar::from_int` panic.
            let truncated = truncate(value as u128, size);
            if sign_extend(truncated, size) as i128 != value {
                throw_unsup_format!(
                    "Signed value {:#x} does not fit in {} bits",
                    value,
                    size.bits()
                )
            }

            allocation.write_scalar(
                tcx,
                ptr.offset(offset, tcx)?,
                Scalar::from_int(value, size).into(),
                size,
            )?;
            offset += size;
        }

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


<commit_before>#![crate_name = "hiredis"]
#![crate_type = "lib"]
#![feature(globs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;

use std::mem::transmute;

pub mod api;

pub struct Reply {
    head:  bool,
    reply: *const api::Reply
}

pub enum ReplyCode {
    String = 1,
    Array,
    Integer,
    Nil,
    Status,
    Error,
    Unknown
}

impl Reply {
    /**
     * Creates a new Reply wrapper.
     *
     * This wraps an already existing Reply returned from hiredis, it will
     * automatically free the data when the reply goes out of scope. Note that
     * this method cannot be invoked outside of the crate.
     */
    fn new(reply: *const api::Reply) -> Reply {
        Reply {
            head:  true,
            reply: reply
        }
    }

    /**
     * Redis replies with the type of data being sent, this method allows
     * peaking into it.
     *
     * TODO: Create a nicer wrapper enum that encodes the data directly with
     * Vectors and so on.
     */
    pub fn typename(&self) -> ReplyCode {
        unsafe {
            match (*self.reply)._type {
                1 => String,
                2 => Array,
                3 => Integer,
                4 => Nil,
                5 => Status,
                6 => Error,
                v => {
                    println!("Unknown Error: {}", v);
                    Unknown
                }
            }
        }
    }

    pub fn string<'r>(&'r self) -> Option<&'r [u8]> {
        match self.typename() {
            String => {
                unsafe {
                    let data = std::c_vec::CVec::new(
                        (*self.reply)._str as *mut u8,
                        (*self.reply).len as uint
                    ).as_mut_slice() as *mut [u8];

                    Some(&*data)
                }
            }

            _ => {
                None
            }
        }
    }
}

impl Drop for Reply {
    fn drop(&mut self) {
        unsafe {
            /* When Redis returns a Reply object, we wrap it in our own Reply
             * object. However, if redis returns an array, the Reply object
             * contains an array of sub Reply objects. These get wrapped too,
             * but should not be freed, as freeing the head object frees the
             * children too. This check prevents us accidentally freeing replies
             * that shouldn't be freed.
             */
            if self.head {
                api::freeReplyObject(transmute(self.reply))
            }
        }
    }
}

pub struct Redis {
    context: *const api::Context
}

impl Redis {
    /**
     * Creates a new connection to a Redis instance.
     *
     * TODO: Deal with the other redisConnect* variants, not yet sure how to
     * design this API.
     */
    pub fn new(ip: &str, port: i32) -> Redis {
        unsafe {
            Redis {
                context: api::redisConnect(
                    ip.to_c_str().as_ptr(),
                    port
                )
            }
        }
    }

    /**
     * Sends a single command to be executed, and returns the reply immediately.
     * If further replies are expected the `receive` function exists to expect
     * them. This function doesn't handle complex spaces in messages, and so the
     * `execf` function exists and uses hiredis's formatting instead.
     *
     * TODO: Move to IoResult using context.err
     */
    pub fn command(&self, command: &str) -> Option<Reply> {
        command.with_c_str(|v| {
            unsafe {
                /* This is the library call, returns (void*)0 on failure. */
                let result = api::redisCommand(self.context, v);

                /* Fail if the command errored for some reason. */
                if result == 0 as *const ::libc::c_void {
                    return None;
                }

                /* Otherwise cast the pointer to the actual struct type being
                 * returned and store it to be returned. */
                Some(Reply::new(result as *const api::Reply))
            }
        })
    }

    /**
     * Appends a command to the output buffer, allowing for pipelining.
     *
     * TODO: This needs to return a status code.
     */
    pub fn append_command(&self, command: &str) {
        command.with_c_str(|v| {
            unsafe {
                api::redisAppendCommand(self.context, v);
            }
        });
    }

    /**
     * Attempts to read a message from the input buffer. Blocking in this
     * context depends on how the connection was created.
     */
    pub fn receive(&self) -> Option<Reply> {
        unsafe {
            let reply: Reply = std::mem::uninitialized();
            let result       = api::redisGetReply(self.context, transmute(&reply));

            Some(reply)
        }
    }
}

impl Drop for Redis {
    /**
     * When a Redis instance goes out of scope, the connection needs to be
     * closed. Redis has a function for this that both closes the connection and
     * frees any resources used.
     */
    fn drop(&mut self) {
        unsafe {
            api::redisFree(self.context)
        }
    }
}
<commit_msg>Ignore<commit_after>#![crate_name = "hiredis"]
#![crate_type = "lib"]
#![feature(globs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;

use std::mem::transmute;

pub mod api;

pub struct Reply {
    head:  bool,
    reply: *const api::Reply
}

pub enum ReplyCode {
    String = 1,
    Array,
    Integer,
    Nil,
    Status,
    Error,
    Unknown
}

impl Reply {
    /**
     * Creates a new Reply wrapper.
     *
     * This wraps an already existing Reply returned from hiredis, it will
     * automatically free the data when the reply goes out of scope. Note that
     * this method cannot be invoked outside of the crate.
     */
    fn new(reply: *const api::Reply) -> Reply {
        Reply {
            head:  true,
            reply: reply
        }
    }

    /**
     * Redis replies with the type of data being sent, this method allows
     * peaking into it.
     *
     * TODO: Create a nicer wrapper enum that encodes the data directly with
     * Vectors and so on.
     */
    pub fn typename(&self) -> uint {
        unsafe {
            //match (*self.reply)._type {
            //    1 => String,
            //    2 => Array,
            //    3 => Integer,
            //    4 => Nil,
            //    5 => Status,
            //    6 => Error,
            //    v => {
            //        println!("Unknown Error: {}", v);
            //        Unknown
            //    }
            //}
        }

        unsafe { (*self.reply)._type as uint }
    }

    pub fn string<'r>(&'r self) -> Option<&'r [u8]> {
        None
        //match self.typename() {
        //    String => {
        //        unsafe {
        //            let data = std::c_vec::CVec::new(
        //                (*self.reply)._str as *mut u8,
        //                (*self.reply).len as uint
        //            ).as_mut_slice() as *mut [u8];

        //            Some(&*data)
        //        }
        //    }

        //    _ => {
        //        None
        //    }
        //}
    }
}

impl Drop for Reply {
    fn drop(&mut self) {
        unsafe {
            /* When Redis returns a Reply object, we wrap it in our own Reply
             * object. However, if redis returns an array, the Reply object
             * contains an array of sub Reply objects. These get wrapped too,
             * but should not be freed, as freeing the head object frees the
             * children too. This check prevents us accidentally freeing replies
             * that shouldn't be freed.
             */
            if self.head {
                api::freeReplyObject(transmute(self.reply))
            }
        }
    }
}

pub struct Redis {
    context: *const api::Context
}

impl Redis {
    /**
     * Creates a new connection to a Redis instance.
     *
     * TODO: Deal with the other redisConnect* variants, not yet sure how to
     * design this API.
     */
    pub fn new(ip: &str, port: i32) -> Redis {
        unsafe {
            Redis {
                context: api::redisConnect(
                    ip.to_c_str().as_ptr(),
                    port
                )
            }
        }
    }

    /**
     * Sends a single command to be executed, and returns the reply immediately.
     * If further replies are expected the `receive` function exists to expect
     * them. This function doesn't handle complex spaces in messages, and so the
     * `execf` function exists and uses hiredis's formatting instead.
     *
     * TODO: Move to IoResult using context.err
     */
    pub fn command(&self, command: &str) -> Option<Reply> {
        command.with_c_str(|v| {
            unsafe {
                /* This is the library call, returns (void*)0 on failure. */
                let result = api::redisCommand(self.context, v);

                /* Fail if the command errored for some reason. */
                if result == 0 as *const ::libc::c_void {
                    return None;
                }

                /* Otherwise cast the pointer to the actual struct type being
                 * returned and store it to be returned. */
                Some(Reply::new(result as *const api::Reply))
            }
        })
    }

    /**
     * Appends a command to the output buffer, allowing for pipelining.
     *
     * TODO: This needs to return a status code.
     */
    pub fn append_command(&self, command: &str) {
        command.with_c_str(|v| {
            unsafe {
                api::redisAppendCommand(self.context, v);
            }
        });
    }

    /**
     * Attempts to read a message from the input buffer. Blocking in this
     * context depends on how the connection was created.
     */
    pub fn receive(&self) -> Option<Reply> {
        unsafe {
            let reply: Reply = std::mem::uninitialized();
            let result       = api::redisGetReply(self.context, transmute(&reply));

            Some(reply)
        }
    }
}

impl Drop for Redis {
    /**
     * When a Redis instance goes out of scope, the connection needs to be
     * closed. Redis has a function for this that both closes the connection and
     * frees any resources used.
     */
    fn drop(&mut self) {
        unsafe {
            api::redisFree(self.context)
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::ops::Index;

pub struct Cursor<'a> {
    history: &'a History,
    cur: Option<usize>
}

impl<'a> Cursor<'a> {

    pub fn new(h: &'a History) -> Cursor<'a> {
        Cursor { history: h, cur: None }
    }

    pub fn incr(&mut self) -> bool {
        let mut flag = false;
        self.cur = match self.cur {
            Some(i) if i + 1 < self.history.len() => Some(i + 1),
            Some(i) => Some(i),
            None if self.history.len() > 0 => {flag = true; Some(0)},
            None => None
        };
        flag
    }

    pub fn decr(&mut self) -> bool {
        let mut flag = false;
        self.cur = match self.cur {
            Some(i) if i > 0 => Some(i - 1),
            Some(_) => {flag = true; None},
            None => None
        };
        flag
    }

    pub fn get(&self) -> Option<&'a String> {
        match self.cur {
            None => None,
            Some(i) => self.history.get(i)
        }
    }

}

pub struct History {
    deque: VecDeque<String>
}

impl History {

    pub fn new() -> History {
        History {
            deque: VecDeque::new()
        }
    }

    pub fn len(&self) -> usize {
        self.deque.len()
    }

    pub fn push(&mut self, s: String) {
        if s.len() > 0 && self.deque.front() != Option::Some(&s) {
            self.deque.push_front(s)
        }
    }

    pub fn pop(&mut self) -> Option<String> {
        self.deque.pop_front()
    }

    pub fn get(&self, idx: usize) -> Option<&String> {
        let len = self.len();
        if len > 0 && idx < len {
            Some(self.deque.index(idx))
        } else {
            None
        }
    }

    pub fn remove(&mut self, idx: usize) -> Option<String> {
        self.deque.remove(idx)
    }

    pub fn clear(&mut self) {
        self.deque.clear()
    }

}
<commit_msg>changed len() > 0 to !is_empty()<commit_after>use std::collections::VecDeque;
use std::ops::Index;

pub struct Cursor<'a> {
    history: &'a History,
    cur: Option<usize>
}

impl<'a> Cursor<'a> {

    pub fn new(h: &'a History) -> Cursor<'a> {
        Cursor { history: h, cur: None }
    }

    pub fn incr(&mut self) -> bool {
        let mut flag = false;
        self.cur = match self.cur {
            Some(i) if i + 1 < self.history.len() => Some(i + 1),
            Some(i) => Some(i),
            None if self.history.len() > 0 => {flag = true; Some(0)},
            None => None
        };
        flag
    }

    pub fn decr(&mut self) -> bool {
        let mut flag = false;
        self.cur = match self.cur {
            Some(i) if i > 0 => Some(i - 1),
            Some(_) => {flag = true; None},
            None => None
        };
        flag
    }

    pub fn get(&self) -> Option<&'a String> {
        match self.cur {
            None => None,
            Some(i) => self.history.get(i)
        }
    }

}

pub struct History {
    deque: VecDeque<String>
}

impl History {

    pub fn new() -> History {
        History {
            deque: VecDeque::new()
        }
    }

    pub fn len(&self) -> usize {
        self.deque.len()
    }

    pub fn push(&mut self, s: String) {
        if !s.is_empty() && self.deque.front() != Option::Some(&s) {
            self.deque.push_front(s)
        }
    }

    pub fn pop(&mut self) -> Option<String> {
        self.deque.pop_front()
    }

    pub fn get(&self, idx: usize) -> Option<&String> {
        let len = self.len();
        if len > 0 && idx < len {
            Some(self.deque.index(idx))
        } else {
            None
        }
    }

    pub fn remove(&mut self, idx: usize) -> Option<String> {
        self.deque.remove(idx)
    }

    pub fn clear(&mut self) {
        self.deque.clear()
    }

}
<|endoftext|>


<commit_before>/// Wrapper around the afl-fuzz binary

use libc;
use std::env;
use std::ffi::CString;
use std::path::PathBuf;

extern "C" {
    // `main` function with afl-fuzz.c
    fn afl_fuzz_main(argc: libc::c_int,
                     argv: *const *const libc::c_char) -> libc::c_int;
}

fn call_afl_fuzz_main(args: Vec<CString>) -> Result<(), libc::c_int> {
    assert!(!args.is_empty());

    // `main` functions in C expect an array of pointers to the arguments
    let args_ptrs = args.iter()
                        .map(|arg| arg.as_ptr())
                        .collect::<Vec<_>>();

    let ret = unsafe {
        afl_fuzz_main(args_ptrs.len() as libc::c_int,
                      args_ptrs.as_ptr())
    };

    match ret {
        0 => Ok(()),
        n => Err(n),
    }
}

// TODO: use builder pattern
pub struct AflFuzzConfig {
    pub in_dir: PathBuf,
    pub out_dir: PathBuf,
    pub target: PathBuf,
}

impl AflFuzzConfig {
    fn into_args(self) -> Vec<CString> {
        let mut args = vec![];

        // -i
        args.push("-i");
        args.push(self.in_dir.to_str().unwrap());

        // -o
        args.push("-o");
        args.push(self.out_dir.to_str().unwrap());

        // target
        args.push(self.target.to_str().unwrap());

        // Convert args from `str`s to to `CString`s
        args.into_iter()
            .map(|s| CString::new(s).unwrap())
            .collect()
    }
}

pub fn afl_fuzz_env() -> Result<(), libc::c_int> {
    let args = env::args();

    // don't include anything before 'afl-fuzz' or 'cargo-afl-fuzz'
    let args = args.skip_while(|a| a != "afl-fuzz" && a != "cargo-afl-fuzz")
                   .map(|arg| CString::new(arg).unwrap())
                   .collect::<Vec<_>>();
    assert!(!args.is_empty(), "Error generating afl-fuzz arguments");

    call_afl_fuzz_main(args)
}

pub fn afl_fuzz(config: AflFuzzConfig) -> Result<(), libc::c_int> {
    let mut args = vec![];

    // Fake the first argument
    let arg0 = CString::new("afl-fuzz").unwrap();
    args.push(arg0);

    args.extend(config.into_args());

    call_afl_fuzz_main(args)
}

/// FIXME: figure out a way to make it not run indefinitely
#[test]
fn testsomething() {
    let config = AflFuzzConfig {
        in_dir: ".".into(),
        out_dir: "testout".into(),
        target: "../target/debug/examples/hello".into(),
    };
    afl_fuzz(config);
}
<commit_msg>Remove duplicated word in a comment<commit_after>/// Wrapper around the afl-fuzz binary

use libc;
use std::env;
use std::ffi::CString;
use std::path::PathBuf;

extern "C" {
    // `main` function with afl-fuzz.c
    fn afl_fuzz_main(argc: libc::c_int,
                     argv: *const *const libc::c_char) -> libc::c_int;
}

fn call_afl_fuzz_main(args: Vec<CString>) -> Result<(), libc::c_int> {
    assert!(!args.is_empty());

    // `main` functions in C expect an array of pointers to the arguments
    let args_ptrs = args.iter()
                        .map(|arg| arg.as_ptr())
                        .collect::<Vec<_>>();

    let ret = unsafe {
        afl_fuzz_main(args_ptrs.len() as libc::c_int,
                      args_ptrs.as_ptr())
    };

    match ret {
        0 => Ok(()),
        n => Err(n),
    }
}

// TODO: use builder pattern
pub struct AflFuzzConfig {
    pub in_dir: PathBuf,
    pub out_dir: PathBuf,
    pub target: PathBuf,
}

impl AflFuzzConfig {
    fn into_args(self) -> Vec<CString> {
        let mut args = vec![];

        // -i
        args.push("-i");
        args.push(self.in_dir.to_str().unwrap());

        // -o
        args.push("-o");
        args.push(self.out_dir.to_str().unwrap());

        // target
        args.push(self.target.to_str().unwrap());

        // Convert args from `str`s to `CString`s
        args.into_iter()
            .map(|s| CString::new(s).unwrap())
            .collect()
    }
}

pub fn afl_fuzz_env() -> Result<(), libc::c_int> {
    let args = env::args();

    // don't include anything before 'afl-fuzz' or 'cargo-afl-fuzz'
    let args = args.skip_while(|a| a != "afl-fuzz" && a != "cargo-afl-fuzz")
                   .map(|arg| CString::new(arg).unwrap())
                   .collect::<Vec<_>>();
    assert!(!args.is_empty(), "Error generating afl-fuzz arguments");

    call_afl_fuzz_main(args)
}

pub fn afl_fuzz(config: AflFuzzConfig) -> Result<(), libc::c_int> {
    let mut args = vec![];

    // Fake the first argument
    let arg0 = CString::new("afl-fuzz").unwrap();
    args.push(arg0);

    args.extend(config.into_args());

    call_afl_fuzz_main(args)
}

/// FIXME: figure out a way to make it not run indefinitely
#[test]
fn testsomething() {
    let config = AflFuzzConfig {
        in_dir: ".".into(),
        out_dir: "testout".into(),
        target: "../target/debug/examples/hello".into(),
    };
    afl_fuzz(config);
}
<|endoftext|>


<commit_before>// FIXME: needs to be updated to provide_ref/request_ref API.
// https://github.com/rust-lang/rust/pull/99431
#![cfg(any())]

#[rustversion::not(nightly)]
#[ignore]
#[test]
fn test_backtrace() {}

#[rustversion::nightly]
#[test]
fn test_backtrace() {
    use anyhow::anyhow;

    let error = anyhow!("oh no!");
    let _ = error.backtrace();
}
<commit_msg>Revert "Disable backtrace test until converted to provider API"<commit_after>#[rustversion::not(nightly)]
#[ignore]
#[test]
fn test_backtrace() {}

#[rustversion::nightly]
#[test]
fn test_backtrace() {
    use anyhow::anyhow;

    let error = anyhow!("oh no!");
    let _ = error.backtrace();
}
<|endoftext|>