<commit_before>//! `ra_assits` crate provides a bunch of code assists, aslo known as code
//! actions (in LSP) or intentions (in IntelliJ).
//!
//! An assist is a micro-refactoring, which is automatically activated in
//! certain context. For example, if the cursor is over `,`, a "swap `,`" assist
//! becomes available.

mod assist_ctx;

use ra_text_edit::TextEdit;
use ra_syntax::{TextRange, TextUnit, SyntaxNode, Direction};
use ra_db::FileRange;
use hir::db::HirDatabase;

pub(crate) use crate::assist_ctx::{AssistCtx, Assist};

#[derive(Debug)]
pub struct AssistLabel {
    /// Short description of the assist, as shown in the UI.
    pub label: String,
}

pub struct AssistAction {
    pub edit: TextEdit,
    pub cursor_position: Option<TextUnit>,
    pub target: Option<TextRange>,
}

/// Return all the assists applicable at the given position.
///
/// Assists are returned in the "unresolved" state, that is only labels are
/// returned, without actual edits.
pub fn applicable_assists<H>(db: &H, range: FileRange) -> Vec<AssistLabel>
where
    H: HirDatabase + 'static,
{
    AssistCtx::with_ctx(db, range, false, |ctx| {
        all_assists()
            .iter()
            .filter_map(|f| f(ctx.clone()))
            .map(|a| match a {
                Assist::Unresolved(label) => label,
                Assist::Resolved(..) => unreachable!(),
            })
            .collect()
    })
}

/// Return all the assists applicable at the given position.
///
/// Assists are returned in the "resolved" state, that is with edit fully
/// computed.
pub fn assists<H>(db: &H, range: FileRange) -> Vec<(AssistLabel, AssistAction)>
where
    H: HirDatabase + 'static,
{
    use std::cmp::Ordering;

    AssistCtx::with_ctx(db, range, true, |ctx| {
        let mut a = all_assists()
            .iter()
            .filter_map(|f| f(ctx.clone()))
            .map(|a| match a {
                Assist::Resolved(label, action) => (label, action),
                Assist::Unresolved(..) => unreachable!(),
            })
            .collect::<Vec<(AssistLabel, AssistAction)>>();
        a.sort_by(|a, b| match a {
            // Some(y) < Some(x) < None for y < x
            (_, AssistAction { target: Some(a), .. }) => match b {
                (_, AssistAction { target: Some(b), .. }) => a.len().cmp(&b.len()),
                _ => Ordering::Less,
            },
            _ => Ordering::Greater,
        });
        a
    })
}

mod add_derive;
mod add_impl;
mod flip_comma;
mod change_visibility;
mod fill_match_arms;
mod introduce_variable;
mod replace_if_let_with_match;
mod split_import;
mod remove_dbg;
fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] {
    &[
        add_derive::add_derive,
        add_impl::add_impl,
        change_visibility::change_visibility,
        fill_match_arms::fill_match_arms,
        flip_comma::flip_comma,
        introduce_variable::introduce_variable,
        replace_if_let_with_match::replace_if_let_with_match,
        split_import::split_import,
        remove_dbg::remove_dbg,
    ]
}

fn non_trivia_sibling(node: &SyntaxNode, direction: Direction) -> Option<&SyntaxNode> {
    node.siblings(direction).skip(1).find(|node| !node.kind().is_trivia())
}

#[cfg(test)]
mod helpers {
    use hir::mock::MockDatabase;
    use ra_syntax::TextRange;
    use ra_db::FileRange;
    use test_utils::{extract_offset, extract_range, assert_eq_text, add_cursor};

    use crate::{AssistCtx, Assist};

    pub(crate) fn check_assist(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
        after: &str,
    ) {
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assist =
            AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
        let action = match assist {
            Assist::Unresolved(_) => unreachable!(),
            Assist::Resolved(_, it) => it,
        };

        let actual = action.edit.apply(&before);
        let actual_cursor_pos = match action.cursor_position {
            None => action
                .edit
                .apply_to_offset(before_cursor_pos)
                .expect("cursor position is affected by the edit"),
            Some(off) => off,
        };
        let actual = add_cursor(&actual, actual_cursor_pos);
        assert_eq_text!(after, &actual);
    }

    pub(crate) fn check_assist_range(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
        after: &str,
    ) {
        let (range, before) = extract_range(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange = FileRange { file_id, range };
        let assist =
            AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
        let action = match assist {
            Assist::Unresolved(_) => unreachable!(),
            Assist::Resolved(_, it) => it,
        };

        let mut actual = action.edit.apply(&before);
        if let Some(pos) = action.cursor_position {
            actual = add_cursor(&actual, pos);
        }
        assert_eq_text!(after, &actual);
    }

    pub(crate) fn check_assist_target(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
        target: &str,
    ) {
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assist =
            AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
        let action = match assist {
            Assist::Unresolved(_) => unreachable!(),
            Assist::Resolved(_, it) => it,
        };

        let range = action.target.expect("expected target on action");
        assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target);
    }

    pub(crate) fn check_assist_range_target(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
        target: &str,
    ) {
        let (range, before) = extract_range(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange = FileRange { file_id, range };
        let assist =
            AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
        let action = match assist {
            Assist::Unresolved(_) => unreachable!(),
            Assist::Resolved(_, it) => it,
        };

        let range = action.target.expect("expected target on action");
        assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target);
    }

    pub(crate) fn check_assist_not_applicable(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
    ) {
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assist = AssistCtx::with_ctx(&db, frange, true, assist);
        assert!(assist.is_none());
    }
}

#[cfg(test)]
mod tests {
    use hir::mock::MockDatabase;
    use ra_syntax::TextRange;
    use ra_db::FileRange;
    use test_utils::{extract_offset};

    #[test]
    fn assist_order_field_struct() {
        let before = "struct Foo { <|>bar: u32 }";
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assists = super::assists(&db, frange);
        let mut assists = assists.iter();

        assert_eq!(assists.next().expect("expected assist").0.label, "make pub(crate)");
        assert_eq!(assists.next().expect("expected assist").0.label, "add `#[derive]`");
    }

    #[test]
    fn assist_order_if_expr() {
        let before = "
        pub fn test_some_range(a: int) -> bool {
            if let 2..6 = 5<|> {
                true
            } else {
                false
            }
        }";
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assists = super::assists(&db, frange);
        let mut assists = assists.iter();

        assert_eq!(assists.next().expect("expected assist").0.label, "introduce variable");
        assert_eq!(assists.next().expect("expected assist").0.label, "replace with match");
    }

}
<commit_msg>Improve sorting delegate<commit_after>//! `ra_assits` crate provides a bunch of code assists, aslo known as code
//! actions (in LSP) or intentions (in IntelliJ).
//!
//! An assist is a micro-refactoring, which is automatically activated in
//! certain context. For example, if the cursor is over `,`, a "swap `,`" assist
//! becomes available.

mod assist_ctx;

use ra_text_edit::TextEdit;
use ra_syntax::{TextRange, TextUnit, SyntaxNode, Direction};
use ra_db::FileRange;
use hir::db::HirDatabase;

pub(crate) use crate::assist_ctx::{AssistCtx, Assist};

#[derive(Debug)]
pub struct AssistLabel {
    /// Short description of the assist, as shown in the UI.
    pub label: String,
}

pub struct AssistAction {
    pub edit: TextEdit,
    pub cursor_position: Option<TextUnit>,
    pub target: Option<TextRange>,
}

/// Return all the assists applicable at the given position.
///
/// Assists are returned in the "unresolved" state, that is only labels are
/// returned, without actual edits.
pub fn applicable_assists<H>(db: &H, range: FileRange) -> Vec<AssistLabel>
where
    H: HirDatabase + 'static,
{
    AssistCtx::with_ctx(db, range, false, |ctx| {
        all_assists()
            .iter()
            .filter_map(|f| f(ctx.clone()))
            .map(|a| match a {
                Assist::Unresolved(label) => label,
                Assist::Resolved(..) => unreachable!(),
            })
            .collect()
    })
}

/// Return all the assists applicable at the given position.
///
/// Assists are returned in the "resolved" state, that is with edit fully
/// computed.
pub fn assists<H>(db: &H, range: FileRange) -> Vec<(AssistLabel, AssistAction)>
where
    H: HirDatabase + 'static,
{
    use std::cmp::Ordering;

    AssistCtx::with_ctx(db, range, true, |ctx| {
        let mut a = all_assists()
            .iter()
            .filter_map(|f| f(ctx.clone()))
            .map(|a| match a {
                Assist::Resolved(label, action) => (label, action),
                Assist::Unresolved(..) => unreachable!(),
            })
            .collect::<Vec<(AssistLabel, AssistAction)>>();
        a.sort_by(|a, b| match (a.1.target, b.1.target) {
            (Some(a), Some(b)) => a.len().cmp(&b.len()),
            (Some(_), None) => Ordering::Less,
            (None, Some(_)) => Ordering::Greater,
            (None, None) => Ordering::Equal,
        });
        a
    })
}

mod add_derive;
mod add_impl;
mod flip_comma;
mod change_visibility;
mod fill_match_arms;
mod introduce_variable;
mod replace_if_let_with_match;
mod split_import;
mod remove_dbg;
fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] {
    &[
        add_derive::add_derive,
        add_impl::add_impl,
        change_visibility::change_visibility,
        fill_match_arms::fill_match_arms,
        flip_comma::flip_comma,
        introduce_variable::introduce_variable,
        replace_if_let_with_match::replace_if_let_with_match,
        split_import::split_import,
        remove_dbg::remove_dbg,
    ]
}

fn non_trivia_sibling(node: &SyntaxNode, direction: Direction) -> Option<&SyntaxNode> {
    node.siblings(direction).skip(1).find(|node| !node.kind().is_trivia())
}

#[cfg(test)]
mod helpers {
    use hir::mock::MockDatabase;
    use ra_syntax::TextRange;
    use ra_db::FileRange;
    use test_utils::{extract_offset, extract_range, assert_eq_text, add_cursor};

    use crate::{AssistCtx, Assist};

    pub(crate) fn check_assist(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
        after: &str,
    ) {
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assist =
            AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
        let action = match assist {
            Assist::Unresolved(_) => unreachable!(),
            Assist::Resolved(_, it) => it,
        };

        let actual = action.edit.apply(&before);
        let actual_cursor_pos = match action.cursor_position {
            None => action
                .edit
                .apply_to_offset(before_cursor_pos)
                .expect("cursor position is affected by the edit"),
            Some(off) => off,
        };
        let actual = add_cursor(&actual, actual_cursor_pos);
        assert_eq_text!(after, &actual);
    }

    pub(crate) fn check_assist_range(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
        after: &str,
    ) {
        let (range, before) = extract_range(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange = FileRange { file_id, range };
        let assist =
            AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
        let action = match assist {
            Assist::Unresolved(_) => unreachable!(),
            Assist::Resolved(_, it) => it,
        };

        let mut actual = action.edit.apply(&before);
        if let Some(pos) = action.cursor_position {
            actual = add_cursor(&actual, pos);
        }
        assert_eq_text!(after, &actual);
    }

    pub(crate) fn check_assist_target(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
        target: &str,
    ) {
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assist =
            AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
        let action = match assist {
            Assist::Unresolved(_) => unreachable!(),
            Assist::Resolved(_, it) => it,
        };

        let range = action.target.expect("expected target on action");
        assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target);
    }

    pub(crate) fn check_assist_range_target(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
        target: &str,
    ) {
        let (range, before) = extract_range(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange = FileRange { file_id, range };
        let assist =
            AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
        let action = match assist {
            Assist::Unresolved(_) => unreachable!(),
            Assist::Resolved(_, it) => it,
        };

        let range = action.target.expect("expected target on action");
        assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target);
    }

    pub(crate) fn check_assist_not_applicable(
        assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
        before: &str,
    ) {
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assist = AssistCtx::with_ctx(&db, frange, true, assist);
        assert!(assist.is_none());
    }
}

#[cfg(test)]
mod tests {
    use hir::mock::MockDatabase;
    use ra_syntax::TextRange;
    use ra_db::FileRange;
    use test_utils::{extract_offset};

    #[test]
    fn assist_order_field_struct() {
        let before = "struct Foo { <|>bar: u32 }";
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assists = super::assists(&db, frange);
        let mut assists = assists.iter();

        assert_eq!(assists.next().expect("expected assist").0.label, "make pub(crate)");
        assert_eq!(assists.next().expect("expected assist").0.label, "add `#[derive]`");
    }

    #[test]
    fn assist_order_if_expr() {
        let before = "
        pub fn test_some_range(a: int) -> bool {
            if let 2..6 = 5<|> {
                true
            } else {
                false
            }
        }";
        let (before_cursor_pos, before) = extract_offset(before);
        let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
        let frange =
            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
        let assists = super::assists(&db, frange);
        let mut assists = assists.iter();

        assert_eq!(assists.next().expect("expected assist").0.label, "introduce variable");
        assert_eq!(assists.next().expect("expected assist").0.label, "replace with match");
    }

}
<|endoftext|>


<commit_before>// Copyright © 2016; Dmitry Roschin
// Licensed under the MIT License <LICENSE.md>
use shared::basetsd::{UINT64};
use shared::guiddef::{IID};
use shared::minwindef::{UINT, ULONG, LPVOID, BOOL, INT, BYTE};
use um::d3dcommon::*;
use um::unknwnbase::{IUnknown, IUnknownVtbl};
use um::winnt::{HRESULT, LPCSTR};

ENUM!{enum D3D12_SHADER_VERSION_TYPE {
    D3D12_SHVER_PIXEL_SHADER = 0x0,
    D3D12_SHVER_VERTEX_SHADER = 0x1,
    D3D12_SHVER_GEOMETRY_SHADER = 0x2,
    D3D12_SHVER_HULL_SHADER = 0x3,
    D3D12_SHVER_DOMAIN_SHADER = 0x4,
    D3D12_SHVER_COMPUTE_SHADER = 0x5,
    D3D12_SHVER_RESERVED0 = 0xFFF0,
}}

STRUCT!{struct D3D12_FUNCTION_DESC {
    Version: UINT,
    Creator: LPCSTR,
    Flags: UINT,
    ConstantBuffers: UINT,
    BoundResources: UINT,
    InstructionCount: UINT,
    TempRegisterCount: UINT,
    TempArrayCount: UINT,
    DefCount: UINT,
    DclCount: UINT,
    TextureNormalInstructions: UINT,
    TextureLoadInstructions: UINT,
    TextureCompInstructions: UINT,
    TextureBiasInstructions: UINT,
    TextureGradientInstructions: UINT,
    FloatInstructionCount: UINT,
    IntInstructionCount: UINT,
    UintInstructionCount: UINT,
    StaticFlowControlCount: UINT,
    DynamicFlowControlCount: UINT,
    MacroInstructionCount: UINT,
    ArrayInstructionCount: UINT,
    MovInstructionCount: UINT,
    MovcInstructionCount: UINT,
    ConversionInstructionCount: UINT,
    BitwiseInstructionCount: UINT,
    MinFeatureLevel: D3D_FEATURE_LEVEL,
    RequiredFeatureFlags: UINT64,
    Name: LPCSTR,
    FunctionParameterCount: INT,
    HasReturn: BOOL,
    Has10Level9VertexShader: BOOL,
    Has10Level9PixelShader: BOOL,
}}

STRUCT!{struct D3D12_LIBRARY_DESC {
    Creator: LPCSTR,
    Flags: UINT,
    FunctionCount: UINT,
}}

STRUCT!{struct D3D12_PARAMETER_DESC {
    Name: LPCSTR,
    SemanticName: LPCSTR,
    Type: D3D_SHADER_VARIABLE_TYPE,
    Class: D3D_SHADER_VARIABLE_CLASS,
    Rows: UINT,
    Columns: UINT,
    InterpolationMode: D3D_INTERPOLATION_MODE,
    Flags: D3D_PARAMETER_FLAGS,
    FirstInRegister: UINT,
    FirstInComponent: UINT,
    FirstOutRegister: UINT,
    FirstOutComponent: UINT,
}}

STRUCT!{struct D3D12_SHADER_BUFFER_DESC {
    Name: LPCSTR,
    Type: D3D_CBUFFER_TYPE,
    Variables: UINT,
    Size: UINT,
    uFlags: UINT,
}}

STRUCT!{struct D3D12_SHADER_DESC {
    Version: UINT,
    Creator: LPCSTR,
    Flags: UINT,
    ConstantBuffers: UINT,
    BoundResources: UINT,
    InputParameters: UINT,
    OutputParameters: UINT,
    InstructionCount: UINT,
    TempRegisterCount: UINT,
    TempArrayCount: UINT,
    DefCount: UINT,
    DclCount: UINT,
    TextureNormalInstructions: UINT,
    TextureLoadInstructions: UINT,
    TextureCompInstructions: UINT,
    TextureBiasInstructions: UINT,
    TextureGradientInstructions: UINT,
    FloatInstructionCount: UINT,
    IntInstructionCount: UINT,
    UintInstructionCount: UINT,
    StaticFlowControlCount: UINT,
    DynamicFlowControlCount: UINT,
    MacroInstructionCount: UINT,
    ArrayInstructionCount: UINT,
    CutInstructionCount: UINT,
    EmitInstructionCount: UINT,
    GSOutputTopology: D3D_PRIMITIVE_TOPOLOGY,
    GSMaxOutputVertexCount: UINT,
    InputPrimitive: D3D_PRIMITIVE,
    PatchConstantParameters: UINT,
    cGSInstanceCount: UINT,
    cControlPoints: UINT,
    HSOutputPrimitive: D3D_TESSELLATOR_OUTPUT_PRIMITIVE,
    HSPartitioning: D3D_TESSELLATOR_PARTITIONING,
    TessellatorDomain: D3D_TESSELLATOR_DOMAIN,
    cBarrierInstructions: UINT,
    cInterlockedInstructions: UINT,
    cTextureStoreInstructions: UINT,
}}

STRUCT!{struct D3D12_SHADER_INPUT_BIND_DESC {
    Name: LPCSTR,
    Type: D3D_SHADER_INPUT_TYPE,
    BindPoint: UINT,
    BindCount: UINT,
    uFlags: UINT,
    ReturnType: D3D_RESOURCE_RETURN_TYPE,
    Dimension: D3D_SRV_DIMENSION,
    NumSamples: UINT,
    Space: UINT,
    uID: UINT,
}}

STRUCT!{struct D3D12_SHADER_TYPE_DESC {
    Class: D3D_SHADER_VARIABLE_CLASS,
    Type: D3D_SHADER_VARIABLE_TYPE,
    Rows: UINT,
    Columns: UINT,
    Elements: UINT,
    Members: UINT,
    Offset: UINT,
    Name: LPCSTR,
}}

STRUCT!{struct D3D12_SHADER_VARIABLE_DESC {
    Name: LPCSTR,
    StartOffset: UINT,
    Size: UINT,
    uFlags: UINT,
    DefaultValue: LPVOID,
    StartTexture: UINT,
    TextureSize: UINT,
    StartSampler: UINT,
    SamplerSize: UINT,
}}

STRUCT!{struct D3D12_SIGNATURE_PARAMETER_DESC {
    SemanticName: LPCSTR,
    SemanticIndex: UINT,
    Register: UINT,
    SystemValueType: D3D_NAME,
    ComponentType: D3D_REGISTER_COMPONENT_TYPE,
    Mask: BYTE,
    ReadWriteMask: BYTE,
    Stream: UINT,
    MinPrecision: D3D_MIN_PRECISION,
}}

RIDL!{#[uuid(0xec25f42d, 0x7006, 0x4f2b, 0xb3, 0x3e, 0x02, 0xcc, 0x33, 0x75, 0x73, 0x3f)]
interface ID3D12FunctionParameterReflection(ID3D12FunctionParameterReflectionVtbl) {
    fn GetDesc(pDesc: *mut D3D12_PARAMETER_DESC) -> HRESULT
}}

RIDL!{#[uuid(0x1108795c, 0x2772, 0x4ba9, 0xb2, 0xa8, 0xd4, 0x64, 0xdc, 0x7e, 0x27, 0x99)]
interface ID3D12FunctionReflection(ID3D12FunctionReflectionVtbl) {
    fn GetDesc(pDesc: *mut D3D12_FUNCTION_DESC) -> HRESULT,
    fn GetConstantBufferByIndex(
        BufferIndex: UINT
    ) -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetConstantBufferByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetResourceBindingDesc(
        ResourceIndex: UINT, pDesc: *mut D3D12_SHADER_INPUT_BIND_DESC
    ) -> HRESULT,
    fn GetVariableByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionVariable,
    fn GetResourceBindingDescByName(
        Name: LPCSTR, pDesc: *mut D3D12_SHADER_INPUT_BIND_DESC
    ) -> HRESULT,
    fn GetFunctionParameter(
        ParameterIndex: INT
    ) -> *mut ID3D12FunctionParameterReflection
}}

RIDL!(#[uuid(0x8e349d19, 0x54db, 0x4a56, 0x9d, 0xc9, 0x11, 0x9d, 0x87, 0xbd, 0xb8, 0x4)]
interface ID3D12LibraryReflection(ID3D12LibraryReflectionVtbl): IUnknown(IUnknownVtbl) {
    fn QueryInterface(
        iid: *const IID, ppv: *mut LPVOID
    ) -> HRESULT,
    fn AddRef() -> ULONG,
    fn Release() -> ULONG,
    fn GetDesc(pDesc: *mut D3D12_LIBRARY_DESC) -> HRESULT,
    fn GetFunctionByIndex(
        FunctionIndex: INT
    ) -> *mut ID3D12FunctionReflection
});

RIDL!{#[uuid(0xc59598b4, 0x48b3, 0x4869, 0xb9, 0xb1, 0xb1, 0x61, 0x8b, 0x14, 0xa8, 0xb7)]
interface ID3D12ShaderReflectionConstantBuffer(ID3D12ShaderReflectionConstantBufferVtbl) {
    fn GetDesc(pDesc: *mut D3D12_SHADER_BUFFER_DESC) -> HRESULT,
    fn GetVariableByIndex(
        Index: UINT
    ) -> *mut ID3D12ShaderReflectionVariable,
    fn GetVariableByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionVariable
}}

RIDL!{#[uuid(0xe913c351, 0x783d, 0x48ca, 0xa1, 0xd1, 0x4f, 0x30, 0x62, 0x84, 0xad, 0x56)]
interface ID3D12ShaderReflectionType(ID3D12ShaderReflectionTypeVtbl) {
    fn GetDesc(pDesc: *mut D3D12_SHADER_TYPE_DESC) -> HRESULT,
    fn GetMemberTypeByIndex(
        Index: UINT
    ) -> *mut ID3D12ShaderReflectionType,
    fn GetMemberTypeByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionType,
    fn GetMemberTypeName(Index: UINT) -> LPCSTR,
    fn IsEqual(
        pType: *mut ID3D12ShaderReflectionType
    ) -> HRESULT,
    fn GetSubType() -> *mut ID3D12ShaderReflectionType,
    fn GetBaseClass() -> *mut ID3D12ShaderReflectionType,
    fn GetNumInterfaces() -> UINT,
    fn GetInterfaceByIndex(
        uIndex: UINT
    ) -> *mut ID3D12ShaderReflectionType,
    fn IsOfType(
        pType: *mut ID3D12ShaderReflectionType
    ) -> HRESULT,
    fn ImplementsInterface(
        pBase: *mut ID3D12ShaderReflectionType
    ) -> HRESULT
}}

RIDL!{#[uuid(0x8337a8a6, 0xa216, 0x444a, 0xb2, 0xf4, 0x31, 0x47, 0x33, 0xa7, 0x3a, 0xea)]
interface ID3D12ShaderReflectionVariable(ID3D12ShaderReflectionVariableVtbl) {
    fn GetDesc(
        pDesc: *mut D3D12_SHADER_VARIABLE_DESC
    ) -> HRESULT,
    fn GetType() -> *mut ID3D12ShaderReflectionType,
    fn GetBuffer() -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetInterfaceSlot(uArrayIndex: UINT) -> UINT
}}

RIDL!(#[uuid(0x5a58797d, 0xa72c, 0x478d, 0x8b, 0xa2, 0xef, 0xc6, 0xb0, 0xef, 0xe8, 0x8e)]
interface ID3D12ShaderReflection(ID3D12ShaderReflectionVtbl): IUnknown(IUnknownVtbl) {
    fn QueryInterface(
        iid: *const IID, ppv: *mut LPVOID
    ) -> HRESULT,
    fn AddRef() -> ULONG,
    fn Release() -> ULONG,
    fn GetDesc(pDesc: *mut D3D12_SHADER_DESC) -> HRESULT,
    fn GetConstantBufferByIndex(
        Index: UINT
    ) -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetConstantBufferByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetResourceBindingDesc(
        ResourceIndex: UINT, pDesc: *mut D3D12_SHADER_INPUT_BIND_DESC
    ) -> HRESULT,
    fn GetInputParameterDesc(
        ParameterIndex: UINT, pDesc: *mut D3D12_SIGNATURE_PARAMETER_DESC
    ) -> HRESULT,
    fn GetOutputParameterDesc(
        ParameterIndex: UINT, pDesc: *mut D3D12_SIGNATURE_PARAMETER_DESC
    ) -> HRESULT,
    fn GetPatchConstantParameterDesc(
        ParameterIndex: UINT, pDesc: *mut D3D12_SIGNATURE_PARAMETER_DESC
    ) -> HRESULT,
    fn GetVariableByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionVariable,
    fn GetResourceBindingDescByName(
        Name: LPCSTR, pDesc: *mut D3D12_SHADER_INPUT_BIND_DESC
    ) -> HRESULT,
    fn GetMovInstructionCount() -> UINT,
    fn GetMovcInstructionCount() -> UINT,
    fn GetConversionInstructionCount() -> UINT,
    fn GetBitwiseInstructionCount() -> UINT,
    fn GetGSInputPrimitive() -> D3D_PRIMITIVE,
    fn IsSampleFrequencyShader() -> BOOL,
    fn GetNumInterfaceSlots() -> UINT,
    fn GetMinFeatureLevel(
        pLevel: *mut D3D_FEATURE_LEVEL
    ) -> HRESULT,
    fn GetThreadGroupSize(
        pSizeX: *mut UINT, pSizeY: *mut UINT, pSizeZ: *mut UINT
    ) -> UINT,
    fn GetRequiresFlags() -> UINT64
});

pub type D3D12_CBUFFER_TYPE = D3D_CBUFFER_TYPE;
pub type D3D12_RESOURCE_RETURN_TYPE = D3D_RESOURCE_RETURN_TYPE;
pub type D3D12_TESSELLATOR_DOMAIN = D3D_TESSELLATOR_DOMAIN;
pub type D3D12_TESSELLATOR_OUTPUT_PRIMITIVE = D3D_TESSELLATOR_OUTPUT_PRIMITIVE;
pub type D3D12_TESSELLATOR_PARTITIONING = D3D_TESSELLATOR_PARTITIONING;
pub type LPD3D12FUNCTIONPARAMETERREFLECTION = *mut ID3D12FunctionParameterReflection;
pub type LPD3D12FUNCTIONREFLECTION = *mut ID3D12FunctionReflection;
pub type LPD3D12LIBRARYREFLECTION = *mut ID3D12LibraryReflection;
pub type LPD3D12SHADERREFLECTION = *mut ID3D12ShaderReflection;
pub type LPD3D12SHADERREFLECTIONCONSTANTBUFFER = *mut ID3D12ShaderReflectionConstantBuffer;
pub type LPD3D12SHADERREFLECTIONTYPE = *mut ID3D12ShaderReflectionType;
pub type LPD3D12SHADERREFLECTIONVARIABLE = *mut ID3D12ShaderReflectionVariable;
pub const D3D_SHADER_REQUIRES_INNER_COVERAGE: UINT64 = 0x00000400;
pub const D3D_SHADER_REQUIRES_ROVS: UINT64 = 0x00001000;
pub const D3D_SHADER_REQUIRES_STENCIL_REF: UINT64 = 0x00000200;
pub const D3D_SHADER_REQUIRES_TYPED_UAV_LOAD_ADDITIONAL_FORMATS: UINT64 = 0x00000800;
pub const D3D_SHADER_REQUIRES_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER: UINT64 = 0x00002000;
<commit_msg>Fix some interface definitions<commit_after>// Copyright © 2016; Dmitry Roschin
// Licensed under the MIT License <LICENSE.md>
use shared::basetsd::{UINT64};
use shared::guiddef::{IID};
use shared::minwindef::{UINT, ULONG, LPVOID, BOOL, INT, BYTE};
use um::d3dcommon::*;
use um::unknwnbase::{IUnknown, IUnknownVtbl};
use um::winnt::{HRESULT, LPCSTR};

ENUM!{enum D3D12_SHADER_VERSION_TYPE {
    D3D12_SHVER_PIXEL_SHADER = 0x0,
    D3D12_SHVER_VERTEX_SHADER = 0x1,
    D3D12_SHVER_GEOMETRY_SHADER = 0x2,
    D3D12_SHVER_HULL_SHADER = 0x3,
    D3D12_SHVER_DOMAIN_SHADER = 0x4,
    D3D12_SHVER_COMPUTE_SHADER = 0x5,
    D3D12_SHVER_RESERVED0 = 0xFFF0,
}}

STRUCT!{struct D3D12_FUNCTION_DESC {
    Version: UINT,
    Creator: LPCSTR,
    Flags: UINT,
    ConstantBuffers: UINT,
    BoundResources: UINT,
    InstructionCount: UINT,
    TempRegisterCount: UINT,
    TempArrayCount: UINT,
    DefCount: UINT,
    DclCount: UINT,
    TextureNormalInstructions: UINT,
    TextureLoadInstructions: UINT,
    TextureCompInstructions: UINT,
    TextureBiasInstructions: UINT,
    TextureGradientInstructions: UINT,
    FloatInstructionCount: UINT,
    IntInstructionCount: UINT,
    UintInstructionCount: UINT,
    StaticFlowControlCount: UINT,
    DynamicFlowControlCount: UINT,
    MacroInstructionCount: UINT,
    ArrayInstructionCount: UINT,
    MovInstructionCount: UINT,
    MovcInstructionCount: UINT,
    ConversionInstructionCount: UINT,
    BitwiseInstructionCount: UINT,
    MinFeatureLevel: D3D_FEATURE_LEVEL,
    RequiredFeatureFlags: UINT64,
    Name: LPCSTR,
    FunctionParameterCount: INT,
    HasReturn: BOOL,
    Has10Level9VertexShader: BOOL,
    Has10Level9PixelShader: BOOL,
}}

STRUCT!{struct D3D12_LIBRARY_DESC {
    Creator: LPCSTR,
    Flags: UINT,
    FunctionCount: UINT,
}}

STRUCT!{struct D3D12_PARAMETER_DESC {
    Name: LPCSTR,
    SemanticName: LPCSTR,
    Type: D3D_SHADER_VARIABLE_TYPE,
    Class: D3D_SHADER_VARIABLE_CLASS,
    Rows: UINT,
    Columns: UINT,
    InterpolationMode: D3D_INTERPOLATION_MODE,
    Flags: D3D_PARAMETER_FLAGS,
    FirstInRegister: UINT,
    FirstInComponent: UINT,
    FirstOutRegister: UINT,
    FirstOutComponent: UINT,
}}

STRUCT!{struct D3D12_SHADER_BUFFER_DESC {
    Name: LPCSTR,
    Type: D3D_CBUFFER_TYPE,
    Variables: UINT,
    Size: UINT,
    uFlags: UINT,
}}

STRUCT!{struct D3D12_SHADER_DESC {
    Version: UINT,
    Creator: LPCSTR,
    Flags: UINT,
    ConstantBuffers: UINT,
    BoundResources: UINT,
    InputParameters: UINT,
    OutputParameters: UINT,
    InstructionCount: UINT,
    TempRegisterCount: UINT,
    TempArrayCount: UINT,
    DefCount: UINT,
    DclCount: UINT,
    TextureNormalInstructions: UINT,
    TextureLoadInstructions: UINT,
    TextureCompInstructions: UINT,
    TextureBiasInstructions: UINT,
    TextureGradientInstructions: UINT,
    FloatInstructionCount: UINT,
    IntInstructionCount: UINT,
    UintInstructionCount: UINT,
    StaticFlowControlCount: UINT,
    DynamicFlowControlCount: UINT,
    MacroInstructionCount: UINT,
    ArrayInstructionCount: UINT,
    CutInstructionCount: UINT,
    EmitInstructionCount: UINT,
    GSOutputTopology: D3D_PRIMITIVE_TOPOLOGY,
    GSMaxOutputVertexCount: UINT,
    InputPrimitive: D3D_PRIMITIVE,
    PatchConstantParameters: UINT,
    cGSInstanceCount: UINT,
    cControlPoints: UINT,
    HSOutputPrimitive: D3D_TESSELLATOR_OUTPUT_PRIMITIVE,
    HSPartitioning: D3D_TESSELLATOR_PARTITIONING,
    TessellatorDomain: D3D_TESSELLATOR_DOMAIN,
    cBarrierInstructions: UINT,
    cInterlockedInstructions: UINT,
    cTextureStoreInstructions: UINT,
}}

STRUCT!{struct D3D12_SHADER_INPUT_BIND_DESC {
    Name: LPCSTR,
    Type: D3D_SHADER_INPUT_TYPE,
    BindPoint: UINT,
    BindCount: UINT,
    uFlags: UINT,
    ReturnType: D3D_RESOURCE_RETURN_TYPE,
    Dimension: D3D_SRV_DIMENSION,
    NumSamples: UINT,
    Space: UINT,
    uID: UINT,
}}

STRUCT!{struct D3D12_SHADER_TYPE_DESC {
    Class: D3D_SHADER_VARIABLE_CLASS,
    Type: D3D_SHADER_VARIABLE_TYPE,
    Rows: UINT,
    Columns: UINT,
    Elements: UINT,
    Members: UINT,
    Offset: UINT,
    Name: LPCSTR,
}}

STRUCT!{struct D3D12_SHADER_VARIABLE_DESC {
    Name: LPCSTR,
    StartOffset: UINT,
    Size: UINT,
    uFlags: UINT,
    DefaultValue: LPVOID,
    StartTexture: UINT,
    TextureSize: UINT,
    StartSampler: UINT,
    SamplerSize: UINT,
}}

STRUCT!{struct D3D12_SIGNATURE_PARAMETER_DESC {
    SemanticName: LPCSTR,
    SemanticIndex: UINT,
    Register: UINT,
    SystemValueType: D3D_NAME,
    ComponentType: D3D_REGISTER_COMPONENT_TYPE,
    Mask: BYTE,
    ReadWriteMask: BYTE,
    Stream: UINT,
    MinPrecision: D3D_MIN_PRECISION,
}}

RIDL!{#[uuid(0xec25f42d, 0x7006, 0x4f2b, 0xb3, 0x3e, 0x02, 0xcc, 0x33, 0x75, 0x73, 0x3f)]
interface ID3D12FunctionParameterReflection(ID3D12FunctionParameterReflectionVtbl) {
    fn GetDesc(pDesc: *mut D3D12_PARAMETER_DESC) -> HRESULT
}}

RIDL!{#[uuid(0x1108795c, 0x2772, 0x4ba9, 0xb2, 0xa8, 0xd4, 0x64, 0xdc, 0x7e, 0x27, 0x99)]
interface ID3D12FunctionReflection(ID3D12FunctionReflectionVtbl) {
    fn GetDesc(pDesc: *mut D3D12_FUNCTION_DESC) -> HRESULT,
    fn GetConstantBufferByIndex(
        BufferIndex: UINT
    ) -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetConstantBufferByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetResourceBindingDesc(
        ResourceIndex: UINT, pDesc: *mut D3D12_SHADER_INPUT_BIND_DESC
    ) -> HRESULT,
    fn GetVariableByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionVariable,
    fn GetResourceBindingDescByName(
        Name: LPCSTR, pDesc: *mut D3D12_SHADER_INPUT_BIND_DESC
    ) -> HRESULT,
    fn GetFunctionParameter(
        ParameterIndex: INT
    ) -> *mut ID3D12FunctionParameterReflection
}}

RIDL!(#[uuid(0x8e349d19, 0x54db, 0x4a56, 0x9d, 0xc9, 0x11, 0x9d, 0x87, 0xbd, 0xb8, 0x4)]
interface ID3D12LibraryReflection(ID3D12LibraryReflectionVtbl): IUnknown(IUnknownVtbl) {
    fn GetDesc(pDesc: *mut D3D12_LIBRARY_DESC) -> HRESULT,
    fn GetFunctionByIndex(
        FunctionIndex: INT
    ) -> *mut ID3D12FunctionReflection
});

RIDL!{#[uuid(0xc59598b4, 0x48b3, 0x4869, 0xb9, 0xb1, 0xb1, 0x61, 0x8b, 0x14, 0xa8, 0xb7)]
interface ID3D12ShaderReflectionConstantBuffer(ID3D12ShaderReflectionConstantBufferVtbl) {
    fn GetDesc(pDesc: *mut D3D12_SHADER_BUFFER_DESC) -> HRESULT,
    fn GetVariableByIndex(
        Index: UINT
    ) -> *mut ID3D12ShaderReflectionVariable,
    fn GetVariableByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionVariable
}}

RIDL!{#[uuid(0xe913c351, 0x783d, 0x48ca, 0xa1, 0xd1, 0x4f, 0x30, 0x62, 0x84, 0xad, 0x56)]
interface ID3D12ShaderReflectionType(ID3D12ShaderReflectionTypeVtbl) {
    fn GetDesc(pDesc: *mut D3D12_SHADER_TYPE_DESC) -> HRESULT,
    fn GetMemberTypeByIndex(
        Index: UINT
    ) -> *mut ID3D12ShaderReflectionType,
    fn GetMemberTypeByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionType,
    fn GetMemberTypeName(Index: UINT) -> LPCSTR,
    fn IsEqual(
        pType: *mut ID3D12ShaderReflectionType
    ) -> HRESULT,
    fn GetSubType() -> *mut ID3D12ShaderReflectionType,
    fn GetBaseClass() -> *mut ID3D12ShaderReflectionType,
    fn GetNumInterfaces() -> UINT,
    fn GetInterfaceByIndex(
        uIndex: UINT
    ) -> *mut ID3D12ShaderReflectionType,
    fn IsOfType(
        pType: *mut ID3D12ShaderReflectionType
    ) -> HRESULT,
    fn ImplementsInterface(
        pBase: *mut ID3D12ShaderReflectionType
    ) -> HRESULT
}}

RIDL!{#[uuid(0x8337a8a6, 0xa216, 0x444a, 0xb2, 0xf4, 0x31, 0x47, 0x33, 0xa7, 0x3a, 0xea)]
interface ID3D12ShaderReflectionVariable(ID3D12ShaderReflectionVariableVtbl) {
    fn GetDesc(
        pDesc: *mut D3D12_SHADER_VARIABLE_DESC
    ) -> HRESULT,
    fn GetType() -> *mut ID3D12ShaderReflectionType,
    fn GetBuffer() -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetInterfaceSlot(uArrayIndex: UINT) -> UINT
}}

RIDL!(#[uuid(0x5a58797d, 0xa72c, 0x478d, 0x8b, 0xa2, 0xef, 0xc6, 0xb0, 0xef, 0xe8, 0x8e)]
interface ID3D12ShaderReflection(ID3D12ShaderReflectionVtbl): IUnknown(IUnknownVtbl) {
    fn GetDesc(pDesc: *mut D3D12_SHADER_DESC) -> HRESULT,
    fn GetConstantBufferByIndex(
        Index: UINT
    ) -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetConstantBufferByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionConstantBuffer,
    fn GetResourceBindingDesc(
        ResourceIndex: UINT, pDesc: *mut D3D12_SHADER_INPUT_BIND_DESC
    ) -> HRESULT,
    fn GetInputParameterDesc(
        ParameterIndex: UINT, pDesc: *mut D3D12_SIGNATURE_PARAMETER_DESC
    ) -> HRESULT,
    fn GetOutputParameterDesc(
        ParameterIndex: UINT, pDesc: *mut D3D12_SIGNATURE_PARAMETER_DESC
    ) -> HRESULT,
    fn GetPatchConstantParameterDesc(
        ParameterIndex: UINT, pDesc: *mut D3D12_SIGNATURE_PARAMETER_DESC
    ) -> HRESULT,
    fn GetVariableByName(
        Name: LPCSTR
    ) -> *mut ID3D12ShaderReflectionVariable,
    fn GetResourceBindingDescByName(
        Name: LPCSTR, pDesc: *mut D3D12_SHADER_INPUT_BIND_DESC
    ) -> HRESULT,
    fn GetMovInstructionCount() -> UINT,
    fn GetMovcInstructionCount() -> UINT,
    fn GetConversionInstructionCount() -> UINT,
    fn GetBitwiseInstructionCount() -> UINT,
    fn GetGSInputPrimitive() -> D3D_PRIMITIVE,
    fn IsSampleFrequencyShader() -> BOOL,
    fn GetNumInterfaceSlots() -> UINT,
    fn GetMinFeatureLevel(
        pLevel: *mut D3D_FEATURE_LEVEL
    ) -> HRESULT,
    fn GetThreadGroupSize(
        pSizeX: *mut UINT, pSizeY: *mut UINT, pSizeZ: *mut UINT
    ) -> UINT,
    fn GetRequiresFlags() -> UINT64
});

pub type D3D12_CBUFFER_TYPE = D3D_CBUFFER_TYPE;
pub type D3D12_RESOURCE_RETURN_TYPE = D3D_RESOURCE_RETURN_TYPE;
pub type D3D12_TESSELLATOR_DOMAIN = D3D_TESSELLATOR_DOMAIN;
pub type D3D12_TESSELLATOR_OUTPUT_PRIMITIVE = D3D_TESSELLATOR_OUTPUT_PRIMITIVE;
pub type D3D12_TESSELLATOR_PARTITIONING = D3D_TESSELLATOR_PARTITIONING;
pub type LPD3D12FUNCTIONPARAMETERREFLECTION = *mut ID3D12FunctionParameterReflection;
pub type LPD3D12FUNCTIONREFLECTION = *mut ID3D12FunctionReflection;
pub type LPD3D12LIBRARYREFLECTION = *mut ID3D12LibraryReflection;
pub type LPD3D12SHADERREFLECTION = *mut ID3D12ShaderReflection;
pub type LPD3D12SHADERREFLECTIONCONSTANTBUFFER = *mut ID3D12ShaderReflectionConstantBuffer;
pub type LPD3D12SHADERREFLECTIONTYPE = *mut ID3D12ShaderReflectionType;
pub type LPD3D12SHADERREFLECTIONVARIABLE = *mut ID3D12ShaderReflectionVariable;
pub const D3D_SHADER_REQUIRES_INNER_COVERAGE: UINT64 = 0x00000400;
pub const D3D_SHADER_REQUIRES_ROVS: UINT64 = 0x00001000;
pub const D3D_SHADER_REQUIRES_STENCIL_REF: UINT64 = 0x00000200;
pub const D3D_SHADER_REQUIRES_TYPED_UAV_LOAD_ADDITIONAL_FORMATS: UINT64 = 0x00000800;
pub const D3D_SHADER_REQUIRES_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER: UINT64 = 0x00002000;
<|endoftext|>


<commit_before>//! string interner
//! same as cargo::core::interning.rs, but thread local and Deserializable

extern crate serde;
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};

use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::HashSet;
use std::error::Error;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::ptr;
use std::str;

fn leak(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

thread_local! {
    static STRING_CACHE: RefCell<HashSet<&'static str>> = Default::default();
}

#[derive(Clone, Copy)]
pub struct InternedString {
    inner: &'static str,
}

impl PartialEq for InternedString {
    fn eq(&self, other: &InternedString) -> bool {
        ptr::eq(self.as_str(), other.as_str())
    }
}

impl Eq for InternedString {}

impl InternedString {
    pub fn new(st: &str) -> InternedString {
        STRING_CACHE.with(|cache| {
            let mut cache = cache.borrow_mut();
            let s = cache.get(st).map(|&s| s).unwrap_or_else(|| {
                let s = leak(st.to_string());
                cache.insert(s);
                s
            });
            InternedString { inner: s }
        })
    }

    pub fn new_if_exists(st: &str) -> Option<InternedString> {
        STRING_CACHE.with(|cache| cache.borrow().get(st).map(|&s| InternedString { inner: s }))
    }

    pub fn as_str(&self) -> &'static str {
        self.inner
    }
}

impl Deref for InternedString {
    type Target = str;

    fn deref(&self) -> &'static str {
        self.as_str()
    }
}

impl Hash for InternedString {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&(self.inner as *const str), state)
    }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.as_str(), f)
    }
}

impl fmt::Display for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.as_str(), f)
    }
}

impl Ord for InternedString {
    fn cmp(&self, other: &InternedString) -> Ordering {
        self.as_str().cmp(other.as_str())
    }
}

impl PartialOrd for InternedString {
    fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Serialize for InternedString {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.inner)
    }
}

impl<'de> Deserialize<'de> for InternedString {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct VisStr;
        impl<'de> Visitor<'de> for VisStr {
            type Value = InternedString;
            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "expecting string")
            }
            fn visit_borrowed_str<E: Error>(self, v: &'de str) -> Result<InternedString, E> {
                Ok(InternedString::new(v))
            }
        }
        deserializer.deserialize_str(VisStr {})
    }
}
<commit_msg>interner: replace explicit instances for InternedString by derive<commit_after>//! string interner
//! same as cargo::core::interning.rs, but thread local and Deserializable

extern crate serde;
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};

use std::cell::RefCell;
use std::collections::HashSet;
use std::error::Error;
use std::fmt;
use std::ops::Deref;
use std::ptr;
use std::str;

fn leak(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

thread_local! {
    static STRING_CACHE: RefCell<HashSet<&'static str>> = Default::default();
}

#[derive(Clone, Copy, PartialOrd, Ord, Eq, Hash)]
pub struct InternedString {
    inner: &'static str,
}

impl PartialEq for InternedString {
    fn eq(&self, other: &InternedString) -> bool {
        ptr::eq(self.as_str(), other.as_str())
    }
}

impl InternedString {
    pub fn new(st: &str) -> InternedString {
        STRING_CACHE.with(|cache| {
            let mut cache = cache.borrow_mut();
            let s = cache.get(st).map(|&s| s).unwrap_or_else(|| {
                let s = leak(st.to_string());
                cache.insert(s);
                s
            });
            InternedString { inner: s }
        })
    }

    pub fn new_if_exists(st: &str) -> Option<InternedString> {
        STRING_CACHE.with(|cache| cache.borrow().get(st).map(|&s| InternedString { inner: s }))
    }

    pub fn as_str(&self) -> &'static str {
        self.inner
    }
}

impl Deref for InternedString {
    type Target = str;

    fn deref(&self) -> &'static str {
        self.as_str()
    }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.as_str(), f)
    }
}

impl fmt::Display for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.as_str(), f)
    }
}

impl Serialize for InternedString {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.inner)
    }
}

impl<'de> Deserialize<'de> for InternedString {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct VisStr;
        impl<'de> Visitor<'de> for VisStr {
            type Value = InternedString;
            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "expecting string")
            }
            fn visit_borrowed_str<E: Error>(self, v: &'de str) -> Result<InternedString, E> {
                Ok(InternedString::new(v))
            }
        }
        deserializer.deserialize_str(VisStr {})
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

mod copy;
mod flash;
mod imxkobs;
mod mender;
mod raw;
mod raw_delta;
mod tarball;
mod test;
mod ubifs;
mod uboot_env;
mod zephyr;

use super::{Error, Result};
use crate::utils;
use find_binary_version::{self as fbv, BinaryKind};
use pkg_schema::{definitions, Object};
use slog_scope::debug;
use std::{io, path::PathBuf};

#[derive(Clone, Debug, Default)]
pub(crate) struct Context {
    pub(crate) download_dir: PathBuf,
    pub(crate) offline_update: bool,
    pub(crate) base_url: String,
}

#[async_trait::async_trait(?Send)]
pub(crate) trait Installer {
    async fn check_requirements(&self, _: &Context) -> Result<()> {
        debug!("running default check_requirements");
        Ok(())
    }

    async fn install(&self, context: &Context) -> Result<()>;
}

#[async_trait::async_trait(?Send)]
impl Installer for Object {
    async fn check_requirements(&self, context: &Context) -> Result<()> {
        for_any_object!(self, o, { o.check_requirements(context).await })
    }

    async fn install(&self, context: &Context) -> Result<()> {
        for_any_object!(self, o, { o.install(context).await })
    }
}

fn check_if_different<R: io::Read + io::Seek>(
    handle: &mut R,
    rule: &definitions::InstallIfDifferent,
    sha256sum: &str,
) -> Result<bool> {
    match rule {
        definitions::InstallIfDifferent::CheckSum => {
            let mut buffer = Vec::default();
            handle.read_to_end(&mut buffer)?;
            if utils::sha256sum(&buffer) == sha256sum {
                return Ok(true);
            }
        }
        definitions::InstallIfDifferent::KnownPattern { version, pattern } => {
            let pattern = match pattern {
                definitions::install_if_different::KnownPatternKind::UBoot => BinaryKind::UBoot,
                definitions::install_if_different::KnownPatternKind::LinuxKernel => {
                    BinaryKind::LinuxKernel
                }
            };
            if let Some(ref cur_version) = fbv::version(handle, pattern) {
                if version == cur_version {
                    return Ok(true);
                }
            }
        }
        definitions::InstallIfDifferent::CustomPattern { version, pattern } => {
            io::Seek::seek(handle, io::SeekFrom::Start(pattern.seek))?;
            let mut src = io::BufReader::with_capacity(pattern.buffer_size as usize, handle);
            if let Some(ref cur_version) = fbv::version_with_pattern(&mut src, &pattern.regexp) {
                if version == cur_version {
                    return Ok(true);
                }
            }
        }
    }
    Ok(false)
}

#[cfg(test)]
mod tests {
    use super::*;
    use lazy_static::lazy_static;
    use std::{
        env, fs,
        io::Write,
        os::unix::fs::PermissionsExt,
        path::{Path, PathBuf},
        sync::{Arc, Mutex},
    };
    use tempfile::TempDir;

    // Used to serialize access to Loop devices across tests
    lazy_static! {
        pub static ref SERIALIZE: Arc<Mutex<()>> = Arc::new(Mutex::default());
    }

    fn create_echo_bin(bin: &Path, output: &Path) -> std::io::Result<()> {
        let mut file = std::fs::File::create(bin)?;
        file.write_all(
            format!(
                "#!/bin/sh\necho {} $@ >> {:?}\n",
                bin.file_name().unwrap().to_str().unwrap(),
                output
            )
            .as_bytes(),
        )?;
        file.set_permissions(fs::Permissions::from_mode(0o777))?;

        Ok(())
    }

    pub fn create_echo_bins(bins: &[&str]) -> std::io::Result<(TempDir, PathBuf)> {
        let mocks = tempfile::tempdir()?;
        let mocks_dir = mocks.path();
        let calls = mocks_dir.join("calls");

        for bin in bins {
            create_echo_bin(&mocks_dir.join(bin), &calls)?;
        }

        env::set_var(
            "PATH",
            format!(
                "{}{}",
                mocks_dir.display(),
                &env::var("PATH").map(|s| format!(":{}", s)).unwrap_or_default()
            ),
        );

        Ok((mocks, calls))
    }

    #[test]
    fn unmatched_checksum() {
        let mut f = tempfile::NamedTempFile::new().unwrap();
        assert!(
            !check_if_different(
                &mut f,
                &definitions::InstallIfDifferent::CheckSum,
                "some_sha256sum"
            )
            .unwrap(),
            "Empty fille should not be validated to the checksum"
        );
    }

    #[test]
    fn checksum() {
        let mut f = tempfile::NamedTempFile::new().unwrap();
        io::Write::write_all(&mut f, b"some_sha256sum").unwrap();
        assert!(
            !check_if_different(
                &mut f,
                &definitions::InstallIfDifferent::CheckSum,
                "7dc201ce54a835790d78835363a0bce4db704dd23c0c05e399d2a7d1f8fcef19",
            )
            .unwrap(),
            "Empty fille should not be validated to the checksum"
        );
    }
}
<commit_msg>uh: Fix checksum test<commit_after>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

mod copy;
mod flash;
mod imxkobs;
mod mender;
mod raw;
mod raw_delta;
mod tarball;
mod test;
mod ubifs;
mod uboot_env;
mod zephyr;

use super::{Error, Result};
use crate::utils;
use find_binary_version::{self as fbv, BinaryKind};
use pkg_schema::{definitions, Object};
use slog_scope::debug;
use std::{io, path::PathBuf};

#[derive(Clone, Debug, Default)]
pub(crate) struct Context {
    pub(crate) download_dir: PathBuf,
    pub(crate) offline_update: bool,
    pub(crate) base_url: String,
}

#[async_trait::async_trait(?Send)]
pub(crate) trait Installer {
    async fn check_requirements(&self, _: &Context) -> Result<()> {
        debug!("running default check_requirements");
        Ok(())
    }

    async fn install(&self, context: &Context) -> Result<()>;
}

#[async_trait::async_trait(?Send)]
impl Installer for Object {
    async fn check_requirements(&self, context: &Context) -> Result<()> {
        for_any_object!(self, o, { o.check_requirements(context).await })
    }

    async fn install(&self, context: &Context) -> Result<()> {
        for_any_object!(self, o, { o.install(context).await })
    }
}

fn check_if_different<R: io::Read + io::Seek>(
    handle: &mut R,
    rule: &definitions::InstallIfDifferent,
    sha256sum: &str,
) -> Result<bool> {
    match rule {
        definitions::InstallIfDifferent::CheckSum => {
            let mut buffer = Vec::default();
            handle.read_to_end(&mut buffer)?;
            if utils::sha256sum(&buffer) == sha256sum {
                return Ok(true);
            }
        }
        definitions::InstallIfDifferent::KnownPattern { version, pattern } => {
            let pattern = match pattern {
                definitions::install_if_different::KnownPatternKind::UBoot => BinaryKind::UBoot,
                definitions::install_if_different::KnownPatternKind::LinuxKernel => {
                    BinaryKind::LinuxKernel
                }
            };
            if let Some(ref cur_version) = fbv::version(handle, pattern) {
                if version == cur_version {
                    return Ok(true);
                }
            }
        }
        definitions::InstallIfDifferent::CustomPattern { version, pattern } => {
            io::Seek::seek(handle, io::SeekFrom::Start(pattern.seek))?;
            let mut src = io::BufReader::with_capacity(pattern.buffer_size as usize, handle);
            if let Some(ref cur_version) = fbv::version_with_pattern(&mut src, &pattern.regexp) {
                if version == cur_version {
                    return Ok(true);
                }
            }
        }
    }
    Ok(false)
}

#[cfg(test)]
mod tests {
    use super::*;
    use lazy_static::lazy_static;
    use std::{
        env, fs,
        io::Write,
        os::unix::fs::PermissionsExt,
        path::{Path, PathBuf},
        sync::{Arc, Mutex},
    };
    use tempfile::TempDir;

    // Used to serialize access to Loop devices across tests
    lazy_static! {
        pub static ref SERIALIZE: Arc<Mutex<()>> = Arc::new(Mutex::default());
    }

    fn create_echo_bin(bin: &Path, output: &Path) -> std::io::Result<()> {
        let mut file = std::fs::File::create(bin)?;
        file.write_all(
            format!(
                "#!/bin/sh\necho {} $@ >> {:?}\n",
                bin.file_name().unwrap().to_str().unwrap(),
                output
            )
            .as_bytes(),
        )?;
        file.set_permissions(fs::Permissions::from_mode(0o777))?;

        Ok(())
    }

    pub fn create_echo_bins(bins: &[&str]) -> std::io::Result<(TempDir, PathBuf)> {
        let mocks = tempfile::tempdir()?;
        let mocks_dir = mocks.path();
        let calls = mocks_dir.join("calls");

        for bin in bins {
            create_echo_bin(&mocks_dir.join(bin), &calls)?;
        }

        env::set_var(
            "PATH",
            format!(
                "{}{}",
                mocks_dir.display(),
                &env::var("PATH").map(|s| format!(":{}", s)).unwrap_or_default()
            ),
        );

        Ok((mocks, calls))
    }

    #[test]
    fn unmatched_checksum() {
        let mut f = tempfile::NamedTempFile::new().unwrap();
        assert!(
            !check_if_different(
                &mut f,
                &definitions::InstallIfDifferent::CheckSum,
                "some_sha256sum"
            )
            .unwrap(),
            "Empty fille should not be validated to the checksum"
        );
    }

    #[test]
    fn checksum() {
        let mut f = tempfile::NamedTempFile::new().unwrap();
        io::Write::write_all(&mut f, b"some_sha256sum").unwrap();
        io::Seek::seek(&mut f, io::SeekFrom::Start(0)).unwrap();
        assert!(
            check_if_different(
                &mut f,
                &definitions::InstallIfDifferent::CheckSum,
                "7dc201ce54a835790d78835363a0bce4db704dd23c0c05e399d2a7d1f8fcef19",
            )
            .unwrap(),
            "Empty fille should not be validated to the checksum"
        );
    }
}
<|endoftext|>


<commit_before>use runtime::{Class, Message, ToMessage, object_getClass};
use {class, ClassName, Id};
use super::NSString;

pub trait INSObject : Message {
	fn class_name() -> ClassName<Self>;

	fn class(&self) -> Class {
		unsafe {
			object_getClass(self.as_ptr())
		}
	}

	fn hash_code(&self) -> uint {
		let result = unsafe {
			msg_send![self hash]
		};
		result as uint
	}

	fn is_equal<T: INSObject>(&self, other: &T) -> bool {
		let result = unsafe {
			msg_send![self isEqual:other.as_ptr()]
		};
		!result.is_null()
	}

	fn description(&self) -> Id<NSString> {
		unsafe {
			let result = msg_send![self description];
			Id::from_ptr(result as *mut NSString)
		}
	}

	fn is_kind_of(&self, cls: Class) -> bool {
		let result = unsafe {
			msg_send![self isKindOfClass:cls]
		};
		!result.is_null()
	}

	fn as_object<T: INSObject>(&self) -> Option<&T> {
		let cls = class::<T>();
		if self.is_kind_of(cls) {
			let ptr = self as *const Self as *mut T;
			Some(unsafe { &*ptr })
		} else {
			None
		}
	}

	fn new() -> Id<Self> {
		let cls = class::<Self>();
		unsafe {
			let obj = msg_send![cls alloc];
			let obj = msg_send![obj init];
			Id::from_retained_ptr(obj as *mut Self)
		}
	}
}

object_struct!(NSObject)

#[cfg(test)]
mod tests {
	use {class, ClassName, Id};
	use foundation::{INSString, NSString};
	use super::{INSObject, NSObject};

	#[test]
	fn test_class_name() {
		let ClassName(name): ClassName<NSObject> = INSObject::class_name();
		assert!(name == "NSObject");
	}

	#[test]
	fn test_class() {
		let obj: Id<NSObject> = INSObject::new();
		let cls = obj.class();
		assert!(cls.name() == "NSObject");
	}

	#[test]
	fn test_is_equal() {
		let obj1: Id<NSObject> = INSObject::new();
		assert!(obj1.is_equal(obj1.deref()));

		let obj2: Id<NSObject> = INSObject::new();
		assert!(!obj1.is_equal(obj2.deref()));
	}

	#[test]
	fn test_hash_code() {
		let obj: Id<NSObject> = INSObject::new();
		assert!(obj.hash_code() == obj.hash_code());
	}

	#[test]
	fn test_description() {
		let obj: Id<NSObject> = INSObject::new();
		let description = obj.description();
		let expected = format!("<NSObject: {}>", obj.deref() as *const NSObject);
		assert!(description.as_str() == expected.as_slice());
	}

	#[test]
	fn test_is_kind_of() {
		let obj: Id<NSObject> = INSObject::new();
		assert!(obj.is_kind_of(class::<NSObject>()));
		assert!(!obj.is_kind_of(class::<NSString>()));
	}

	#[test]
	fn test_as_object() {
		let obj: Id<NSObject> = INSObject::new();
		let as_str: Option<&NSString> = obj.as_object();
		assert!(as_str.is_none());

		let string: Id<NSString> = INSObject::new();
		let as_obj: Option<&NSObject> = string.as_object();
		assert!(as_obj.is_some());
	}
}
<commit_msg>Use Object's class method for NSObject.<commit_after>use runtime::{Class, Message, ToMessage};
use {class, ClassName, Id};
use super::NSString;

pub trait INSObject : Message {
	fn class_name() -> ClassName<Self>;

	fn class(&self) -> Class {
		let obj = unsafe { &*self.as_ptr() };
		obj.class()
	}

	fn hash_code(&self) -> uint {
		let result = unsafe {
			msg_send![self hash]
		};
		result as uint
	}

	fn is_equal<T: INSObject>(&self, other: &T) -> bool {
		let result = unsafe {
			msg_send![self isEqual:other.as_ptr()]
		};
		!result.is_null()
	}

	fn description(&self) -> Id<NSString> {
		unsafe {
			let result = msg_send![self description];
			Id::from_ptr(result as *mut NSString)
		}
	}

	fn is_kind_of(&self, cls: Class) -> bool {
		let result = unsafe {
			msg_send![self isKindOfClass:cls]
		};
		!result.is_null()
	}

	fn as_object<T: INSObject>(&self) -> Option<&T> {
		let cls = class::<T>();
		if self.is_kind_of(cls) {
			let ptr = self as *const Self as *mut T;
			Some(unsafe { &*ptr })
		} else {
			None
		}
	}

	fn new() -> Id<Self> {
		let cls = class::<Self>();
		unsafe {
			let obj = msg_send![cls alloc];
			let obj = msg_send![obj init];
			Id::from_retained_ptr(obj as *mut Self)
		}
	}
}

object_struct!(NSObject)

#[cfg(test)]
mod tests {
	use {class, ClassName, Id};
	use foundation::{INSString, NSString};
	use super::{INSObject, NSObject};

	#[test]
	fn test_class_name() {
		let ClassName(name): ClassName<NSObject> = INSObject::class_name();
		assert!(name == "NSObject");
	}

	#[test]
	fn test_class() {
		let obj: Id<NSObject> = INSObject::new();
		let cls = obj.class();
		assert!(cls.name() == "NSObject");
	}

	#[test]
	fn test_is_equal() {
		let obj1: Id<NSObject> = INSObject::new();
		assert!(obj1.is_equal(obj1.deref()));

		let obj2: Id<NSObject> = INSObject::new();
		assert!(!obj1.is_equal(obj2.deref()));
	}

	#[test]
	fn test_hash_code() {
		let obj: Id<NSObject> = INSObject::new();
		assert!(obj.hash_code() == obj.hash_code());
	}

	#[test]
	fn test_description() {
		let obj: Id<NSObject> = INSObject::new();
		let description = obj.description();
		let expected = format!("<NSObject: {}>", obj.deref() as *const NSObject);
		assert!(description.as_str() == expected.as_slice());
	}

	#[test]
	fn test_is_kind_of() {
		let obj: Id<NSObject> = INSObject::new();
		assert!(obj.is_kind_of(class::<NSObject>()));
		assert!(!obj.is_kind_of(class::<NSString>()));
	}

	#[test]
	fn test_as_object() {
		let obj: Id<NSObject> = INSObject::new();
		let as_str: Option<&NSString> = obj.as_object();
		assert!(as_str.is_none());

		let string: Id<NSString> = INSObject::new();
		let as_obj: Option<&NSObject> = string.as_object();
		assert!(as_obj.is_some());
	}
}
<|endoftext|>


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

use std::collections::HashMap;
use std::env;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};

use hcore::fs::FS_ROOT_PATH;
use hcore::package::{PackageIdent, PackageInstall};
use hcore::util::{deserialize_using_from_str, serialize_using_to_string};

use error::{Error, Result};
use fs;
use util;

const PATH_KEY: &'static str = "PATH";
static LOGKEY: &'static str = "PK";

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Env(HashMap<String, String>);

impl Deref for Env {
    type Target = HashMap<String, String>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for Env {
    fn deref_mut(&mut self) -> &mut HashMap<String, String> {
        &mut self.0
    }
}

impl Env {
    /// Modifies PATH env with the full run path for this package. This path is composed of any
    /// binary paths specified by this package, or its TDEPS, plus a path to a BusyBox(non-windows),
    /// plus the existing value of the PATH variable.
    ///
    /// This means we work on any operating system, as long as you can invoke the Supervisor,
    /// without having to worry much about context.
    pub fn new(package: &PackageInstall) -> Result<Self> {
        let mut env = package.runtime_environment()?;
        let mut paths: Vec<PathBuf> = match env.get(PATH_KEY) {
            Some(path) => env::split_paths(&path).collect(),
            None => vec![],
        };
        // Lets join the run paths to the FS_ROOT
        // In most cases, this does nothing and should only mutate
        // the paths in a windows studio where FS_ROOT_PATH will
        // be the studio root path (ie c:\hab\studios\...). In any other
        // environment FS_ROOT will be "/" and this will not make any
        // meaningful change.
        for i in 0..paths.len() {
            if paths[i].starts_with("/") {
                paths[i] = Path::new(&*FS_ROOT_PATH).join(paths[i].strip_prefix("/").unwrap());
            }
        }
        env.insert(
            PATH_KEY.to_string(),
            util::path::append_interpreter_and_path(&mut paths)?,
        );
        Ok(Env(env))
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Pkg {
    #[serde(deserialize_with = "deserialize_using_from_str",
            serialize_with = "serialize_using_to_string")]
    pub ident: PackageIdent,
    pub origin: String,
    pub name: String,
    pub version: String,
    pub release: String,
    pub deps: Vec<PackageIdent>,
    pub env: Env,
    pub exposes: Vec<String>,
    pub exports: HashMap<String, String>,
    pub path: PathBuf,
    pub svc_path: PathBuf,
    pub svc_config_path: PathBuf,
    pub svc_data_path: PathBuf,
    pub svc_files_path: PathBuf,
    pub svc_static_path: PathBuf,
    pub svc_var_path: PathBuf,
    pub svc_pid_file: PathBuf,
    pub svc_run: PathBuf,
    pub svc_user: String,
    pub svc_group: String,
}

impl Pkg {
    pub fn from_install(package: PackageInstall) -> Result<Self> {
        let (svc_user, svc_group) = util::users::get_user_and_group(&package)?;
        let pkg = Pkg {
            svc_path: fs::svc_path(&package.ident.name),
            svc_config_path: fs::svc_config_path(&package.ident.name),
            svc_data_path: fs::svc_data_path(&package.ident.name),
            svc_files_path: fs::svc_files_path(&package.ident.name),
            svc_run: fs::svc_path(&package.ident.name).join("run"),
            svc_static_path: fs::svc_static_path(&package.ident.name),
            svc_var_path: fs::svc_var_path(&package.ident.name),
            svc_pid_file: fs::svc_pid_file(&package.ident.name),
            svc_user: svc_user,
            svc_group: svc_group,
            env: Env::new(&package)?,
            deps: package.tdeps().map_err(|e| {
                sup_error!(Error::BadPackage(package.clone(), e))
            })?,
            exposes: package.exposes().map_err(|e| {
                sup_error!(Error::BadPackage(package.clone(), e))
            })?,
            exports: package.exports().map_err(|e| {
                sup_error!(Error::BadPackage(package.clone(), e))
            })?,
            path: package.installed_path,
            ident: package.ident.clone(),
            origin: package.ident.origin.clone(),
            name: package.ident.name.clone(),
            version: package.ident.version.expect(
                "No package version in PackageInstall",
            ),
            release: package.ident.release.expect(
                "No package release in PackageInstall",
            ),
        };
        Ok(pkg)
    }
}
<commit_msg>Extract `transform_path` function<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::env;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};

use hcore::fs::FS_ROOT_PATH;
use hcore::package::{PackageIdent, PackageInstall};
use hcore::util::{deserialize_using_from_str, serialize_using_to_string};

use error::{Error, Result};
use fs;
use util;

const PATH_KEY: &'static str = "PATH";
static LOGKEY: &'static str = "PK";

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Env(HashMap<String, String>);

impl Deref for Env {
    type Target = HashMap<String, String>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for Env {
    fn deref_mut(&mut self) -> &mut HashMap<String, String> {
        &mut self.0
    }
}

impl Env {
    /// Modifies PATH env with the full run path for this package. This path is composed of any
    /// binary paths specified by this package, or its TDEPS, plus a path to a BusyBox(non-windows),
    /// plus the existing value of the PATH variable.
    ///
    /// This means we work on any operating system, as long as you can invoke the Supervisor,
    /// without having to worry much about context.
    pub fn new(package: &PackageInstall) -> Result<Self> {
        let mut env = package.runtime_environment()?;
        let path = Self::transform_path(env.get(PATH_KEY))?;
        env.insert(PATH_KEY.to_string(), path);
        Ok(Env(env))
    }

    fn transform_path(path: Option<&String>) -> Result<String> {
        let mut paths: Vec<PathBuf> = match path {
            Some(path) => env::split_paths(&path).collect(),
            None => vec![],
        };

        // Lets join the run paths to the FS_ROOT
        // In most cases, this does nothing and should only mutate
        // the paths in a windows studio where FS_ROOT_PATH will
        // be the studio root path (ie c:\hab\studios\...). In any other
        // environment FS_ROOT will be "/" and this will not make any
        // meaningful change.
        for i in 0..paths.len() {
            if paths[i].starts_with("/") {
                paths[i] = Path::new(&*FS_ROOT_PATH).join(paths[i].strip_prefix("/").unwrap());
            }
        }

        util::path::append_interpreter_and_path(&mut paths)
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Pkg {
    #[serde(deserialize_with = "deserialize_using_from_str",
            serialize_with = "serialize_using_to_string")]
    pub ident: PackageIdent,
    pub origin: String,
    pub name: String,
    pub version: String,
    pub release: String,
    pub deps: Vec<PackageIdent>,
    pub env: Env,
    pub exposes: Vec<String>,
    pub exports: HashMap<String, String>,
    pub path: PathBuf,
    pub svc_path: PathBuf,
    pub svc_config_path: PathBuf,
    pub svc_data_path: PathBuf,
    pub svc_files_path: PathBuf,
    pub svc_static_path: PathBuf,
    pub svc_var_path: PathBuf,
    pub svc_pid_file: PathBuf,
    pub svc_run: PathBuf,
    pub svc_user: String,
    pub svc_group: String,
}

impl Pkg {
    pub fn from_install(package: PackageInstall) -> Result<Self> {
        let (svc_user, svc_group) = util::users::get_user_and_group(&package)?;
        let pkg = Pkg {
            svc_path: fs::svc_path(&package.ident.name),
            svc_config_path: fs::svc_config_path(&package.ident.name),
            svc_data_path: fs::svc_data_path(&package.ident.name),
            svc_files_path: fs::svc_files_path(&package.ident.name),
            svc_run: fs::svc_path(&package.ident.name).join("run"),
            svc_static_path: fs::svc_static_path(&package.ident.name),
            svc_var_path: fs::svc_var_path(&package.ident.name),
            svc_pid_file: fs::svc_pid_file(&package.ident.name),
            svc_user: svc_user,
            svc_group: svc_group,
            env: Env::new(&package)?,
            deps: package.tdeps().map_err(|e| {
                sup_error!(Error::BadPackage(package.clone(), e))
            })?,
            exposes: package.exposes().map_err(|e| {
                sup_error!(Error::BadPackage(package.clone(), e))
            })?,
            exports: package.exports().map_err(|e| {
                sup_error!(Error::BadPackage(package.clone(), e))
            })?,
            path: package.installed_path,
            ident: package.ident.clone(),
            origin: package.ident.origin.clone(),
            name: package.ident.name.clone(),
            version: package.ident.version.expect(
                "No package version in PackageInstall",
            ),
            release: package.ident.release.expect(
                "No package release in PackageInstall",
            ),
        };
        Ok(pkg)
    }
}
<|endoftext|>


<commit_before>#![recursion_limit = "128"]

extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;

#[proc_macro_derive(NapiArgs)]
pub fn napi_args(input: TokenStream) -> TokenStream {
    let ast = syn::parse_derive_input(&input.to_string()).unwrap();
    match impl_napi_args(&ast) {
        Ok(generated) => generated.parse().unwrap(),
        Err(message) => panic!(message),
    }
}

fn impl_napi_args(
    ast: &syn::DeriveInput,
) -> Result<quote::Tokens, &'static str> {
    let name = &ast.ident;

    let variant_data = match ast.body {
        syn::Body::Struct(ref data) => data,
        _ => return Err("NapiArgs can only be derived for structs"),
    };

    let (init_list, count) = match *variant_data {
        syn::VariantData::Struct(ref fields) => {
            let inner = fields
                .iter()
                .enumerate()
                .map(|(idx, field)| {
                    let ident = field.clone().ident.unwrap();
                    quote! {
                        #ident: <_ as NapiValue>::from_sys_checked(
                            env,
                            argv[#idx],
                        )?
                    }
                })
                .collect::<Vec<_>>();

            let outer = quote! {
                { #(#inner),* }
            };

            (Some(outer), fields.len())
        }

        syn::VariantData::Tuple(ref fields) => {
            let inner = (0..fields.len())
                .map(|idx| {
                    quote! {
                        <_ as NapiValue>::from_sys_checked(env, argv[#idx])?
                    }
                })
                .collect::<Vec<_>>();

            let outer = quote! {
                ( #(#inner),* )
            };

            (Some(outer), fields.len())
        }

        syn::VariantData::Unit => (None, 0),
    };

    let construct = if let Some(init_list) = init_list {
        quote! { #name #init_list }
    } else {
        quote! { #name }
    };

    let (gen_lifetime, ref_lifetime) = if count > 0 {
        (quote! { <'env> }, quote! { 'env })
    } else {
        (quote!{}, quote!{})
    };

    Ok(quote! {
        impl<'env> ::napi::NapiArgs<'env> for #name #gen_lifetime {
            fn from_cb_info(
                env: & #ref_lifetime ::napi::NapiEnv,
                cb_info: ::napi::sys::napi_callback_info,
            ) -> ::napi::NapiResult<Self> {
                use ::napi::sys;
                use ::napi::{NapiError, NapiString, NapiValue};

                use ::std::ptr;

                let mut argc = #count;
                let mut argv = [ptr::null_mut(); #count];

                env.handle_status(unsafe {
                    sys::napi_get_cb_info(
                        env.as_sys_env(),
                        cb_info,
                        &mut argc,
                        argv.as_mut_ptr(),
                        ptr::null_mut(),
                        ptr::null_mut(),
                    )
                })?;

                if argc != #count {
                    let message = NapiString::from_str(env, &format!(
                        "Expected {} arguments, but got {}",
                        #count,
                        argc,
                    ))?;
                    return Err(NapiError::type_error(env, &message));
                }

                Ok(#construct)
            }
        }
    })
}
<commit_msg>fix(derive): fix a compiler warning<commit_after>#![recursion_limit = "128"]

extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;

#[proc_macro_derive(NapiArgs)]
pub fn napi_args(input: TokenStream) -> TokenStream {
    let ast = syn::parse_derive_input(&input.to_string()).unwrap();
    match impl_napi_args(&ast) {
        Ok(generated) => generated.parse().unwrap(),
        Err(message) => panic!(message),
    }
}

fn impl_napi_args(
    ast: &syn::DeriveInput,
) -> Result<quote::Tokens, &'static str> {
    let name = &ast.ident;

    let variant_data = match ast.body {
        syn::Body::Struct(ref data) => data,
        _ => return Err("NapiArgs can only be derived for structs"),
    };

    let (init_list, count, imports) = match *variant_data {
        syn::VariantData::Struct(ref fields) => {
            let inner = fields
                .iter()
                .enumerate()
                .map(|(idx, field)| {
                    let ident = field.clone().ident.unwrap();
                    quote! {
                        #ident: <_ as NapiValue>::from_sys_checked(
                            env,
                            argv[#idx],
                        )?
                    }
                })
                .collect::<Vec<_>>();

            let outer = quote! {
                { #(#inner),* }
            };

            let imports = quote! {
                use ::napi::NapiValue;
            };

            (Some(outer), fields.len(), imports)
        }

        syn::VariantData::Tuple(ref fields) => {
            let inner = (0..fields.len())
                .map(|idx| {
                    quote! {
                        <_ as NapiValue>::from_sys_checked(env, argv[#idx])?
                    }
                })
                .collect::<Vec<_>>();

            let outer = quote! {
                ( #(#inner),* )
            };

            (Some(outer), fields.len(), quote! {})
        }

        syn::VariantData::Unit => (None, 0, quote! {}),
    };

    let construct = if let Some(init_list) = init_list {
        quote! { #name #init_list }
    } else {
        quote! { #name }
    };

    let (gen_lifetime, ref_lifetime) = if count > 0 {
        (quote! { <'env> }, quote! { 'env })
    } else {
        (quote!{}, quote!{})
    };

    Ok(quote! {
        impl<'env> ::napi::NapiArgs<'env> for #name #gen_lifetime {
            fn from_cb_info(
                env: & #ref_lifetime ::napi::NapiEnv,
                cb_info: ::napi::sys::napi_callback_info,
            ) -> ::napi::NapiResult<Self> {
                use ::napi::sys;
                use ::napi::{NapiError, NapiString};

                use ::std::ptr;

                #imports

                let mut argc = #count;
                let mut argv = [ptr::null_mut(); #count];

                env.handle_status(unsafe {
                    sys::napi_get_cb_info(
                        env.as_sys_env(),
                        cb_info,
                        &mut argc,
                        argv.as_mut_ptr(),
                        ptr::null_mut(),
                        ptr::null_mut(),
                    )
                })?;

                if argc != #count {
                    let message = NapiString::from_str(env, &format!(
                        "Expected {} arguments, but got {}",
                        #count,
                        argc,
                    ))?;
                    return Err(NapiError::type_error(env, &message));
                }

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


<commit_before>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

use test_raftstore::*;
use test_util;

fn test_partition_write<T: Simulator>(cluster: &mut Cluster<T>) {
    cluster.run();

    let (key, value) = (b"k1", b"v1");
    cluster.must_put(key, value);
    must_get_equal(&cluster.engines[&1].kv.as_inner(), key, value);

    let region_id = cluster.get_region_id(key);

    // transfer leader to (1, 1)
    cluster.must_transfer_leader(region_id, new_peer(1, 1));

    // leader in majority, partition doesn't affect write/read
    cluster.partition(vec![1, 2, 3], vec![4, 5]);
    cluster.must_put(key, value);
    assert_eq!(cluster.get(key), Some(value.to_vec()));
    cluster.must_transfer_leader(region_id, new_peer(1, 1));
    cluster.clear_send_filters();

    // leader in minority, new leader should be elected
    cluster.partition(vec![1, 2], vec![3, 4, 5]);
    assert_eq!(cluster.must_get(key), Some(value.to_vec()));
    assert_ne!(cluster.leader_of_region(region_id).unwrap().get_id(), 1);
    assert_ne!(cluster.leader_of_region(region_id).unwrap().get_id(), 2);
    cluster.must_put(key, b"changed");
    cluster.clear_send_filters();

    // when network recover, old leader should sync data
    cluster.reset_leader_of_region(region_id);
    cluster.must_put(b"k2", b"v2");
    must_get_equal(&cluster.get_engine(1), b"k2", b"v2");
    must_get_equal(&cluster.get_engine(1), key, b"changed");
}

#[test]
fn test_node_partition_write() {
    let mut cluster = new_node_cluster(0, 5);
    test_partition_write(&mut cluster);
}

#[test]
fn test_server_partition_write() {
    let mut cluster = new_server_cluster(0, 5);
    test_partition_write(&mut cluster);
}

#[test]
fn test_secure_connect() {
    let mut cluster = new_server_cluster(0, 3);
    cluster.cfg.security = test_util::new_security_cfg(None);
    cluster.run_conf_change();

    let (key, value) = (b"k1", b"v1");
    cluster.must_put(key, value);

    for id in 1..4 {
        must_get_equal(&cluster.get_engine(id), key, value);
    }
}
<commit_msg>Fix test `test_secure_connect` (#9053)<commit_after>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

use test_raftstore::*;
use test_util;

fn test_partition_write<T: Simulator>(cluster: &mut Cluster<T>) {
    cluster.run();

    let (key, value) = (b"k1", b"v1");
    cluster.must_put(key, value);
    must_get_equal(&cluster.engines[&1].kv.as_inner(), key, value);

    let region_id = cluster.get_region_id(key);

    // transfer leader to (1, 1)
    cluster.must_transfer_leader(region_id, new_peer(1, 1));

    // leader in majority, partition doesn't affect write/read
    cluster.partition(vec![1, 2, 3], vec![4, 5]);
    cluster.must_put(key, value);
    assert_eq!(cluster.get(key), Some(value.to_vec()));
    cluster.must_transfer_leader(region_id, new_peer(1, 1));
    cluster.clear_send_filters();

    // leader in minority, new leader should be elected
    cluster.partition(vec![1, 2], vec![3, 4, 5]);
    assert_eq!(cluster.must_get(key), Some(value.to_vec()));
    assert_ne!(cluster.leader_of_region(region_id).unwrap().get_id(), 1);
    assert_ne!(cluster.leader_of_region(region_id).unwrap().get_id(), 2);
    cluster.must_put(key, b"changed");
    cluster.clear_send_filters();

    // when network recover, old leader should sync data
    cluster.reset_leader_of_region(region_id);
    cluster.must_put(b"k2", b"v2");
    must_get_equal(&cluster.get_engine(1), b"k2", b"v2");
    must_get_equal(&cluster.get_engine(1), key, b"changed");
}

#[test]
fn test_node_partition_write() {
    let mut cluster = new_node_cluster(0, 5);
    test_partition_write(&mut cluster);
}

#[test]
fn test_server_partition_write() {
    let mut cluster = new_server_cluster(0, 5);
    test_partition_write(&mut cluster);
}

#[test]
fn test_secure_connect() {
    let mut cluster = new_server_cluster(0, 3);
    cluster.cfg.security = test_util::new_security_cfg(None);
    cluster.pd_client.disable_default_operator();
    cluster.run();

    let (key, value) = (b"k1", b"v1");
    cluster.must_put(key, value);

    for id in 1..4 {
        must_get_equal(&cluster.get_engine(id), key, value);
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate opengl_graphics;
extern crate graphics;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;

use opengl_graphics::{ GlGraphics, OpenGL };
use graphics::Graphics;
use std::rc::Rc;
use std::cell::RefCell;
use piston::window::WindowSettings;
use piston::input::Button;
use piston::input::keyboard::Key;
#[cfg(feature = "include_sdl2")]
use sdl2_window::Sdl2Window as Window;
#[cfg(feature = "include_glfw")]
use glfw_window::GlfwWindow as Window;
#[cfg(feature = "include_glutin")]
use glutin_window::GlutinWindow as Window;

fn main() {
    let opengl = OpenGL::_3_2;
    let window = Window::new(
        opengl,
        WindowSettings {
            title: "piston-example-user_input".to_string(),
            size: [600, 600],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    println!("Press C to turn capture cursor on/off");

    let mut capture_cursor = false;
    let window = Rc::new(RefCell::new(window));
    let ref mut gl = GlGraphics::new(opengl);
    let mut cursor = [0.0, 0.0];
    for e in piston::events(window.clone()) {
        use piston::event::*;

        if let Some(Button::Mouse(button)) = e.press_args() {
            println!("Pressed mouse button '{:?}'", button);
        }
        if let Some(Button::Keyboard(key)) = e.press_args() {
            if key == Key::C {
                println!("Turned capture cursor on");
                capture_cursor = !capture_cursor;
                // window.set(CaptureCursor(capture_cursor));
            }

            println!("Pressed keyboard key '{:?}'", key);
        };
        if let Some(button) = e.release_args() {
            match button {
                Button::Keyboard(key) => println!("Released keyboard key '{:?}'", key),
                Button::Mouse(button) => println!("Released mouse button '{:?}'", button),
            }
        };
        e.mouse_cursor(|x, y| {
            cursor = [x, y];
            println!("Mouse moved '{} {}'", x, y);
        });
        e.mouse_scroll(|dx, dy| println!("Scrolled mouse '{}, {}'", dx, dy));
        e.mouse_relative(|dx, dy| println!("Relative mouse moved '{} {}'", dx, dy));
        e.text(|text| println!("Typed '{}'", text));
        e.resize(|w, h| println!("Resized '{}, {}'", w, h));
        if let Some(focused) = e.focus_args() {
            if focused { println!("Gained focus"); }
            else { println!("Lost focus"); }
        };
        if let Some(args) = e.render_args() {
            gl.draw(
                [0, 0, args.width as i32, args.height as i32],
                |_, g| {
                    graphics::clear([1.0; 4], g);
                    draw_rectangles(cursor, &window, g);
                }
            );
        }
        e.update(|_| {});
    }
}

fn draw_rectangles<G: Graphics>(
    cursor: [f64; 2],
    window: &RefCell<Window>,
    g: &mut G,
) {
    use piston::window::{ Size, DrawSize };
    use piston::quack::Get;

    let Size(size) = window.get();
    let DrawSize(draw_size) = window.get();
    let zoom = 0.2;
    let offset = 30.0;

    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(size[0] as f64, size[1] as f64);
    let rect_border = graphics::Rectangle::border([1.0, 0.0, 0.0, 1.0], 1.0);

    // Cursor.
    let cursor_color = [0.0, 0.0, 0.0, 1.0];
    let zoomed_cursor = [offset + cursor[0] * zoom, offset + cursor[1] * zoom];
    graphics::ellipse(
        cursor_color,
        graphics::ellipse::circle(zoomed_cursor[0], zoomed_cursor[1], 4.0),
        transform,
        g
    );

    // User coordinates.
    rect_border.draw([offset, offset, size[0] as f64 * zoom, size[1] as f64 * zoom],
        draw_state, transform, g);
    let rect_border = graphics::Rectangle::border([0.0, 0.0, 1.0, 1.0], 1.0);
    rect_border.draw(
        [
            offset + size[0] as f64 * zoom,
            offset,
            draw_size[0] as f64 * zoom,
            draw_size[1] as f64 * zoom
        ],
        draw_state, transform, g);
}
<commit_msg>Testing capture cursor<commit_after>extern crate piston;
extern crate opengl_graphics;
extern crate graphics;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;

use opengl_graphics::{ GlGraphics, OpenGL };
use graphics::Graphics;
use std::rc::Rc;
use std::cell::RefCell;
use piston::window::WindowSettings;
use piston::input::Button;
use piston::input::keyboard::Key;
#[cfg(feature = "include_sdl2")]
use sdl2_window::Sdl2Window as Window;
#[cfg(feature = "include_glfw")]
use glfw_window::GlfwWindow as Window;
#[cfg(feature = "include_glutin")]
use glutin_window::GlutinWindow as Window;

fn main() {
    let opengl = OpenGL::_3_2;
    let window = Window::new(
        opengl,
        WindowSettings {
            title: "piston-example-user_input".to_string(),
            size: [600, 600],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    println!("Press C to turn capture cursor on/off");

    let mut capture_cursor = false;
    let window = Rc::new(RefCell::new(window));
    let ref mut gl = GlGraphics::new(opengl);
    let mut cursor = [0.0, 0.0];
    for e in piston::events(window.clone()) {
        use piston::event::*;

        if let Some(Button::Mouse(button)) = e.press_args() {
            println!("Pressed mouse button '{:?}'", button);
        }
        if let Some(Button::Keyboard(key)) = e.press_args() {
            if key == Key::C {
                use piston::quack::Set;

                println!("Turned capture cursor on");
                capture_cursor = !capture_cursor;
                window.borrow_mut().set_mut(piston::window::CaptureCursor(capture_cursor));
            }

            println!("Pressed keyboard key '{:?}'", key);
        };
        if let Some(button) = e.release_args() {
            match button {
                Button::Keyboard(key) => println!("Released keyboard key '{:?}'", key),
                Button::Mouse(button) => println!("Released mouse button '{:?}'", button),
            }
        };
        e.mouse_cursor(|x, y| {
            cursor = [x, y];
            println!("Mouse moved '{} {}'", x, y);
        });
        e.mouse_scroll(|dx, dy| println!("Scrolled mouse '{}, {}'", dx, dy));
        e.mouse_relative(|dx, dy| println!("Relative mouse moved '{} {}'", dx, dy));
        e.text(|text| println!("Typed '{}'", text));
        e.resize(|w, h| println!("Resized '{}, {}'", w, h));
        if let Some(focused) = e.focus_args() {
            if focused { println!("Gained focus"); }
            else { println!("Lost focus"); }
        };
        if let Some(args) = e.render_args() {
            gl.draw(
                [0, 0, args.width as i32, args.height as i32],
                |_, g| {
                    graphics::clear([1.0; 4], g);
                    draw_rectangles(cursor, &window, g);
                }
            );
        }
        e.update(|_| {});
    }
}

fn draw_rectangles<G: Graphics>(
    cursor: [f64; 2],
    window: &RefCell<Window>,
    g: &mut G,
) {
    use piston::window::{ Size, DrawSize };
    use piston::quack::Get;

    let Size(size) = window.get();
    let DrawSize(draw_size) = window.get();
    let zoom = 0.2;
    let offset = 30.0;

    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(size[0] as f64, size[1] as f64);
    let rect_border = graphics::Rectangle::border([1.0, 0.0, 0.0, 1.0], 1.0);

    // Cursor.
    let cursor_color = [0.0, 0.0, 0.0, 1.0];
    let zoomed_cursor = [offset + cursor[0] * zoom, offset + cursor[1] * zoom];
    graphics::ellipse(
        cursor_color,
        graphics::ellipse::circle(zoomed_cursor[0], zoomed_cursor[1], 4.0),
        transform,
        g
    );

    // User coordinates.
    rect_border.draw([offset, offset, size[0] as f64 * zoom, size[1] as f64 * zoom],
        draw_state, transform, g);
    let rect_border = graphics::Rectangle::border([0.0, 0.0, 1.0, 1.0], 1.0);
    rect_border.draw(
        [
            offset + size[0] as f64 * zoom,
            offset,
            draw_size[0] as f64 * zoom,
            draw_size[1] as f64 * zoom
        ],
        draw_state, transform, g);
}
<|endoftext|>