<commit_before>use super::internal_prelude::*;

    fn constrain_size_but_input_format(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
        let input = ctx.first_parent_frame_info_some(ix).unwrap();

        let weight = &mut ctx.weight_mut(ix);
        match weight.params {
            NodeParams::Json(s::Node::Constrain(ref constraint)) => {
                let (w, h, _) = constrain(input.w as u32, input.h as u32, constraint);
                weight.frame_est = FrameEstimate::Some(FrameInfo {
                    w: w as i32,
                    h: h as i32,
                    fmt: ffi::PixelFormat::from(input.fmt),
                    alpha_meaningful: input.alpha_meaningful,
                });
            }
            _ => {
                panic!("Node params missing");
            }
        }
    }

fn scale_b_to(aspect_ratio_a_over_b: f32, a_from: u32, a_to: u32, b_from: u32) -> u32{
    let scale_factor = a_to as f32 / a_from as f32;
    let result = b_from as f32 * scale_factor;// * aspect_ratio_a_over_b;
    result.round() as u32
}
fn constrain(old_w: u32, old_h: u32, constraint: &s::Constraint) -> (u32,u32, Option<s::ConstraintResamplingHints>){
    let aspect = old_w as f32 / old_h as f32;
    match constraint.clone(){

        s::Constraint::Within{ w: Some(w), h: None, ref hints} if w < old_w => {
            (w, scale_b_to(aspect, old_w, w, old_h), *hints)
        }
        s::Constraint::Within{ w: None, h: Some(h), ref hints} if h < old_h => {
            (scale_b_to(1f32 / aspect, old_h, h, old_w), h, *hints)
        }
        s::Constraint::Within{ w: Some(w), h: Some(h), ref hints} if w < old_w || h < old_h => {

            let constraint_aspect = w as f32 / h as f32;
            if constraint_aspect > aspect{
                //height is the constraint
                (scale_b_to(1f32 / aspect, old_h, h, old_w), h, *hints)
            }else{
                //width is the constraint
                (w, scale_b_to(aspect, old_w, w, old_h), *hints)
            }
        }
        s::Constraint::Within{ ref hints, ..} => (old_w, old_h, *hints),
    }
}

#[test]
fn test_constrain(){
    //let hints = s::ConstraintResamplingHints{down_filter: None, up_filter: None, resample_when: None, sharpen_percent: None};
    {
        let constraint = s::Constraint::Within { w: Some(100), h: Some(100), hints: None };
        assert_eq!(constrain(200, 50, &constraint), (100, 25, None));
    }
    {
        let constraint = s::Constraint::Within { w: Some(100), h: Some(100), hints: None };
        assert_eq!(constrain(50, 200, &constraint), (25, 100, None));
    }
    {
        let constraint = s::Constraint::Within { w: Some(640), h: Some(480), hints: None };
        assert_eq!(constrain(200, 50, &constraint), (200, 50, None));
    }
    {
        let constraint = s::Constraint::Within { w: Some(100), h: Some(100), hints: None };
        assert_eq!(constrain(100, 100, &constraint), (100, 100, None));
    }
    {
        let constraint = s::Constraint::Within { w: Some(100), h: Some(100), hints: None };
        assert_eq!(constrain(100, 100, &constraint), (100, 100, None));
    }

}

fn constrain_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.constrain",
        name: "constrain",
        inbound_edges: EdgesIn::OneInput,
        description: "constrain",
        fn_estimate: Some(constrain_size_but_input_format),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                let input = ctx.first_parent_frame_info_some(ix).unwrap();
                let input_w = input.w as u32;
                let input_h = input.h as u32;
                if let s::Node::Constrain(ref constraint) =
                ctx.get_json_params(ix).unwrap() {

                    let (new_w, new_h, hints_val) = constrain(input_w, input_h, constraint);

                    let hints = &hints_val;

                    let resample_when = hints.and_then(|ref h| h.resample_when).unwrap_or(s::ResampleWhen::SizeDiffers);
                    let size_differs = new_w != input_w || new_h != input_h;
                    let sharpen_requested = hints.and_then(|h| h.sharpen_percent).unwrap_or(0f32) > 0f32;

                    let resample = match resample_when{
                        s::ResampleWhen::Always => true,
                        s::ResampleWhen::SizeDiffers if size_differs => true,
                        s::ResampleWhen::SizeDiffersOrSharpeningRequested if size_differs || sharpen_requested => true,
                        _ => false
                    };

                    if resample {
                        let scale2d_params = s::Node::Resample2D {
                            w: new_w as usize,
                            h: new_h as usize,
                            up_filter: hints.and_then(|h| h.up_filter),
                            down_filter: hints.and_then(|h| h.down_filter),
                            hints: hints.map(|h| s::ResampleHints {
                                sharpen_percent: h.sharpen_percent,
                                prefer_1d_twice: None
                            }),
                        };

                        let scale2d = ctx.graph
                            .add_node(Node::new(&super::SCALE,
                                                NodeParams::Json(scale2d_params)));
                        ctx.replace_node_with_existing(ix, scale2d);
                    }else{
                        ctx.delete_node_and_snap_together(ix);
                    }
                }

            }
            f
        }),
        ..Default::default()
    }
}

fn command_string_partially_expanded_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.expanding_command_string",
        name: "expanding_command_string",
        inbound_edges: EdgesIn::OneInput,
        description: "expanding command string",
        fn_estimate: None,
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                let input = ctx.first_parent_frame_info_some(ix).unwrap();

                if let s::Node::CommandString{ref kind, ref value, ref decode, ref encode} =
                ctx.get_json_params(ix).unwrap() {

                    match kind {
                        &s::CommandStringKind::ImageResizer4 => {
                            let url = ::url::Url::from_str(&format!("https://fakeurl/img.jpg?{}", value)).expect("Must be a valid querystring, excluding ?");

                            let (ext, mime) = match (input.fmt, input.alpha_meaningful){
                                (PixelFormat::Bgr24, false) => ("jpg", "image/jpeg"),
                                _ => ("png", "image/png")
                            };

                            let (instructions, warnings) = ::imageflow_riapi::ir4::parsing::parse_url(&url);
                            let layout = ::imageflow_riapi::ir4::Ir4Layout::new(
                                s::ImageInfo{
                                    current_frame_index: 0,
                                    frame_count: 1,
                                    frame_decodes_into: input.fmt,
                                    image_height: input.h,
                                    image_width: input.w,
                                    preferred_extension: ext.to_owned(),
                                    preferred_mime_type: mime.to_owned(),
                                },
                                instructions
                            );
                            match layout.produce_steps(None, *encode) {
                                Ok(steps) => {
                                    ctx.replace_node(ix, steps.into_iter().map(|n| Node::from(n)).collect::<>());
                                }
                                Err(e) => {
                                    panic!("{:?} {:?}", e, warnings);
                                }
                            }
                        }
                    }
                }

            }
            f
        }),
        ..Default::default()
    }
}

fn command_string_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.command_string",
        name: "command_string",
        inbound_edges: EdgesIn::OneOptionalInput,
        description: "command string",
        fn_estimate: None,
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                let n = ctx.get_json_params(ix).unwrap();

                if let s::Node::CommandString{ref kind, ref value, ref decode, ref encode} = n.clone() {

                    match kind {
                        &s::CommandStringKind::ImageResizer4 => {

                            let input = ctx.first_parent_frame_info_some(ix);

                            if let &Some(d_id) = decode{
                                if input.is_some(){
                                    panic!("CommandString must either have decode: null or have no parent nodes. Specifying a value for decode creates a new decoder node.");
                                }
                                // TODO: decoder commands should be sourced from Instructions
                                ctx.replace_node(ix, vec![
                                    Node::from(s::Node::Decode {io_id: d_id, commands: None}),
                                    Node::new(&EXPANDING_COMMAND_STRING, NodeParams::Json(n))
                                ]);
                            }else{
                                if input.is_some(){
                                    panic!("CommandString must have a parent node unless 'decode' has a numeric value. Otherwise it has no image source. ");
                                }
                                ctx.replace_node(ix, vec![
                                    Node::new(&EXPANDING_COMMAND_STRING, NodeParams::Json(n))
                                ]);
                            }
                        }
                    }
                }

            }
            f
        }),
        ..Default::default()
    }
}

lazy_static! {
    pub static ref CONSTRAIN: NodeDefinition = constrain_def();
    pub static ref COMMAND_STRING: NodeDefinition = command_string_def();
    pub static ref EXPANDING_COMMAND_STRING: NodeDefinition = command_string_partially_expanded_def();
}
<commit_msg>For IR4, always map no-alpha to jpeg by default (for now)<commit_after>use super::internal_prelude::*;

    fn constrain_size_but_input_format(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
        let input = ctx.first_parent_frame_info_some(ix).unwrap();

        let weight = &mut ctx.weight_mut(ix);
        match weight.params {
            NodeParams::Json(s::Node::Constrain(ref constraint)) => {
                let (w, h, _) = constrain(input.w as u32, input.h as u32, constraint);
                weight.frame_est = FrameEstimate::Some(FrameInfo {
                    w: w as i32,
                    h: h as i32,
                    fmt: ffi::PixelFormat::from(input.fmt),
                    alpha_meaningful: input.alpha_meaningful,
                });
            }
            _ => {
                panic!("Node params missing");
            }
        }
    }

fn scale_b_to(aspect_ratio_a_over_b: f32, a_from: u32, a_to: u32, b_from: u32) -> u32{
    let scale_factor = a_to as f32 / a_from as f32;
    let result = b_from as f32 * scale_factor;// * aspect_ratio_a_over_b;
    result.round() as u32
}
fn constrain(old_w: u32, old_h: u32, constraint: &s::Constraint) -> (u32,u32, Option<s::ConstraintResamplingHints>){
    let aspect = old_w as f32 / old_h as f32;
    match constraint.clone(){

        s::Constraint::Within{ w: Some(w), h: None, ref hints} if w < old_w => {
            (w, scale_b_to(aspect, old_w, w, old_h), *hints)
        }
        s::Constraint::Within{ w: None, h: Some(h), ref hints} if h < old_h => {
            (scale_b_to(1f32 / aspect, old_h, h, old_w), h, *hints)
        }
        s::Constraint::Within{ w: Some(w), h: Some(h), ref hints} if w < old_w || h < old_h => {

            let constraint_aspect = w as f32 / h as f32;
            if constraint_aspect > aspect{
                //height is the constraint
                (scale_b_to(1f32 / aspect, old_h, h, old_w), h, *hints)
            }else{
                //width is the constraint
                (w, scale_b_to(aspect, old_w, w, old_h), *hints)
            }
        }
        s::Constraint::Within{ ref hints, ..} => (old_w, old_h, *hints),
    }
}

#[test]
fn test_constrain(){
    //let hints = s::ConstraintResamplingHints{down_filter: None, up_filter: None, resample_when: None, sharpen_percent: None};
    {
        let constraint = s::Constraint::Within { w: Some(100), h: Some(100), hints: None };
        assert_eq!(constrain(200, 50, &constraint), (100, 25, None));
    }
    {
        let constraint = s::Constraint::Within { w: Some(100), h: Some(100), hints: None };
        assert_eq!(constrain(50, 200, &constraint), (25, 100, None));
    }
    {
        let constraint = s::Constraint::Within { w: Some(640), h: Some(480), hints: None };
        assert_eq!(constrain(200, 50, &constraint), (200, 50, None));
    }
    {
        let constraint = s::Constraint::Within { w: Some(100), h: Some(100), hints: None };
        assert_eq!(constrain(100, 100, &constraint), (100, 100, None));
    }
    {
        let constraint = s::Constraint::Within { w: Some(100), h: Some(100), hints: None };
        assert_eq!(constrain(100, 100, &constraint), (100, 100, None));
    }

}

fn constrain_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.constrain",
        name: "constrain",
        inbound_edges: EdgesIn::OneInput,
        description: "constrain",
        fn_estimate: Some(constrain_size_but_input_format),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                let input = ctx.first_parent_frame_info_some(ix).unwrap();
                let input_w = input.w as u32;
                let input_h = input.h as u32;
                if let s::Node::Constrain(ref constraint) =
                ctx.get_json_params(ix).unwrap() {

                    let (new_w, new_h, hints_val) = constrain(input_w, input_h, constraint);

                    let hints = &hints_val;

                    let resample_when = hints.and_then(|ref h| h.resample_when).unwrap_or(s::ResampleWhen::SizeDiffers);
                    let size_differs = new_w != input_w || new_h != input_h;
                    let sharpen_requested = hints.and_then(|h| h.sharpen_percent).unwrap_or(0f32) > 0f32;

                    let resample = match resample_when{
                        s::ResampleWhen::Always => true,
                        s::ResampleWhen::SizeDiffers if size_differs => true,
                        s::ResampleWhen::SizeDiffersOrSharpeningRequested if size_differs || sharpen_requested => true,
                        _ => false
                    };

                    if resample {
                        let scale2d_params = s::Node::Resample2D {
                            w: new_w as usize,
                            h: new_h as usize,
                            up_filter: hints.and_then(|h| h.up_filter),
                            down_filter: hints.and_then(|h| h.down_filter),
                            hints: hints.map(|h| s::ResampleHints {
                                sharpen_percent: h.sharpen_percent,
                                prefer_1d_twice: None
                            }),
                        };

                        let scale2d = ctx.graph
                            .add_node(Node::new(&super::SCALE,
                                                NodeParams::Json(scale2d_params)));
                        ctx.replace_node_with_existing(ix, scale2d);
                    }else{
                        ctx.delete_node_and_snap_together(ix);
                    }
                }

            }
            f
        }),
        ..Default::default()
    }
}

fn command_string_partially_expanded_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.expanding_command_string",
        name: "expanding_command_string",
        inbound_edges: EdgesIn::OneInput,
        description: "expanding command string",
        fn_estimate: None,
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                let input = ctx.first_parent_frame_info_some(ix).unwrap();

                if let s::Node::CommandString{ref kind, ref value, ref decode, ref encode} =
                ctx.get_json_params(ix).unwrap() {

                    match kind {
                        &s::CommandStringKind::ImageResizer4 => {
                            let url = ::url::Url::from_str(&format!("https://fakeurl/img.jpg?{}", value)).expect("Must be a valid querystring, excluding ?");

                            let (ext, mime) = match (input.fmt, input.alpha_meaningful){
                                (PixelFormat::Bgr24, false) => ("jpg", "image/jpeg"),
                                (PixelFormat::Bgra32, false) => ("jpg", "image/jpeg"),
                                _ => ("png", "image/png")
                            };

                            let (instructions, warnings) = ::imageflow_riapi::ir4::parsing::parse_url(&url);
                            let layout = ::imageflow_riapi::ir4::Ir4Layout::new(
                                s::ImageInfo{
                                    current_frame_index: 0,
                                    frame_count: 1,
                                    frame_decodes_into: input.fmt,
                                    image_height: input.h,
                                    image_width: input.w,
                                    preferred_extension: ext.to_owned(),
                                    preferred_mime_type: mime.to_owned(),
                                },
                                instructions
                            );
                            match layout.produce_steps(None, *encode) {
                                Ok(steps) => {
                                    ctx.replace_node(ix, steps.into_iter().map(|n| Node::from(n)).collect::<>());
                                }
                                Err(e) => {
                                    panic!("{:?} {:?}", e, warnings);
                                }
                            }
                        }
                    }
                }

            }
            f
        }),
        ..Default::default()
    }
}

fn command_string_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.command_string",
        name: "command_string",
        inbound_edges: EdgesIn::OneOptionalInput,
        description: "command string",
        fn_estimate: None,
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                let n = ctx.get_json_params(ix).unwrap();

                if let s::Node::CommandString{ref kind, ref value, ref decode, ref encode} = n.clone() {

                    match kind {
                        &s::CommandStringKind::ImageResizer4 => {

                            let input = ctx.first_parent_frame_info_some(ix);

                            if let &Some(d_id) = decode{
                                if input.is_some(){
                                    panic!("CommandString must either have decode: null or have no parent nodes. Specifying a value for decode creates a new decoder node.");
                                }
                                // TODO: decoder commands should be sourced from Instructions
                                ctx.replace_node(ix, vec![
                                    Node::from(s::Node::Decode {io_id: d_id, commands: None}),
                                    Node::new(&EXPANDING_COMMAND_STRING, NodeParams::Json(n))
                                ]);
                            }else{
                                if input.is_some(){
                                    panic!("CommandString must have a parent node unless 'decode' has a numeric value. Otherwise it has no image source. ");
                                }
                                ctx.replace_node(ix, vec![
                                    Node::new(&EXPANDING_COMMAND_STRING, NodeParams::Json(n))
                                ]);
                            }
                        }
                    }
                }

            }
            f
        }),
        ..Default::default()
    }
}

lazy_static! {
    pub static ref CONSTRAIN: NodeDefinition = constrain_def();
    pub static ref COMMAND_STRING: NodeDefinition = command_string_def();
    pub static ref EXPANDING_COMMAND_STRING: NodeDefinition = command_string_partially_expanded_def();
}
<|endoftext|>


<commit_before><commit_msg>Add check in SolveH for compatible shapes<commit_after><|endoftext|>


<commit_before>use syntax::{
    ast::{self, AstNode},
    match_ast, SyntaxElement, TextRange, TextSize, T,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: remove_dbg
//
// Removes `dbg!()` macro call.
//
// ```
// fn main() {
//     $0dbg!(92);
// }
// ```
// ->
// ```
// fn main() {
//     92;
// }
// ```
pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
    let new_contents = adjusted_macro_contents(&macro_call)?;

    let macro_text_range = macro_call.syntax().text_range();
    let macro_end = if macro_call.semicolon_token().is_some() {
        macro_text_range.end() - TextSize::of(';')
    } else {
        macro_text_range.end()
    };

    acc.add(
        AssistId("remove_dbg", AssistKind::Refactor),
        "Remove dbg!()",
        macro_text_range,
        |builder| {
            builder.replace(TextRange::new(macro_text_range.start(), macro_end), new_contents);
        },
    )
}

fn adjusted_macro_contents(macro_call: &ast::MacroCall) -> Option<String> {
    let contents = get_valid_macrocall_contents(&macro_call, "dbg")?;
    let macro_text_with_brackets = macro_call.token_tree()?.syntax().text();
    let macro_text_in_brackets = macro_text_with_brackets.slice(TextRange::new(
        TextSize::of('('),
        macro_text_with_brackets.len() - TextSize::of(')'),
    ));

    Some(
        if !is_leaf_or_control_flow_expr(macro_call)
            && needs_parentheses_around_macro_contents(contents)
        {
            format!("({})", macro_text_in_brackets)
        } else {
            macro_text_in_brackets.to_string()
        },
    )
}

fn is_leaf_or_control_flow_expr(macro_call: &ast::MacroCall) -> bool {
    macro_call.syntax().next_sibling().is_none()
        || match macro_call.syntax().parent() {
            Some(parent) => match_ast! {
                match parent {
                    ast::Condition(_it) => true,
                    ast::MatchExpr(_it) => true,
                    _ => false,
                }
            },
            None => false,
        }
}

/// Verifies that the given macro_call actually matches the given name
/// and contains proper ending tokens, then returns the contents between the ending tokens
fn get_valid_macrocall_contents(
    macro_call: &ast::MacroCall,
    macro_name: &str,
) -> Option<Vec<SyntaxElement>> {
    let path = macro_call.path()?;
    let name_ref = path.segment()?.name_ref()?;

    // Make sure it is actually a dbg-macro call, dbg followed by !
    let excl = path.syntax().next_sibling_or_token()?;
    if name_ref.text() != macro_name || excl.kind() != T![!] {
        return None;
    }

    let mut children_with_tokens = macro_call.token_tree()?.syntax().children_with_tokens();
    let first_child = children_with_tokens.next()?;
    let mut contents_between_brackets = children_with_tokens.collect::<Vec<_>>();
    let last_child = contents_between_brackets.pop()?;

    match (first_child.kind(), last_child.kind()) {
        (T!['('], T![')']) | (T!['['], T![']']) | (T!['{'], T!['}']) => {
            Some(contents_between_brackets)
        }
        _ => None,
    }
}

fn needs_parentheses_around_macro_contents(macro_contents: Vec<SyntaxElement>) -> bool {
    if macro_contents.len() < 2 {
        return false;
    }
    let mut macro_contents = macro_contents.into_iter().peekable();
    let mut unpaired_brackets_in_contents = Vec::new();
    while let Some(element) = macro_contents.next() {
        match element.kind() {
            T!['('] | T!['['] | T!['{'] => unpaired_brackets_in_contents.push(element),
            T![')'] => {
                if !matches!(unpaired_brackets_in_contents.pop(), Some(correct_bracket) if correct_bracket.kind() == T!['('])
                {
                    return true;
                }
            }
            T![']'] => {
                if !matches!(unpaired_brackets_in_contents.pop(), Some(correct_bracket) if correct_bracket.kind() == T!['['])
                {
                    return true;
                }
            }
            T!['}'] => {
                if !matches!(unpaired_brackets_in_contents.pop(), Some(correct_bracket) if correct_bracket.kind() == T!['{'])
                {
                    return true;
                }
            }
            symbol_kind => {
                let symbol_not_in_bracket = unpaired_brackets_in_contents.is_empty();
                if symbol_not_in_bracket
                    && symbol_kind != T![:] // paths
                    && (symbol_kind != T![.] // field/method access
                        || macro_contents // range expressions consist of two SyntaxKind::Dot in macro invocations
                            .peek()
                            .map(|element| element.kind() == T![.])
                            .unwrap_or(false))
                    && symbol_kind != T![?] // try operator
                    && (symbol_kind.is_punct() || symbol_kind == T![as])
                {
                    return true;
                }
            }
        }
    }
    !unpaired_brackets_in_contents.is_empty()
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    use super::*;

    #[test]
    fn test_remove_dbg() {
        check_assist(remove_dbg, "$0dbg!(1 + 1)", "1 + 1");

        check_assist(remove_dbg, "dbg!$0((1 + 1))", "(1 + 1)");

        check_assist(remove_dbg, "dbg!(1 $0+ 1)", "1 + 1");

        check_assist(remove_dbg, "let _ = $0dbg!(1 + 1)", "let _ = 1 + 1");

        check_assist(
            remove_dbg,
            "
fn foo(n: usize) {
    if let Some(_) = dbg!(n.$0checked_sub(4)) {
        // ...
    }
}
",
            "
fn foo(n: usize) {
    if let Some(_) = n.checked_sub(4) {
        // ...
    }
}
",
        );

        check_assist(remove_dbg, "$0dbg!(Foo::foo_test()).bar()", "Foo::foo_test().bar()");
    }

    #[test]
    fn test_remove_dbg_with_brackets_and_braces() {
        check_assist(remove_dbg, "dbg![$01 + 1]", "1 + 1");
        check_assist(remove_dbg, "dbg!{$01 + 1}", "1 + 1");
    }

    #[test]
    fn test_remove_dbg_not_applicable() {
        check_assist_not_applicable(remove_dbg, "$0vec![1, 2, 3]");
        check_assist_not_applicable(remove_dbg, "$0dbg(5, 6, 7)");
        check_assist_not_applicable(remove_dbg, "$0dbg!(5, 6, 7");
    }

    #[test]
    fn test_remove_dbg_target() {
        check_assist_target(
            remove_dbg,
            "
fn foo(n: usize) {
    if let Some(_) = dbg!(n.$0checked_sub(4)) {
        // ...
    }
}
",
            "dbg!(n.checked_sub(4))",
        );
    }

    #[test]
    fn test_remove_dbg_keep_semicolon() {
        // https://github.com/rust-analyzer/rust-analyzer/issues/5129#issuecomment-651399779
        // not quite though
        // adding a comment at the end of the line makes
        // the ast::MacroCall to include the semicolon at the end
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(1 * 20); // needless comment"#,
            r#"let res = 1 * 20; // needless comment"#,
        );
    }

    #[test]
    fn remove_dbg_from_non_leaf_simple_expression() {
        check_assist(
            remove_dbg,
            "
fn main() {
    let mut a = 1;
    while dbg!$0(a) < 10000 {
        a += 1;
    }
}
",
            "
fn main() {
    let mut a = 1;
    while a < 10000 {
        a += 1;
    }
}
",
        );
    }

    #[test]
    fn test_remove_dbg_keep_expression() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(a + b).foo();"#,
            r#"let res = (a + b).foo();"#,
        );

        check_assist(remove_dbg, r#"let res = $0dbg!(2 + 2) * 5"#, r#"let res = (2 + 2) * 5"#);
        check_assist(remove_dbg, r#"let res = $0dbg![2 + 2] * 5"#, r#"let res = (2 + 2) * 5"#);
    }

    #[test]
    fn test_remove_dbg_method_chaining() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(foo().bar()).baz();"#,
            r#"let res = foo().bar().baz();"#,
        );
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(foo.bar()).baz();"#,
            r#"let res = foo.bar().baz();"#,
        );
    }

    #[test]
    fn test_remove_dbg_field_chaining() {
        check_assist(remove_dbg, r#"let res = $0dbg!(foo.bar).baz;"#, r#"let res = foo.bar.baz;"#);
    }

    #[test]
    fn test_remove_dbg_from_inside_fn() {
        check_assist_target(
            remove_dbg,
            r#"
fn square(x: u32) -> u32 {
    x * x
}

fn main() {
    let x = square(dbg$0!(5 + 10));
    println!("{}", x);
}"#,
            "dbg!(5 + 10)",
        );

        check_assist(
            remove_dbg,
            r#"
fn square(x: u32) -> u32 {
    x * x
}

fn main() {
    let x = square(dbg$0!(5 + 10));
    println!("{}", x);
}"#,
            r#"
fn square(x: u32) -> u32 {
    x * x
}

fn main() {
    let x = square(5 + 10);
    println!("{}", x);
}"#,
        );
    }

    #[test]
    fn test_remove_dbg_try_expr() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(result?).foo();"#,
            r#"let res = result?.foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_await_expr() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(fut.await).foo();"#,
            r#"let res = fut.await.foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_as_cast() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(3 as usize).foo();"#,
            r#"let res = (3 as usize).foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_index_expr() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(array[3]).foo();"#,
            r#"let res = array[3].foo();"#,
        );
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(tuple.3).foo();"#,
            r#"let res = tuple.3.foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_range_expr() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(foo..bar).foo();"#,
            r#"let res = (foo..bar).foo();"#,
        );
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(foo..=bar).foo();"#,
            r#"let res = (foo..=bar).foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_followed_by_block() {
        check_assist(
            remove_dbg,
            r#"fn foo() {
    if $0dbg!(x || y) {}
}"#,
            r#"fn foo() {
    if x || y {}
}"#,
        );
        check_assist(
            remove_dbg,
            r#"fn foo() {
    while let foo = $0dbg!(&x) {}
}"#,
            r#"fn foo() {
    while let foo = &x {}
}"#,
        );
        check_assist(
            remove_dbg,
            r#"fn foo() {
    if let foo = $0dbg!(&x) {}
}"#,
            r#"fn foo() {
    if let foo = &x {}
}"#,
        );
        check_assist(
            remove_dbg,
            r#"fn foo() {
    match $0dbg!(&x) {}
}"#,
            r#"fn foo() {
    match &x {}
}"#,
        );
    }

    #[test]
    fn test_remove_empty_dbg() {
        check_assist(remove_dbg, r#"$0dbg!()"#, r#""#);
    }
}
<commit_msg>Remove dbg expression and newline as whole<commit_after>use syntax::{
    ast::{self, AstNode, AstToken},
    match_ast, SyntaxElement, TextRange, TextSize, T,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: remove_dbg
//
// Removes `dbg!()` macro call.
//
// ```
// fn main() {
//     $0dbg!(92);
// }
// ```
// ->
// ```
// fn main() {
//     92;
// }
// ```
pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
    let new_contents = adjusted_macro_contents(&macro_call)?;

    let macro_text_range = if new_contents.is_empty() {
        let parent = macro_call.syntax().parent()?;

        let start = parent
            .prev_sibling_or_token()
            .and_then(|el| {
                Some(el.into_token().and_then(ast::Whitespace::cast)?.syntax().text_range().start())
            })
            .unwrap_or(parent.text_range().start());
        let end = parent.text_range().end();

        TextRange::new(start, end)
    } else {
        macro_call.syntax().text_range()
    };

    let macro_end = match macro_call.semicolon_token() {
        Some(_) => macro_text_range.end() - TextSize::of(';'),
        None => macro_text_range.end(),
    };

    acc.add(
        AssistId("remove_dbg", AssistKind::Refactor),
        "Remove dbg!()",
        macro_text_range,
        |builder| {
            builder.replace(TextRange::new(macro_text_range.start(), macro_end), new_contents);
        },
    )
}

fn adjusted_macro_contents(macro_call: &ast::MacroCall) -> Option<String> {
    let contents = get_valid_macrocall_contents(&macro_call, "dbg")?;
    let macro_text_with_brackets = macro_call.token_tree()?.syntax().text();
    let macro_text_in_brackets = macro_text_with_brackets.slice(TextRange::new(
        TextSize::of('('),
        macro_text_with_brackets.len() - TextSize::of(')'),
    ));

    Some(
        if !is_leaf_or_control_flow_expr(macro_call)
            && needs_parentheses_around_macro_contents(contents)
        {
            format!("({})", macro_text_in_brackets)
        } else {
            macro_text_in_brackets.to_string()
        },
    )
}

fn is_leaf_or_control_flow_expr(macro_call: &ast::MacroCall) -> bool {
    macro_call.syntax().next_sibling().is_none()
        || match macro_call.syntax().parent() {
            Some(parent) => match_ast! {
                match parent {
                    ast::Condition(_it) => true,
                    ast::MatchExpr(_it) => true,
                    _ => false,
                }
            },
            None => false,
        }
}

/// Verifies that the given macro_call actually matches the given name
/// and contains proper ending tokens, then returns the contents between the ending tokens
fn get_valid_macrocall_contents(
    macro_call: &ast::MacroCall,
    macro_name: &str,
) -> Option<Vec<SyntaxElement>> {
    let path = macro_call.path()?;
    let name_ref = path.segment()?.name_ref()?;

    // Make sure it is actually a dbg-macro call, dbg followed by !
    let excl = path.syntax().next_sibling_or_token()?;
    if name_ref.text() != macro_name || excl.kind() != T![!] {
        return None;
    }

    let mut children_with_tokens = macro_call.token_tree()?.syntax().children_with_tokens();
    let first_child = children_with_tokens.next()?;
    let mut contents_between_brackets = children_with_tokens.collect::<Vec<_>>();
    let last_child = contents_between_brackets.pop()?;

    match (first_child.kind(), last_child.kind()) {
        (T!['('], T![')']) | (T!['['], T![']']) | (T!['{'], T!['}']) => {
            Some(contents_between_brackets)
        }
        _ => None,
    }
}

fn needs_parentheses_around_macro_contents(macro_contents: Vec<SyntaxElement>) -> bool {
    if macro_contents.len() < 2 {
        return false;
    }
    let mut macro_contents = macro_contents.into_iter().peekable();
    let mut unpaired_brackets_in_contents = Vec::new();
    while let Some(element) = macro_contents.next() {
        match element.kind() {
            T!['('] | T!['['] | T!['{'] => unpaired_brackets_in_contents.push(element),
            T![')'] => {
                if !matches!(unpaired_brackets_in_contents.pop(), Some(correct_bracket) if correct_bracket.kind() == T!['('])
                {
                    return true;
                }
            }
            T![']'] => {
                if !matches!(unpaired_brackets_in_contents.pop(), Some(correct_bracket) if correct_bracket.kind() == T!['['])
                {
                    return true;
                }
            }
            T!['}'] => {
                if !matches!(unpaired_brackets_in_contents.pop(), Some(correct_bracket) if correct_bracket.kind() == T!['{'])
                {
                    return true;
                }
            }
            symbol_kind => {
                let symbol_not_in_bracket = unpaired_brackets_in_contents.is_empty();
                if symbol_not_in_bracket
                    && symbol_kind != T![:] // paths
                    && (symbol_kind != T![.] // field/method access
                        || macro_contents // range expressions consist of two SyntaxKind::Dot in macro invocations
                            .peek()
                            .map(|element| element.kind() == T![.])
                            .unwrap_or(false))
                    && symbol_kind != T![?] // try operator
                    && (symbol_kind.is_punct() || symbol_kind == T![as])
                {
                    return true;
                }
            }
        }
    }
    !unpaired_brackets_in_contents.is_empty()
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    use super::*;

    #[test]
    fn test_remove_dbg() {
        check_assist(remove_dbg, "$0dbg!(1 + 1)", "1 + 1");

        check_assist(remove_dbg, "dbg!$0((1 + 1))", "(1 + 1)");

        check_assist(remove_dbg, "dbg!(1 $0+ 1)", "1 + 1");

        check_assist(remove_dbg, "let _ = $0dbg!(1 + 1)", "let _ = 1 + 1");

        check_assist(
            remove_dbg,
            "
fn foo(n: usize) {
    if let Some(_) = dbg!(n.$0checked_sub(4)) {
        // ...
    }
}
",
            "
fn foo(n: usize) {
    if let Some(_) = n.checked_sub(4) {
        // ...
    }
}
",
        );

        check_assist(remove_dbg, "$0dbg!(Foo::foo_test()).bar()", "Foo::foo_test().bar()");
    }

    #[test]
    fn test_remove_dbg_with_brackets_and_braces() {
        check_assist(remove_dbg, "dbg![$01 + 1]", "1 + 1");
        check_assist(remove_dbg, "dbg!{$01 + 1}", "1 + 1");
    }

    #[test]
    fn test_remove_dbg_not_applicable() {
        check_assist_not_applicable(remove_dbg, "$0vec![1, 2, 3]");
        check_assist_not_applicable(remove_dbg, "$0dbg(5, 6, 7)");
        check_assist_not_applicable(remove_dbg, "$0dbg!(5, 6, 7");
    }

    #[test]
    fn test_remove_dbg_target() {
        check_assist_target(
            remove_dbg,
            "
fn foo(n: usize) {
    if let Some(_) = dbg!(n.$0checked_sub(4)) {
        // ...
    }
}
",
            "dbg!(n.checked_sub(4))",
        );
    }

    #[test]
    fn test_remove_dbg_keep_semicolon() {
        // https://github.com/rust-analyzer/rust-analyzer/issues/5129#issuecomment-651399779
        // not quite though
        // adding a comment at the end of the line makes
        // the ast::MacroCall to include the semicolon at the end
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(1 * 20); // needless comment"#,
            r#"let res = 1 * 20; // needless comment"#,
        );
    }

    #[test]
    fn remove_dbg_from_non_leaf_simple_expression() {
        check_assist(
            remove_dbg,
            "
fn main() {
    let mut a = 1;
    while dbg!$0(a) < 10000 {
        a += 1;
    }
}
",
            "
fn main() {
    let mut a = 1;
    while a < 10000 {
        a += 1;
    }
}
",
        );
    }

    #[test]
    fn test_remove_dbg_keep_expression() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(a + b).foo();"#,
            r#"let res = (a + b).foo();"#,
        );

        check_assist(remove_dbg, r#"let res = $0dbg!(2 + 2) * 5"#, r#"let res = (2 + 2) * 5"#);
        check_assist(remove_dbg, r#"let res = $0dbg![2 + 2] * 5"#, r#"let res = (2 + 2) * 5"#);
    }

    #[test]
    fn test_remove_dbg_method_chaining() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(foo().bar()).baz();"#,
            r#"let res = foo().bar().baz();"#,
        );
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(foo.bar()).baz();"#,
            r#"let res = foo.bar().baz();"#,
        );
    }

    #[test]
    fn test_remove_dbg_field_chaining() {
        check_assist(remove_dbg, r#"let res = $0dbg!(foo.bar).baz;"#, r#"let res = foo.bar.baz;"#);
    }

    #[test]
    fn test_remove_dbg_from_inside_fn() {
        check_assist_target(
            remove_dbg,
            r#"
fn square(x: u32) -> u32 {
    x * x
}

fn main() {
    let x = square(dbg$0!(5 + 10));
    println!("{}", x);
}"#,
            "dbg!(5 + 10)",
        );

        check_assist(
            remove_dbg,
            r#"
fn square(x: u32) -> u32 {
    x * x
}

fn main() {
    let x = square(dbg$0!(5 + 10));
    println!("{}", x);
}"#,
            r#"
fn square(x: u32) -> u32 {
    x * x
}

fn main() {
    let x = square(5 + 10);
    println!("{}", x);
}"#,
        );
    }

    #[test]
    fn test_remove_dbg_try_expr() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(result?).foo();"#,
            r#"let res = result?.foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_await_expr() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(fut.await).foo();"#,
            r#"let res = fut.await.foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_as_cast() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(3 as usize).foo();"#,
            r#"let res = (3 as usize).foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_index_expr() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(array[3]).foo();"#,
            r#"let res = array[3].foo();"#,
        );
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(tuple.3).foo();"#,
            r#"let res = tuple.3.foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_range_expr() {
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(foo..bar).foo();"#,
            r#"let res = (foo..bar).foo();"#,
        );
        check_assist(
            remove_dbg,
            r#"let res = $0dbg!(foo..=bar).foo();"#,
            r#"let res = (foo..=bar).foo();"#,
        );
    }

    #[test]
    fn test_remove_dbg_followed_by_block() {
        check_assist(
            remove_dbg,
            r#"fn foo() {
    if $0dbg!(x || y) {}
}"#,
            r#"fn foo() {
    if x || y {}
}"#,
        );
        check_assist(
            remove_dbg,
            r#"fn foo() {
    while let foo = $0dbg!(&x) {}
}"#,
            r#"fn foo() {
    while let foo = &x {}
}"#,
        );
        check_assist(
            remove_dbg,
            r#"fn foo() {
    if let foo = $0dbg!(&x) {}
}"#,
            r#"fn foo() {
    if let foo = &x {}
}"#,
        );
        check_assist(
            remove_dbg,
            r#"fn foo() {
    match $0dbg!(&x) {}
}"#,
            r#"fn foo() {
    match &x {}
}"#,
        );
    }

    #[test]
    fn test_remove_empty_dbg() {
        check_assist(remove_dbg, r#"fn foo() { $0dbg!(); }"#, r#"fn foo() { }"#);
        check_assist(
            remove_dbg,
            r#"fn foo() {
$0dbg!();
}"#,
            r#"fn foo() {
}"#,
        );
    }
}
<|endoftext|>


<commit_before>extern crate scroll;

use scroll::{ctx, Pread, BE};

#[derive(Debug)]
struct Data<'a> {
    name: &'a str,
    id: u32,
}

#[derive(Debug, Clone, Copy, Default)]
struct DataCtx {
    pub size: usize,
    pub endian: scroll::Endian
}

impl<'a> ctx::TryFromCtx<'a, (usize, DataCtx)> for Data<'a> {
    type Error = scroll::Error;
    fn try_from_ctx (src: &'a [u8], (offset, DataCtx {size, endian}): (usize, DataCtx))
                     -> Result<Self, Self::Error> {
        let name = src.pread_slice::<str>(offset, size)?;
        let id = src.pread_with(offset+size, endian)?;
        Ok(Data { name: name, id: id })
    }
}

fn main() {
    let bytes = b"UserName\x01\x02\x03\x04";
    let data = bytes.pread_with::<Data>(0, DataCtx { size: 8, endian: BE }).unwrap();
    assert_eq!(data.id, 0x01020304);
    assert_eq!(data.name.to_string(), "UserName".to_string());
    println!("Data: {:?}", &data);
}
<commit_msg>remove pread_slice from example<commit_after>extern crate scroll;

use scroll::{ctx, Endian, Pread, BE};

#[derive(Debug)]
struct Data<'a> {
    name: &'a str,
    id: u32,
}

impl<'a> ctx::TryFromCtx<'a, (usize, Endian)> for Data<'a> {
    type Error = scroll::Error;
    fn try_from_ctx (src: &'a [u8], (offset, endian): (usize, Endian))
                     -> Result<Self, Self::Error> {
        let name = src.pread::<&'a str>(offset)?;
        let id = src.pread_with(offset+name.len(), endian)?;
        Ok(Data { name: name, id: id })
    }
}

fn main() {
    let bytes = b"UserName\x01\x02\x03\x04\x00";
    let data = bytes.pread_with::<Data>(0, BE).unwrap();
    assert_eq!(data.id, 0x01020304);
    assert_eq!(data.name.to_string(), "UserName".to_string());
    println!("Data: {:?}", &data);
}
<|endoftext|>


<commit_before>extern mod glfw;

fn main() {
    glfw::set_error_callback(error_callback);

    do glfw::spawn {

        glfw::window_hint(glfw::VISIBLE, glfw::TRUE);

        let window = glfw::Window::create(640, 480, "Defaults", glfw::Windowed).unwrap();

        window.make_context_current();

        let (width, height) = window.get_size();
        io::println(fmt!("window size: %? x %?", width, height));

        io::println(fmt!("Context version major: %?",     window.get_param(glfw::CONTEXT_VERSION_MAJOR)));
        io::println(fmt!("Context version minor: %?",     window.get_param(glfw::CONTEXT_VERSION_MINOR)));
        io::println(fmt!("OpenGL forward compatible: %?", window.get_param(glfw::OPENGL_FORWARD_COMPAT)));
        io::println(fmt!("OpenGL debug context: %?",      window.get_param(glfw::OPENGL_DEBUG_CONTEXT)));
        io::println(fmt!("OpenGL profile: %?",            window.get_param(glfw::OPENGL_PROFILE)));

        // TODO: Test OpenGL defaults:
        //   - GL_RED_BITS
        //   - GL_GREEN_BITS
        //   - GL_BLUE_BITS
        //   - GL_ALPHA_BITS
        //   - GL_DEPTH_BITS
        //   - GL_STENCIL_BITS
        //   - GL_STEREO
        //   - GL_SAMPLES_ARB
    }
}

fn error_callback(_error: libc::c_int, description: ~str) {
    io::println(fmt!("GLFW Error: %s", description));
}<commit_msg>Add OpenGL parameter checks to 'defaults' example<commit_after>extern mod glfw;

fn error_callback(_error: libc::c_int, description: ~str) {
    io::println(fmt!("GLFW Error: %s", description));
}

fn main() {
    glfw::set_error_callback(error_callback);

    do glfw::spawn {

        glfw::window_hint(glfw::VISIBLE, glfw::TRUE);

        let window = glfw::Window::create(640, 480, "Defaults", glfw::Windowed).unwrap();

        window.make_context_current();

        let (width, height) = window.get_size();
        io::println(fmt!("window size: %? x %?", width, height));

        println(fmt!("Context version major: %?",     window.get_param(glfw::CONTEXT_VERSION_MAJOR)));
        println(fmt!("Context version minor: %?",     window.get_param(glfw::CONTEXT_VERSION_MINOR)));
        println(fmt!("OpenGL forward compatible: %?", window.get_param(glfw::OPENGL_FORWARD_COMPAT)));
        println(fmt!("OpenGL debug context: %?",      window.get_param(glfw::OPENGL_DEBUG_CONTEXT)));
        println(fmt!("OpenGL profile: %?",            window.get_param(glfw::OPENGL_PROFILE)));

        let gl_params = [
            (gl::RED_BITS,          None,   "red bits"          ),
            (gl::GREEN_BITS,        None,   "green bits"        ),
            (gl::BLUE_BITS,         None,   "blue bits"         ),
            (gl::ALPHA_BITS,        None,   "alpha bits"        ),
            (gl::DEPTH_BITS,        None,   "depth bits"        ),
            (gl::STENCIL_BITS,      None,   "stencil bits"      ),
            (gl::ACCUM_RED_BITS,    None,   "accum red bits"    ),
            (gl::ACCUM_GREEN_BITS,  None,   "accum green bits"  ),
            (gl::ACCUM_BLUE_BITS,   None,   "accum blue bits"   ),
            (gl::ACCUM_ALPHA_BITS,  None,   "accum alpha bits"  ),
            (gl::STEREO,            None,   "stereo"            ),
            (gl::SAMPLES_ARB,       Some("GL_ARB_multisample"), "FSAA samples" ),
        ];

        for gl_params.each |&p| {
            let (param, ext, name) = p;

            if do ext.map_default(true) |&s| {
                glfw::extension_supported(s)
            } {
                let mut value = 0;
                unsafe { gl::GetIntegerv(param, &value); }

                println(fmt!("OpenGL %s: %?", name, value));
            };
        }
    }
}

mod gl {
    #[nolink]
    #[link_args="-framework OpenGL"]
    #[cfg(target_os = "macos")]
    extern mod linkhack {}

    #[nolink]
    #[link_args="-lGL"]
    #[cfg(target_os = "linux")]
    extern mod linkhack {}

    pub type GLenum = libc::c_uint;
    pub type GLint  = libc::c_int;

    pub static RED_BITS              : GLenum = 0x0D52;
    pub static GREEN_BITS            : GLenum = 0x0D53;
    pub static BLUE_BITS             : GLenum = 0x0D54;
    pub static ALPHA_BITS            : GLenum = 0x0D55;
    pub static DEPTH_BITS            : GLenum = 0x0D56;
    pub static STENCIL_BITS          : GLenum = 0x0D57;
    pub static ACCUM_RED_BITS        : GLenum = 0x0D58;
    pub static ACCUM_GREEN_BITS      : GLenum = 0x0D59;
    pub static ACCUM_BLUE_BITS       : GLenum = 0x0D5A;
    pub static ACCUM_ALPHA_BITS      : GLenum = 0x0D5B;
    pub static STEREO                : GLenum = 0x0C33;
    pub static SAMPLES_ARB           : GLenum = 0x80A9;

    pub extern "C" {
        #[link_name="glGetIntegerv"]
        pub fn GetIntegerv(pname: GLenum, params: *GLint);
    }
}<|endoftext|>


<commit_before>use frontend::input;
use app::constants::*;
use core::geometry::*;
use core::clock::Seconds;
use core::view::ViewTransform;
use core::view::WorldTransform;
use app::constants::DEAD_ZONE;
use super::events::VectorDirection;
use super::events::Event;

pub struct DefaultController {}

pub trait InputController {
	fn update<V, W, I>(input_state: &I, view_transform: &V, world_transform: &W, dt: Seconds) -> Vec<Event>
		where V: ViewTransform, W: WorldTransform, I: input::InputRead;
}

impl InputController for DefaultController {
	fn update<V, W, I>(input_state: &I, view_transform: &V, world_transform: &W, dt: Seconds) -> Vec<Event>
		where V: ViewTransform, W: WorldTransform, I: input::InputRead {
		let mut events = Vec::new();

		macro_rules! on_key_held {
			[$($key:ident -> $app_event:ident),*] => (
				$(if input_state.key_pressed(input::Key::$key) { events.push(Event::$app_event); })
				*
			);
			[$($key:ident -> $app_event:ident($app_args:expr)),*] => (
				$(if input_state.key_pressed(input::Key::$key) { events.push(Event::$app_event($app_args)); })
				*
			)

		}
		macro_rules! on_key_pressed_once {
			[$($key:ident -> $app_event:ident),*] => (
				$(if input_state.key_once(input::Key::$key) { events.push(Event::$app_event); })
				*
			)
		}

		on_key_held![
			W -> CamUp(1.),
			S -> CamDown(1.),
			A -> CamLeft(1.),
			D -> CamRight(1.)
		];

		on_key_pressed_once![
			F5 -> Reload,
			F1 -> ToggleGui,
			GamepadL3 -> ToggleGui,
			N0 -> CamReset,
			Home -> CamReset,
			KpHome -> CamReset,
			GamepadDPadUp -> ZoomIn,
			GamepadDPadDown -> ZoomOut,
			GamepadR3 -> ZoomReset,
			Plus -> ZoomIn,
			Minus -> ZoomOut,
			N1 -> ZoomReset,
			F6 -> SaveGenePoolToFile,
			F7 -> SaveWorldToFile,
			F8 -> RestartFromCheckpoint,
			F10 -> ToggleDebug,
			GamepadStart -> ToggleDebug,
			Z -> DeselectAll,
			L -> NextLight,
			B -> NextBackground,
			K -> PrevLight,
			V -> PrevBackground,
			G -> PrevSpeedFactor,
			GamepadL1 -> PrevSpeedFactor,
			H -> NextSpeedFactor,
			GamepadR1 -> NextSpeedFactor,
			P -> TogglePause,
			Esc -> AppQuit,
			MouseScrollUp -> ZoomIn,
			MouseScrollDown -> ZoomOut
		];

		let mouse_window_pos = input_state.mouse_position();
		let mouse_view_pos = view_transform.to_view(mouse_window_pos);
		let mouse_world_pos = world_transform.to_world(mouse_view_pos);

		let mouse_left_pressed = input_state.key_pressed(input::Key::MouseLeft) && !input_state.any_ctrl_pressed();
		if input_state.key_once(input::Key::MouseLeft) && input_state.any_ctrl_pressed() {
			events.push(Event::PickMinion(mouse_world_pos));
		};

		let firerate = input_state.gamepad_axis(0, input::Axis::L2);
		let firepower = input_state.gamepad_axis(0, input::Axis::R2);
		if firepower >= DEAD_ZONE {
			events.push(Event::PrimaryTrigger(firepower, firerate as f64));
		} else {
			if input_state.key_pressed(input::Key::Space) ||
				mouse_left_pressed {
				events.push(Event::PrimaryTrigger(1.0, 1.0));
			}
		}
		let thrust = Position {
			x: if input_state.key_pressed(input::Key::Right) {
				1.
			} else if input_state.key_pressed(input::Key::Left) {
				-1.
			} else {
				input_state.gamepad_axis(0, input::Axis::LStickX)
			},

			y: if input_state.key_pressed(input::Key::Up) {
				1.
			} else if input_state.key_pressed(input::Key::Down) {
				-1.
			} else {
				input_state.gamepad_axis(0, input::Axis::LStickY)
			},
		};

		let yaw = Position {
			x: input_state.gamepad_axis(0, input::Axis::RStickX),
			y: input_state.gamepad_axis(0, input::Axis::RStickY),
		};

		use cgmath::InnerSpace;
		let magnitude = thrust.magnitude2();
		events.push(Event::VectorThrust(
			if magnitude >= DEAD_ZONE {
				Some(thrust / magnitude.max(1.))
			} else {
				None
			},
			if input_state.key_pressed(input::Key::PageUp) {
				VectorDirection::Turn(TURN_SPEED)
			} else if input_state.key_pressed(input::Key::PageDown) {
				VectorDirection::Turn(-TURN_SPEED)
			} else if yaw.magnitude() >= DEAD_ZONE {
				VectorDirection::Orientation(yaw)
			} else if mouse_left_pressed {
				VectorDirection::LookAt(mouse_world_pos)
			} else if thrust.magnitude2() > 0.1 {
				VectorDirection::FromVelocity
			} else {
				VectorDirection::None
			}));
		if input_state.key_once(input::Key::MouseMiddle) {
			if input_state.any_ctrl_pressed() {
				events.push(Event::RandomizeMinion(mouse_world_pos));
			} else {
				events.push(Event::NewMinion(mouse_world_pos));
			}
		}

		match input_state.dragging() {
			input::Dragging::Begin(_, from) => {
				let from = world_transform.to_world(from);
				events.push(Event::BeginDrag(from, from));
			}
			input::Dragging::Dragging(_, from, to) => {
				events.push(Event::Drag(world_transform.to_world(from), world_transform.to_world(to)));
			}
			input::Dragging::End(_, from, to, prev) => {
				let mouse_vel = (view_transform.to_view(prev) - to) / dt.into();
				events.push(Event::EndDrag(
					world_transform.to_world(from),
					world_transform.to_world(to),
					mouse_vel,
				));
			}
			_ => {}
		}
		events
	}
}
<commit_msg>Gamepad start/options pauses<commit_after>use frontend::input;
use app::constants::*;
use core::geometry::*;
use core::clock::Seconds;
use core::view::ViewTransform;
use core::view::WorldTransform;
use app::constants::DEAD_ZONE;
use super::events::VectorDirection;
use super::events::Event;

pub struct DefaultController {}

pub trait InputController {
	fn update<V, W, I>(input_state: &I, view_transform: &V, world_transform: &W, dt: Seconds) -> Vec<Event>
		where V: ViewTransform, W: WorldTransform, I: input::InputRead;
}

impl InputController for DefaultController {
	fn update<V, W, I>(input_state: &I, view_transform: &V, world_transform: &W, dt: Seconds) -> Vec<Event>
		where V: ViewTransform, W: WorldTransform, I: input::InputRead {
		let mut events = Vec::new();

		macro_rules! on_key_held {
			[$($key:ident -> $app_event:ident),*] => (
				$(if input_state.key_pressed(input::Key::$key) { events.push(Event::$app_event); })
				*
			);
			[$($key:ident -> $app_event:ident($app_args:expr)),*] => (
				$(if input_state.key_pressed(input::Key::$key) { events.push(Event::$app_event($app_args)); })
				*
			)

		}
		macro_rules! on_key_pressed_once {
			[$($key:ident -> $app_event:ident),*] => (
				$(if input_state.key_once(input::Key::$key) { events.push(Event::$app_event); })
				*
			)
		}

		on_key_held![
			W -> CamUp(1.),
			S -> CamDown(1.),
			A -> CamLeft(1.),
			D -> CamRight(1.)
		];

		on_key_pressed_once![
			F5 -> Reload,
			F1 -> ToggleGui,
			GamepadL3 -> ToggleGui,
			N0 -> CamReset,
			Home -> CamReset,
			GamepadStart -> TogglePause,
			KpHome -> CamReset,
			GamepadDPadUp -> ZoomIn,
			GamepadDPadDown -> ZoomOut,
			GamepadR3 -> ZoomReset,
			Plus -> ZoomIn,
			Minus -> ZoomOut,
			N1 -> ZoomReset,
			F6 -> SaveGenePoolToFile,
			F7 -> SaveWorldToFile,
			F8 -> RestartFromCheckpoint,
			F10 -> ToggleDebug,
			GamepadStart -> ToggleDebug,
			Z -> DeselectAll,
			L -> NextLight,
			B -> NextBackground,
			K -> PrevLight,
			V -> PrevBackground,
			G -> PrevSpeedFactor,
			GamepadL1 -> PrevSpeedFactor,
			H -> NextSpeedFactor,
			GamepadR1 -> NextSpeedFactor,
			P -> TogglePause,
			Esc -> AppQuit,
			MouseScrollUp -> ZoomIn,
			MouseScrollDown -> ZoomOut
		];

		let mouse_window_pos = input_state.mouse_position();
		let mouse_view_pos = view_transform.to_view(mouse_window_pos);
		let mouse_world_pos = world_transform.to_world(mouse_view_pos);

		let mouse_left_pressed = input_state.key_pressed(input::Key::MouseLeft) && !input_state.any_ctrl_pressed();
		if input_state.key_once(input::Key::MouseLeft) && input_state.any_ctrl_pressed() {
			events.push(Event::PickMinion(mouse_world_pos));
		};

		let firerate = input_state.gamepad_axis(0, input::Axis::L2);
		let firepower = input_state.gamepad_axis(0, input::Axis::R2);
		if firepower >= DEAD_ZONE {
			events.push(Event::PrimaryTrigger(firepower, firerate as f64));
		} else {
			if input_state.key_pressed(input::Key::Space) ||
				mouse_left_pressed {
				events.push(Event::PrimaryTrigger(1.0, 1.0));
			}
		}
		let thrust = Position {
			x: if input_state.key_pressed(input::Key::Right) {
				1.
			} else if input_state.key_pressed(input::Key::Left) {
				-1.
			} else {
				input_state.gamepad_axis(0, input::Axis::LStickX)
			},

			y: if input_state.key_pressed(input::Key::Up) {
				1.
			} else if input_state.key_pressed(input::Key::Down) {
				-1.
			} else {
				input_state.gamepad_axis(0, input::Axis::LStickY)
			},
		};

		let yaw = Position {
			x: input_state.gamepad_axis(0, input::Axis::RStickX),
			y: input_state.gamepad_axis(0, input::Axis::RStickY),
		};

		use cgmath::InnerSpace;
		let magnitude = thrust.magnitude2();
		events.push(Event::VectorThrust(
			if magnitude >= DEAD_ZONE {
				Some(thrust / magnitude.max(1.))
			} else {
				None
			},
			if input_state.key_pressed(input::Key::PageUp) {
				VectorDirection::Turn(TURN_SPEED)
			} else if input_state.key_pressed(input::Key::PageDown) {
				VectorDirection::Turn(-TURN_SPEED)
			} else if yaw.magnitude() >= DEAD_ZONE {
				VectorDirection::Orientation(yaw)
			} else if mouse_left_pressed {
				VectorDirection::LookAt(mouse_world_pos)
			} else if thrust.magnitude2() > 0.1 {
				VectorDirection::FromVelocity
			} else {
				VectorDirection::None
			}));
		if input_state.key_once(input::Key::MouseMiddle) {
			if input_state.any_ctrl_pressed() {
				events.push(Event::RandomizeMinion(mouse_world_pos));
			} else {
				events.push(Event::NewMinion(mouse_world_pos));
			}
		}

		match input_state.dragging() {
			input::Dragging::Begin(_, from) => {
				let from = world_transform.to_world(from);
				events.push(Event::BeginDrag(from, from));
			}
			input::Dragging::Dragging(_, from, to) => {
				events.push(Event::Drag(world_transform.to_world(from), world_transform.to_world(to)));
			}
			input::Dragging::End(_, from, to, prev) => {
				let mouse_vel = (view_transform.to_view(prev) - to) / dt.into();
				events.push(Event::EndDrag(
					world_transform.to_world(from),
					world_transform.to_world(to),
					mouse_vel,
				));
			}
			_ => {}
		}
		events
	}
}
<|endoftext|>


<commit_before>use super::*;
use {Signature, Path, Message, ffi};
use std::marker::PhantomData;
use std::{ptr, mem, any, fmt};
use super::check;
use std::ffi::{CString};
use std::os::raw::{c_void, c_int};

// Map DBus-Type -> Alignment. Copied from _dbus_marshal_write_fixed_multi in
// http://dbus.freedesktop.org/doc/api/html/dbus-marshal-basic_8c_source.html#l01020
// Note that Rust booleans are one byte, dbus booleans are four bytes!
const FIXED_ARRAY_ALIGNMENTS: [(ArgType, usize); 9] = [
    (ArgType::Byte, 1),
    (ArgType::Int16, 2),
    (ArgType::UInt16, 2),
    (ArgType::UInt32, 4),
    (ArgType::Int32, 4),
    (ArgType::Boolean, 4),
    (ArgType::Int64, 8),
    (ArgType::UInt64, 8),
    (ArgType::Double, 8)
];

/// Represents a D-Bus array.
impl<'a, T: Arg> Arg for &'a [T] {
    fn arg_type() -> ArgType { ArgType::Array }
    fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
}

fn array_append<T: Arg, F: FnMut(&T, &mut IterAppend)>(z: &[T], i: &mut IterAppend, mut f: F) {
    let zptr = z.as_ptr();
    let zlen = z.len() as i32;

    // Can we do append_fixed_array?
    let a = (T::arg_type(), mem::size_of::<T>());
    let can_fixed_array = (zlen > 1) && (z.len() == zlen as usize) && FIXED_ARRAY_ALIGNMENTS.iter().any(|&v| v == a);

    i.append_container(ArgType::Array, Some(T::signature().as_cstr()), |s|
        if can_fixed_array { unsafe { check("dbus_message_iter_append_fixed_array",
            ffi::dbus_message_iter_append_fixed_array(&mut s.0, a.0 as c_int, &zptr as *const _ as *const c_void, zlen)) }}
        else { for arg in z { f(arg, s); }}
    );
}

/// Appends a D-Bus array. Note: In case you have a large array of a type that implements FixedArray,
/// using this method will be more efficient than using an Array.
impl<'a, T: Arg + Append + Clone> Append for &'a [T] {
    fn append(self, i: &mut IterAppend) {
        array_append(self, i, |arg, s| arg.clone().append(s));
    }
}

impl<'a, T: Arg + RefArg> RefArg for &'a [T] {
    fn arg_type(&self) -> ArgType { ArgType::Array }
    fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
    fn append(&self, i: &mut IterAppend) {
        array_append(self, i, |arg, s| (arg as &RefArg).append(s));
    }
    fn as_any(&self) -> &any::Any where Self: 'static { self }
}

impl<T: Arg + RefArg> RefArg for Vec<T> {
    fn arg_type(&self) -> ArgType { ArgType::Array }
    fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
    fn append(&self, i: &mut IterAppend) {
        array_append(&self, i, |arg, s| (arg as &RefArg).append(s));
    }
    fn as_any(&self) -> &any::Any where Self: 'static { self }
}

impl<'a, T: FixedArray> Get<'a> for &'a [T] {
    fn get(i: &mut Iter<'a>) -> Option<&'a [T]> {
        debug_assert!(FIXED_ARRAY_ALIGNMENTS.iter().any(|&v| v == (T::arg_type(), mem::size_of::<T>())));
        i.recurse(Self::arg_type()).and_then(|mut si| unsafe {
            if ffi::dbus_message_iter_get_arg_type(&mut si.0) != T::arg_type() as c_int { return None };

            let mut v = ptr::null_mut();
            let mut i = 0;
            ffi::dbus_message_iter_get_fixed_array(&mut si.0, &mut v as *mut _ as *mut c_void, &mut i);
            Some(::std::slice::from_raw_parts(v, i as usize))
        })
    }
}

#[derive(Copy, Clone, Debug)]
/// Append a D-Bus dict type (i e, an array of dict entries).
pub struct Dict<'a, K: DictKey, V: Arg, I>(I, PhantomData<(&'a Message, *const K, *const V)>);

impl<'a, K: DictKey, V: Arg, I> Dict<'a, K, V, I> {
    fn entry_sig() -> String { format!("{{{}{}}}", K::signature(), V::signature()) }
}

impl<'a, K: 'a + DictKey, V: 'a + Append + Arg, I: Iterator<Item=(K, V)>> Dict<'a, K, V, I> {
    /// Creates a new Dict from an iterator. The iterator is consumed when appended.
    pub fn new<J: IntoIterator<IntoIter=I, Item=(K, V)>>(j: J) -> Dict<'a, K, V, I> { Dict(j.into_iter(), PhantomData) }
}

impl<'a, K: DictKey, V: Arg, I> Arg for Dict<'a, K, V, I> {
    fn arg_type() -> ArgType { ArgType::Array }
    fn signature() -> Signature<'static> {
        Signature::from(format!("a{}", Self::entry_sig())) }
}

impl<'a, K: 'a + DictKey + Append, V: 'a + Append + Arg, I: Iterator<Item=(K, V)>> Append for Dict<'a, K, V, I> {
    fn append(self, i: &mut IterAppend) {
        let z = self.0;
        i.append_container(Self::arg_type(), Some(&CString::new(Self::entry_sig()).unwrap()), |s| for (k, v) in z {
            s.append_container(ArgType::DictEntry, None, |ss| {
                k.append(ss);
                v.append(ss);
            })
        });
    }
}

impl<'a, K: DictKey + Get<'a>, V: Arg + Get<'a>> Get<'a> for Dict<'a, K, V, Iter<'a>> {
    fn get(i: &mut Iter<'a>) -> Option<Self> {
        i.recurse(Self::arg_type()).map(|si| Dict(si, PhantomData))
        // TODO: Verify full element signature?
    }
}

impl<'a, K: DictKey + Get<'a>, V: Arg + Get<'a>> Iterator for Dict<'a, K, V, Iter<'a>> {
    type Item = (K, V);
    fn next(&mut self) -> Option<(K, V)> {
        let i = self.0.recurse(ArgType::DictEntry).and_then(|mut si| {
            let k = si.get();
            if k.is_none() { return None };
            assert!(si.next());
            let v = si.get();
            if v.is_none() { return None };
            Some((k.unwrap(), v.unwrap()))
        });
        self.0.next();
        i
    }
}

#[derive(Copy, Clone, Debug)]
/// Represents a D-Bus Array. Maximum flexibility (wraps an iterator of items to append).
/// Note: Slices of FixedArray can be faster.
pub struct Array<'a, T, I>(I, PhantomData<(*const T, &'a Message)>);

impl<'a, T: 'a, I: Iterator<Item=T>> Array<'a, T, I> {
    /// Creates a new Array from an iterator. The iterator is consumed when appending.
    pub fn new<J: IntoIterator<IntoIter=I, Item=T>>(j: J) -> Array<'a, T, I> { Array(j.into_iter(), PhantomData) }
}

impl<'a, T: Arg, I> Arg for Array<'a, T, I> {
    fn arg_type() -> ArgType { ArgType::Array }
    fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
}

impl<'a, T: 'a + Arg + Append, I: Iterator<Item=T>> Append for Array<'a, T, I> {
    fn append(self, i: &mut IterAppend) {
        let z = self.0;
        i.append_container(ArgType::Array, Some(T::signature().as_cstr()), |s| for arg in z { arg.append(s) });
    }
}

impl<'a, T: Arg + Get<'a>> Get<'a> for Array<'a, T, Iter<'a>> {
    fn get(i: &mut Iter<'a>) -> Option<Array<'a, T, Iter<'a>>> {
        i.recurse(Self::arg_type()).map(|si| Array(si, PhantomData))
        // TODO: Verify full element signature?
    }
}

impl<'a, T: Get<'a>> Iterator for Array<'a, T, Iter<'a>> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        let i = self.0.get();
        self.0.next();
        i
    }
}

// Due to the strong typing here; RefArg is implemented only for T's that are both Arg and RefArg.
// We need Arg for this to work for empty arrays (we can't get signature from first element if there is no elements).
// We need RefArg for non-consuming append.
impl<'a, T: 'a + Arg + fmt::Debug + RefArg, I: fmt::Debug + Clone + Iterator<Item=&'a T>> RefArg for Array<'static, T, I> {
    fn arg_type(&self) -> ArgType { ArgType::Array }
    fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
    fn append(&self, i: &mut IterAppend) {
        let z = self.0.clone();
        i.append_container(ArgType::Array, Some(<T as Arg>::signature().as_cstr()), |s|
            for arg in z { (arg as &RefArg).append(s) }
        );
    }
    fn as_any(&self) -> &any::Any where Self: 'static { self }
}

fn get_fixed_array_refarg<'a, T: FixedArray + Clone + RefArg>(i: &mut Iter<'a>) -> Box<RefArg> {
    let s = <&[T]>::get(i).unwrap();
    Box::new(s.to_vec())
}

fn get_var_array_refarg<'a, T: 'static + RefArg + Arg, F: FnMut(&mut Iter<'a>) -> Option<T>>
    (i: &mut Iter<'a>, mut f: F) -> Box<RefArg> {
    let mut v: Vec<T> = vec!(); // dbus_message_iter_get_element_count might be O(n), better not use it
    let mut si = i.recurse(ArgType::Array).unwrap();
    while let Some(q) = f(&mut si) { v.push(q); si.next(); }
    Box::new(v)
}

pub fn get_array_refarg<'a>(i: &mut Iter<'a>) -> Box<RefArg> {
    debug_assert!(i.arg_type() == ArgType::Array);
    let etype = ArgType::from_i32(unsafe { ffi::dbus_message_iter_get_element_type(&mut i.0) } as i32).unwrap();
    match etype {
        ArgType::Byte => get_fixed_array_refarg::<u8>(i),
        ArgType::Int16 => get_fixed_array_refarg::<i16>(i),
        ArgType::UInt16 => get_fixed_array_refarg::<u16>(i),
        ArgType::Int32 => get_fixed_array_refarg::<i32>(i),
        ArgType::UInt32 => get_fixed_array_refarg::<u32>(i),
        ArgType::Int64 => get_fixed_array_refarg::<i64>(i),
        ArgType::UInt64 => get_fixed_array_refarg::<u64>(i),
        ArgType::Double => get_fixed_array_refarg::<f64>(i),
	ArgType::String => get_var_array_refarg::<String, _>(i, |si| si.get()),
	ArgType::ObjectPath => get_var_array_refarg::<Path<'static>, _>(i, |si| si.get::<Path>().map(|s| s.into_static())),
	ArgType::Signature => get_var_array_refarg::<Signature<'static>, _>(i, |si| si.get::<Signature>().map(|s| s.into_static())),
	ArgType::Variant => get_var_array_refarg::<Variant<Box<RefArg>>, _>(i, |si| Variant::new_refarg(si)),
	ArgType::Boolean => get_var_array_refarg::<bool, _>(i, |si| si.get()),
	ArgType::Invalid => panic!("Array with Invalid ArgType"),
        _ => unimplemented!(),
    }
}

<commit_msg>Fix bug with empty fixed arrays<commit_after>use super::*;
use {Signature, Path, Message, ffi};
use std::marker::PhantomData;
use std::{ptr, mem, any, fmt};
use super::check;
use std::ffi::{CString};
use std::os::raw::{c_void, c_int};

// Map DBus-Type -> Alignment. Copied from _dbus_marshal_write_fixed_multi in
// http://dbus.freedesktop.org/doc/api/html/dbus-marshal-basic_8c_source.html#l01020
// Note that Rust booleans are one byte, dbus booleans are four bytes!
const FIXED_ARRAY_ALIGNMENTS: [(ArgType, usize); 9] = [
    (ArgType::Byte, 1),
    (ArgType::Int16, 2),
    (ArgType::UInt16, 2),
    (ArgType::UInt32, 4),
    (ArgType::Int32, 4),
    (ArgType::Boolean, 4),
    (ArgType::Int64, 8),
    (ArgType::UInt64, 8),
    (ArgType::Double, 8)
];

/// Represents a D-Bus array.
impl<'a, T: Arg> Arg for &'a [T] {
    fn arg_type() -> ArgType { ArgType::Array }
    fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
}

fn array_append<T: Arg, F: FnMut(&T, &mut IterAppend)>(z: &[T], i: &mut IterAppend, mut f: F) {
    let zptr = z.as_ptr();
    let zlen = z.len() as i32;

    // Can we do append_fixed_array?
    let a = (T::arg_type(), mem::size_of::<T>());
    let can_fixed_array = (zlen > 1) && (z.len() == zlen as usize) && FIXED_ARRAY_ALIGNMENTS.iter().any(|&v| v == a);

    i.append_container(ArgType::Array, Some(T::signature().as_cstr()), |s|
        if can_fixed_array { unsafe { check("dbus_message_iter_append_fixed_array",
            ffi::dbus_message_iter_append_fixed_array(&mut s.0, a.0 as c_int, &zptr as *const _ as *const c_void, zlen)) }}
        else { for arg in z { f(arg, s); }}
    );
}

/// Appends a D-Bus array. Note: In case you have a large array of a type that implements FixedArray,
/// using this method will be more efficient than using an Array.
impl<'a, T: Arg + Append + Clone> Append for &'a [T] {
    fn append(self, i: &mut IterAppend) {
        array_append(self, i, |arg, s| arg.clone().append(s));
    }
}

impl<'a, T: Arg + RefArg> RefArg for &'a [T] {
    fn arg_type(&self) -> ArgType { ArgType::Array }
    fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
    fn append(&self, i: &mut IterAppend) {
        array_append(self, i, |arg, s| (arg as &RefArg).append(s));
    }
    fn as_any(&self) -> &any::Any where Self: 'static { self }
}

impl<T: Arg + RefArg> RefArg for Vec<T> {
    fn arg_type(&self) -> ArgType { ArgType::Array }
    fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
    fn append(&self, i: &mut IterAppend) {
        array_append(&self, i, |arg, s| (arg as &RefArg).append(s));
    }
    fn as_any(&self) -> &any::Any where Self: 'static { self }
}

impl<'a, T: FixedArray> Get<'a> for &'a [T] {
    fn get(i: &mut Iter<'a>) -> Option<&'a [T]> {
        debug_assert!(FIXED_ARRAY_ALIGNMENTS.iter().any(|&v| v == (T::arg_type(), mem::size_of::<T>())));
        i.recurse(Self::arg_type()).and_then(|mut si| unsafe {
            let etype = ffi::dbus_message_iter_get_element_type(&mut i.0);

            if etype != T::arg_type() as c_int { return None };

            let mut v = ptr::null_mut();
            let mut i = 0;
            ffi::dbus_message_iter_get_fixed_array(&mut si.0, &mut v as *mut _ as *mut c_void, &mut i);
            if v == ptr::null_mut() {
                assert_eq!(i, 0);
                Some(&[][..])
            } else {
                Some(::std::slice::from_raw_parts(v, i as usize))
            }
        })
    }
}

#[derive(Copy, Clone, Debug)]
/// Append a D-Bus dict type (i e, an array of dict entries).
pub struct Dict<'a, K: DictKey, V: Arg, I>(I, PhantomData<(&'a Message, *const K, *const V)>);

impl<'a, K: DictKey, V: Arg, I> Dict<'a, K, V, I> {
    fn entry_sig() -> String { format!("{{{}{}}}", K::signature(), V::signature()) }
}

impl<'a, K: 'a + DictKey, V: 'a + Append + Arg, I: Iterator<Item=(K, V)>> Dict<'a, K, V, I> {
    /// Creates a new Dict from an iterator. The iterator is consumed when appended.
    pub fn new<J: IntoIterator<IntoIter=I, Item=(K, V)>>(j: J) -> Dict<'a, K, V, I> { Dict(j.into_iter(), PhantomData) }
}

impl<'a, K: DictKey, V: Arg, I> Arg for Dict<'a, K, V, I> {
    fn arg_type() -> ArgType { ArgType::Array }
    fn signature() -> Signature<'static> {
        Signature::from(format!("a{}", Self::entry_sig())) }
}

impl<'a, K: 'a + DictKey + Append, V: 'a + Append + Arg, I: Iterator<Item=(K, V)>> Append for Dict<'a, K, V, I> {
    fn append(self, i: &mut IterAppend) {
        let z = self.0;
        i.append_container(Self::arg_type(), Some(&CString::new(Self::entry_sig()).unwrap()), |s| for (k, v) in z {
            s.append_container(ArgType::DictEntry, None, |ss| {
                k.append(ss);
                v.append(ss);
            })
        });
    }
}

impl<'a, K: DictKey + Get<'a>, V: Arg + Get<'a>> Get<'a> for Dict<'a, K, V, Iter<'a>> {
    fn get(i: &mut Iter<'a>) -> Option<Self> {
        i.recurse(Self::arg_type()).map(|si| Dict(si, PhantomData))
        // TODO: Verify full element signature?
    }
}

impl<'a, K: DictKey + Get<'a>, V: Arg + Get<'a>> Iterator for Dict<'a, K, V, Iter<'a>> {
    type Item = (K, V);
    fn next(&mut self) -> Option<(K, V)> {
        let i = self.0.recurse(ArgType::DictEntry).and_then(|mut si| {
            let k = si.get();
            if k.is_none() { return None };
            assert!(si.next());
            let v = si.get();
            if v.is_none() { return None };
            Some((k.unwrap(), v.unwrap()))
        });
        self.0.next();
        i
    }
}

#[derive(Copy, Clone, Debug)]
/// Represents a D-Bus Array. Maximum flexibility (wraps an iterator of items to append).
/// Note: Slices of FixedArray can be faster.
pub struct Array<'a, T, I>(I, PhantomData<(*const T, &'a Message)>);

impl<'a, T: 'a, I: Iterator<Item=T>> Array<'a, T, I> {
    /// Creates a new Array from an iterator. The iterator is consumed when appending.
    pub fn new<J: IntoIterator<IntoIter=I, Item=T>>(j: J) -> Array<'a, T, I> { Array(j.into_iter(), PhantomData) }
}

impl<'a, T: Arg, I> Arg for Array<'a, T, I> {
    fn arg_type() -> ArgType { ArgType::Array }
    fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
}

impl<'a, T: 'a + Arg + Append, I: Iterator<Item=T>> Append for Array<'a, T, I> {
    fn append(self, i: &mut IterAppend) {
        let z = self.0;
        i.append_container(ArgType::Array, Some(T::signature().as_cstr()), |s| for arg in z { arg.append(s) });
    }
}

impl<'a, T: Arg + Get<'a>> Get<'a> for Array<'a, T, Iter<'a>> {
    fn get(i: &mut Iter<'a>) -> Option<Array<'a, T, Iter<'a>>> {
        i.recurse(Self::arg_type()).map(|si| Array(si, PhantomData))
        // TODO: Verify full element signature?
    }
}

impl<'a, T: Get<'a>> Iterator for Array<'a, T, Iter<'a>> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        let i = self.0.get();
        self.0.next();
        i
    }
}

// Due to the strong typing here; RefArg is implemented only for T's that are both Arg and RefArg.
// We need Arg for this to work for empty arrays (we can't get signature from first element if there is no elements).
// We need RefArg for non-consuming append.
impl<'a, T: 'a + Arg + fmt::Debug + RefArg, I: fmt::Debug + Clone + Iterator<Item=&'a T>> RefArg for Array<'static, T, I> {
    fn arg_type(&self) -> ArgType { ArgType::Array }
    fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
    fn append(&self, i: &mut IterAppend) {
        let z = self.0.clone();
        i.append_container(ArgType::Array, Some(<T as Arg>::signature().as_cstr()), |s|
            for arg in z { (arg as &RefArg).append(s) }
        );
    }
    fn as_any(&self) -> &any::Any where Self: 'static { self }
}

fn get_fixed_array_refarg<'a, T: FixedArray + Clone + RefArg>(i: &mut Iter<'a>) -> Box<RefArg> {
    let s = <&[T]>::get(i).unwrap();
    Box::new(s.to_vec())
}

fn get_var_array_refarg<'a, T: 'static + RefArg + Arg, F: FnMut(&mut Iter<'a>) -> Option<T>>
    (i: &mut Iter<'a>, mut f: F) -> Box<RefArg> {
    let mut v: Vec<T> = vec!(); // dbus_message_iter_get_element_count might be O(n), better not use it
    let mut si = i.recurse(ArgType::Array).unwrap();
    while let Some(q) = f(&mut si) { v.push(q); si.next(); }
    Box::new(v)
}

pub fn get_array_refarg<'a>(i: &mut Iter<'a>) -> Box<RefArg> {
    debug_assert!(i.arg_type() == ArgType::Array);
    let etype = ArgType::from_i32(unsafe { ffi::dbus_message_iter_get_element_type(&mut i.0) } as i32).unwrap();
    match etype {
        ArgType::Byte => get_fixed_array_refarg::<u8>(i),
        ArgType::Int16 => get_fixed_array_refarg::<i16>(i),
        ArgType::UInt16 => get_fixed_array_refarg::<u16>(i),
        ArgType::Int32 => get_fixed_array_refarg::<i32>(i),
        ArgType::UInt32 => get_fixed_array_refarg::<u32>(i),
        ArgType::Int64 => get_fixed_array_refarg::<i64>(i),
        ArgType::UInt64 => get_fixed_array_refarg::<u64>(i),
        ArgType::Double => get_fixed_array_refarg::<f64>(i),
	ArgType::String => get_var_array_refarg::<String, _>(i, |si| si.get()),
	ArgType::ObjectPath => get_var_array_refarg::<Path<'static>, _>(i, |si| si.get::<Path>().map(|s| s.into_static())),
	ArgType::Signature => get_var_array_refarg::<Signature<'static>, _>(i, |si| si.get::<Signature>().map(|s| s.into_static())),
	ArgType::Variant => get_var_array_refarg::<Variant<Box<RefArg>>, _>(i, |si| Variant::new_refarg(si)),
	ArgType::Boolean => get_var_array_refarg::<bool, _>(i, |si| si.get()),
	ArgType::Invalid => panic!("Array with Invalid ArgType"),
        // Unfortunately, we need to get an Array of Arrays as if it were an Array of structs.
        // Otherwise, we'll get type explosion. :-(
        ArgType::Array => Box::new(i.recurse(ArgType::Array).unwrap().collect::<Vec<_>>()),
        ArgType::DictEntry => unimplemented!(),
        ArgType::UnixFd => unimplemented!(),
        ArgType::Struct => Box::new(i.recurse(ArgType::Array).unwrap().collect::<Vec<_>>()),
    }
}

<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;

use super::super::config::Config;
use super::super::helpers::oauth2client;
use super::super::results::{BearerResult, BearerError};

pub fn command(config_dir: &str, client_name: &str) -> BearerResult<()> {
    debug!("Display authorization header for client {} in directory {}",
           client_name,
           config_dir);

    let mut conf = Config::from_file(config_dir, client_name)?;

    let update = match conf.expired() {
        Some(true) => {
            debug!("Refreshing Token");
            match conf.refresh_token() {
                Some(rtoken) => {
                    let tokens = oauth2client::from_refresh_token(&conf.client(), rtoken)?;
                    Some(tokens)
                }
                None => {
                    return Err(BearerError::ValueError("Client must be initialized. (No Refresh \
                                                        Tokens)"
                        .to_string()))
                }
            }
        }
        Some(false) => {
            debug!("Access Token Is OK");
            None
        }
        None => {
            error!("TODO: Command to reregister client implement yet");
            return Err(BearerError::ValueError("Client must be initialized".to_string()));
        }
    };

    if let Some(new_tokens) = update {
        conf.set_tokens(new_tokens);
        conf.write()?;
    }

    print!("Authorization: Bearer {}", conf.access_token().unwrap());
    io::stdout().flush().unwrap();

    Ok(())
}
<commit_msg>Fix spacing in string<commit_after>use std::io;
use std::io::prelude::*;

use super::super::config::Config;
use super::super::helpers::oauth2client;
use super::super::results::{BearerResult, BearerError};

pub fn command(config_dir: &str, client_name: &str) -> BearerResult<()> {
    debug!("Display authorization header for client {} in directory {}",
           client_name,
           config_dir);

    let mut conf = Config::from_file(config_dir, client_name)?;

    let update = match conf.expired() {
        Some(true) => {
            debug!("Refreshing Token");
            match conf.refresh_token() {
                Some(rtoken) => {
                    let tokens = oauth2client::from_refresh_token(&conf.client(), rtoken)?;
                    Some(tokens)
                }
                None => {
                    return Err(BearerError::ValueError("Client must be refreshed. (No Refresh \
 Token)".to_string()))
                }
            }
        }
        Some(false) => {
            debug!("Access Token Is OK");
            None
        }
        None => {
            error!("TODO: Command to reregister client implement yet");
            return Err(BearerError::ValueError("Client must be initialized".to_string()));
        }
    };

    if let Some(new_tokens) = update {
        conf.set_tokens(new_tokens);
        conf.write()?;
    }

    print!("Authorization: Bearer {}", conf.access_token().unwrap());
    io::stdout().flush().unwrap();

    Ok(())
}
<|endoftext|>


<commit_before>#[link(name     = "sphere4d"
       , vers   = "0.0"
       , author = "Sébastien Crozet"
       , uuid   = "cf8cfe5d-18ca-40cb-b596-d8790090a56d")];
#[crate_type = "bin"];
#[warn(non_camel_case_types)]

extern mod nalgebra;
extern mod ncollide;
extern mod nrays;

use std::io::buffered::BufferedWriter;
use std::io::fs::File;
use std::rand::Rng;
use std::rand;
use nalgebra::na::{Iso3, Iso4, Vec2, Vec3, Vec4, Mat4, Inv};
use nalgebra::na;
use ncollide::ray::Ray;
use ncollide::geom::{Ball, Box};
use nrays::scene_node::SceneNode;
use nrays::material::Material4d;
use nrays::normal_material::NormalMaterial;
use nrays::phong_material::PhongMaterial;
use nrays::reflective_material::ReflectiveMaterial;
use nrays::scene::Scene;
use nrays::light::Light;

fn main() {
    let eye        = Vec4::new(0.0f64, 0.0, 0.0, 0.0);
    let at         = Vec4::new(0.0f64, 0.0, 0.0, 1.0);
    let resolution = Vec3::new(100.0f64, 100.0, 100.0);

    let mut lights = ~[];

    {
        lights.push(Light::new(Vec4::new(10.0f64, -10.0, 10.0, 10.0),
                               Vec3::new(1.0, 1.0, 1.0)));
    }

    let blue = @PhongMaterial::new(
        Vec3::new(0.0, 0.0, 1.0),
        Vec3::new(0.0, 0.0, 1.0),
        0.0,
        0.0,
        1.0,
        100.0
    ) as Material4d<f64>;

    let transform: Iso4<f64> = na::one();

    let ball = @Box::new_with_margin(Vec4::new(5.0, 5.0, 5.0, 1.0), 0.0);

    let pos = na::append_translation(&transform, &Vec4::new(50.0, 50.0, 50.0, 1.0));

    let mut nodes = ~[];
    nodes.push(@SceneNode::new(~[blue], pos, ball));

    let scene = Scene::new(nodes, lights);
    let pixels = do scene.render(&resolution) |pt| {
        // Ray::new(eye, na::normalize(&(Vec4::new(pt.x, pt.y, pt.z, 1.0) - eye)))
        Ray::new(Vec4::new(pt.x, pt.y, pt.z, 0.0), na::normalize(&(Vec4::new(pt.x, pt.y, pt.z, 1.0) - eye)))
    };

    let path = "out.4d";
    let mut file = File::create(&Path::new(path)).expect("Cannot create the file: " + path);
    // let mut file = BufferedWriter::new(file);
    pixels.to_file(&mut file);
}
<commit_msg>Change the 4d example to be more interesting.<commit_after>#[link(name     = "sphere4d"
       , vers   = "0.0"
       , author = "Sébastien Crozet"
       , uuid   = "cf8cfe5d-18ca-40cb-b596-d8790090a56d")];
#[crate_type = "bin"];
#[warn(non_camel_case_types)]

extern mod nalgebra;
extern mod ncollide;
extern mod nrays;

use std::io::buffered::BufferedWriter;
use std::io::fs::File;
use std::rand::Rng;
use std::rand;
use nalgebra::na::{Iso3, Iso4, Vec2, Vec3, Vec4, Mat4, Inv};
use nalgebra::na;
use ncollide::ray::Ray;
use ncollide::geom::{Ball, Box, Plane, Cone, Cylinder};
use nrays::scene_node::SceneNode;
use nrays::material::Material4d;
use nrays::normal_material::NormalMaterial;
use nrays::phong_material::PhongMaterial;
use nrays::reflective_material::ReflectiveMaterial;
use nrays::scene::Scene;
use nrays::light::Light;

fn main() {
    let eye        = Vec4::new(0.0f64, 0.0, 0.0, 0.0);
    let at         = Vec4::new(0.0f64, 0.0, 0.0, 1.0);
    let resolution = Vec3::new(100.0f64, 100.0, 100.0);

    let mut lights = ~[];

    {
        lights.push(Light::new(Vec4::new(10.0f64, -10.0, 10.0, 1.0),
                               Vec3::new(1.0, 1.0, 1.0)));
        lights.push(Light::new(Vec4::new(-10.0f64, -10.0, 10.0, 1.0),
                               Vec3::new(1.0, 1.0, 1.0)));
        lights.push(Light::new(Vec4::new(10.0f64, 10.0, 10.0, 1.0),
                               Vec3::new(1.0, 1.0, 1.0)));
        lights.push(Light::new(Vec4::new(-10.0f64, 10.0, 10.0, 1.0),
                               Vec3::new(1.0, 1.0, 1.0)));
    }

    let refl = @ReflectiveMaterial::new(0.2) as Material4d<f64>;
    let blue = @PhongMaterial::new(
        Vec3::new(1.0, 1.0, 1.0),
        Vec3::new(1.0, 1.0, 1.0),
        0.6,
        0.0,
        0.4,
        100.0
    ) as Material4d<f64>;
    let white = @PhongMaterial::new(
        Vec3::new(1.0, 1.0, 1.0),
        Vec3::new(1.0, 1.0, 1.0),
        0.0,
        0.0,
        1.0,
        100.0
    ) as Material4d<f64>;

    let transform: Iso4<f64> = na::one();

    let box      = @Box::new_with_margin(Vec4::new(0.25, 0.25, 0.25, 0.25), 0.0);
    let ball     = @Ball::new(0.25);
    let cone     = @Cone::new_with_margin(0.25, 0.25, 0.0);
    let cylinder = @Cylinder::new_with_margin(0.25, 0.25, 0.0);
    let plane    = @Plane::new(Vec4::new(0.0, 0.0, 0.0, -1.0));

    let pos  = na::append_translation(&transform, &Vec4::new(0.0, 0.0, 0.0,    4.0));
    let pos2 = na::append_translation(&transform, &Vec4::new(0.75, 0.75, 0.0,  4.0));
    let pos3 = na::append_translation(&transform, &Vec4::new(0.0, 0.75, 0.75,  4.0));
    let pos4 = na::append_translation(&transform, &Vec4::new(0.0, 0.75, -0.75, 4.0));

    let mut nodes = ~[];
    nodes.push(@SceneNode::new(~[refl, blue], pos,  ball));
    nodes.push(@SceneNode::new(~[refl, blue], pos2, box));
    nodes.push(@SceneNode::new(~[refl, blue], pos3, cone));
    nodes.push(@SceneNode::new(~[refl, blue], pos4, cylinder));
    // nodes.push(@SceneNode::new(~[white],  na::append_translation(&transform, &Vec4::new(0.0f64, 0.0f64, 0.0, 4.0)), plane));

    let scene = Scene::new(nodes, lights);
    let pixels = do scene.render(&resolution) |pt| {
        let x = (pt.x / resolution.x - 0.5) * 2.0;
        let y = (pt.y / resolution.y - 0.5) * 2.0;
        let z = (pt.z / resolution.z - 0.5) * 2.0;
        // Ray::new(eye, na::normalize(&(Vec4::new(pt.x, pt.y, pt.z, 1.0) - eye)))

        Ray::new(Vec4::new(x, y, z, 0.0), Vec4::new(0.0, 0.0, 0.0, 1.0))
    };

    let path = "out.4d";
    let mut file = File::create(&Path::new(path)).expect("Cannot create the file: " + path);
    // let mut file = BufferedWriter::new(file);
    pixels.to_file(&mut file);
}
<|endoftext|>