<commit_before>//! Function interfaces for VST 2.4 API.

#![doc(hidden)]

use std::{mem, slice};
use std::cell::Cell;
use std::os::raw::{c_char, c_void};

use buffer::AudioBuffer;
use api::consts::*;
use api::{self, AEffect, ChannelProperties, TimeInfo};
use editor::{Rect, KeyCode, Key, KnobMode};
use host::Host;

/// Deprecated process function.
pub fn process_deprecated(
    _effect: *mut AEffect,
    _raw_inputs: *const *const f32,
    _raw_outputs: *mut *mut f32,
    _samples: i32,
) {
}

/// VST2.4 replacing function.
pub fn process_replacing(
    effect: *mut AEffect,
    raw_inputs: *const *const f32,
    raw_outputs: *mut *mut f32,
    samples: i32,
) {
    // Handle to the VST
    let plugin = unsafe { (*effect).get_plugin() };
    let cache = unsafe { (*effect).get_cache() };
    let info = &mut cache.info;
    let (input_count, output_count) = (info.inputs as usize, info.outputs as usize);
    let mut buffer = unsafe {
        AudioBuffer::from_raw(
            input_count,
            output_count,
            raw_inputs,
            raw_outputs,
            samples as usize,
        )
    };
    plugin.process(&mut buffer);
}

/// VST2.4 replacing function with `f64` values.
pub fn process_replacing_f64(
    effect: *mut AEffect,
    raw_inputs: *const *const f64,
    raw_outputs: *mut *mut f64,
    samples: i32,
) {
    let plugin = unsafe { (*effect).get_plugin() };
    let cache = unsafe { (*effect).get_cache() };
    let info = &mut cache.info;
    let (input_count, output_count) = (info.inputs as usize, info.outputs as usize);
    let mut buffer = unsafe {
        AudioBuffer::from_raw(
            input_count,
            output_count,
            raw_inputs,
            raw_outputs,
            samples as usize,
        )
    };
    plugin.process_f64(&mut buffer);
}

/// VST2.4 set parameter function.
pub fn set_parameter(effect: *mut AEffect, index: i32, value: f32) {
    unsafe { (*effect).get_plugin() }.set_parameter(index, value);
}

/// VST2.4 get parameter function.
pub fn get_parameter(effect: *mut AEffect, index: i32) -> f32 {
    unsafe { (*effect).get_plugin() }.get_parameter(index)
}

/// Copy a string into a destination buffer.
///
/// String will be cut at `max` characters.
fn copy_string(dst: *mut c_void, src: &str, max: usize) -> isize {
    unsafe {
        use std::cmp::min;
        use libc::{c_void, memset, memcpy};

        let dst = dst as *mut c_void;
        memset(dst, 0, max);
        memcpy(dst, src.as_ptr() as *const c_void, min(max, src.as_bytes().len()));
    }

    1 // Success
}

/// VST2.4 dispatch function. This function handles dispatching all opcodes to the VST plugin.
pub fn dispatch(
    effect: *mut AEffect,
    opcode: i32,
    index: i32,
    value: isize,
    ptr: *mut c_void,
    opt: f32,
) -> isize {
    use plugin::{CanDo, OpCode};

    // Convert passed in opcode to enum
    let opcode = OpCode::from(opcode);
    // Plugin handle
    let plugin = unsafe { (*effect).get_plugin() };

    match opcode {
        OpCode::Initialize => plugin.init(),
        OpCode::Shutdown => unsafe {
            (*effect).drop_plugin();
            drop(mem::transmute::<*mut AEffect, Box<AEffect>>(effect));
        },

        OpCode::ChangePreset => plugin.change_preset(value as i32),
        OpCode::GetCurrentPresetNum => return plugin.get_preset_num() as isize,
        OpCode::SetCurrentPresetName => plugin.set_preset_name(read_string(ptr)),
        OpCode::GetCurrentPresetName => {
            let num = plugin.get_preset_num();
            return copy_string(ptr, &plugin.get_preset_name(num), MAX_PRESET_NAME_LEN);
        }

        OpCode::GetParameterLabel => {
            return copy_string(ptr, &plugin.get_parameter_label(index), MAX_PARAM_STR_LEN)
        }
        OpCode::GetParameterDisplay => {
            return copy_string(ptr, &plugin.get_parameter_text(index), MAX_PARAM_STR_LEN)
        }
        OpCode::GetParameterName => {
            return copy_string(ptr, &plugin.get_parameter_name(index), MAX_PARAM_STR_LEN)
        }

        OpCode::SetSampleRate => plugin.set_sample_rate(opt),
        OpCode::SetBlockSize => plugin.set_block_size(value as i64),
        OpCode::StateChanged => {
            if value == 1 {
                plugin.resume();
            } else {
                plugin.suspend();
            }
        }

        OpCode::EditorGetRect => {
            if let Some(editor) = plugin.get_editor() {
                let size = editor.size();
                let pos = editor.position();

                unsafe {
                    // Given a Rect** structure
                    // TODO: Investigate whether we are given a valid Rect** pointer already
                    *(ptr as *mut *mut c_void) = Box::into_raw(Box::new(Rect {
                        left: pos.0 as i16, // x coord of position
                        top: pos.1 as i16, // y coord of position
                        right: (pos.0 + size.0) as i16, // x coord of pos + x coord of size
                        bottom: (pos.1 + size.1) as i16, // y coord of pos + y coord of size
                    })) as *mut _; // TODO: free memory
                }
            }
        }
        OpCode::EditorOpen => {
            if let Some(editor) = plugin.get_editor() {
                editor.open(ptr); //ptr is raw window handle, eg HWND* on windows
            }
        }
        OpCode::EditorClose => {
            if let Some(editor) = plugin.get_editor() {
                editor.close();
            }
        }

        OpCode::EditorIdle => {
            if let Some(editor) = plugin.get_editor() {
                editor.idle();
            }
        }

        OpCode::GetData => {
            let mut chunks = if index == 0 {
                plugin.get_bank_data()
            } else {
                plugin.get_preset_data()
            };

            chunks.shrink_to_fit();
            let len = chunks.len() as isize; // eventually we should be using ffi::size_t

            unsafe {
                *(ptr as *mut *mut c_void) = chunks.as_ptr() as *mut c_void;
            }

            mem::forget(chunks);
            return len;
        }
        OpCode::SetData => {
            let chunks = unsafe { slice::from_raw_parts(ptr as *mut u8, value as usize) };

            if index == 0 {
                plugin.load_bank_data(chunks);
            } else {
                plugin.load_preset_data(chunks);
            }
        }

        OpCode::ProcessEvents => {
            plugin.process_events(unsafe { &*(ptr as *const api::Events) });
        }
        OpCode::CanBeAutomated => return plugin.can_be_automated(index) as isize,
        OpCode::StringToParameter => {
            return plugin.string_to_parameter(index, read_string(ptr)) as isize
        }

        OpCode::GetPresetName => {
            return copy_string(ptr, &plugin.get_preset_name(index), MAX_PRESET_NAME_LEN)
        }

        OpCode::GetInputInfo => {
            if index >= 0 && index < plugin.get_info().inputs {
                unsafe {
                    let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
                    *ptr = plugin.get_input_info(index).into();
                }
            }
        }
        OpCode::GetOutputInfo => {
            if index >= 0 && index < plugin.get_info().outputs {
                unsafe {
                    let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
                    *ptr = plugin.get_output_info(index).into();
                }
            }
        }
        OpCode::GetCategory => {
            return plugin.get_info().category.into();
        }

        OpCode::GetVendorName => {
            return copy_string(ptr, &plugin.get_info().vendor, MAX_VENDOR_STR_LEN)
        }
        OpCode::GetProductName => {
            return copy_string(ptr, &plugin.get_info().name, MAX_PRODUCT_STR_LEN)
        }
        OpCode::GetVendorVersion => return plugin.get_info().version as isize,
        OpCode::VendorSpecific => return plugin.vendor_specific(index, value, ptr, opt),
        OpCode::CanDo => {
            let can_do = CanDo::from_str(&read_string(ptr));
            return plugin.can_do(can_do).into();
        }
        OpCode::GetTailSize => {
            if plugin.get_tail_size() == 0 {
                return 1;
            } else {
                return plugin.get_tail_size();
            }
        }

        //OpCode::GetParamInfo => { /*TODO*/ }
        OpCode::GetApiVersion => return 2400,

        OpCode::EditorKeyDown => {
            if let Some(editor) = plugin.get_editor() {
                editor.key_down(KeyCode {
                    character: index as u8 as char,
                    key: Key::from(value),
                    modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8,
                });
            }
        }
        OpCode::EditorKeyUp => {
            if let Some(editor) = plugin.get_editor() {
                editor.key_up(KeyCode {
                    character: index as u8 as char,
                    key: Key::from(value),
                    modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8,
                });
            }
        }
        OpCode::EditorSetKnobMode => {
            if let Some(editor) = plugin.get_editor() {
                editor.set_knob_mode(KnobMode::from(value));
            }
        }

        OpCode::StartProcess => plugin.start_process(),
        OpCode::StopProcess => plugin.stop_process(),

        OpCode::GetNumMidiInputs => {
            return plugin.get_info().midi_inputs as isize;
        }
        OpCode::GetNumMidiOutputs => {
            return plugin.get_info().midi_outputs as isize;
        }

        _ => {
            debug!("Unimplemented opcode ({:?})", opcode);
            trace!(
                "Arguments; index: {}, value: {}, ptr: {:?}, opt: {}",
                index,
                value,
                ptr,
                opt
            );
        }
    }

    0
}

pub fn host_dispatch(
    host: &mut Host,
    effect: *mut AEffect,
    opcode: i32,
    index: i32,
    value: isize,
    ptr: *mut c_void,
    opt: f32,
) -> isize {
    use host::OpCode;

    match OpCode::from(opcode) {
        OpCode::Version => return 2400,
        OpCode::Automate => host.automate(index, opt),

        OpCode::Idle => host.idle(),

        // ...
        OpCode::CanDo => {
            info!("Plugin is asking if host can: {}.", read_string(ptr));
        }

        OpCode::GetVendorVersion => return host.get_info().0,
        OpCode::GetVendorString => return copy_string(ptr, &host.get_info().1, MAX_VENDOR_STR_LEN),
        OpCode::GetProductString => {
            return copy_string(ptr, &host.get_info().2, MAX_PRODUCT_STR_LEN)
        }
        OpCode::ProcessEvents => {
            host.process_events(unsafe { &*(ptr as *const api::Events) });
        }

        OpCode::GetTime => {
            return match host.get_time_info(value as i32) {
                None => 0,
                Some(result) => {
                    thread_local! {
                        static TIME_INFO: Cell<TimeInfo> =
                            Cell::new(TimeInfo::default());
                    }
                    TIME_INFO.with(|time_info| {
                        (*time_info).set(result);
                        time_info.as_ptr() as isize
                    })
                }
            };
        }
        OpCode::GetBlockSize => return host.get_block_size(),

        unimplemented => {
            trace!("VST: Got unimplemented host opcode ({:?})", unimplemented);
            trace!(
                "Arguments; effect: {:?}, index: {}, value: {}, ptr: {:?}, opt: {}",
                effect,
                index,
                value,
                ptr,
                opt
            );
        }
    }
    0
}

// Read a string from the `ptr` buffer
fn read_string(ptr: *mut c_void) -> String {
    use std::ffi::CStr;

    String::from_utf8_lossy(unsafe { CStr::from_ptr(ptr as *mut c_char).to_bytes() }).into_owned()
}
<commit_msg>Use plugin cache to get number of midi in- and outputs<commit_after>//! Function interfaces for VST 2.4 API.

#![doc(hidden)]

use std::{mem, slice};
use std::cell::Cell;
use std::os::raw::{c_char, c_void};

use buffer::AudioBuffer;
use api::consts::*;
use api::{self, AEffect, ChannelProperties, TimeInfo};
use editor::{Rect, KeyCode, Key, KnobMode};
use host::Host;

/// Deprecated process function.
pub fn process_deprecated(
    _effect: *mut AEffect,
    _raw_inputs: *const *const f32,
    _raw_outputs: *mut *mut f32,
    _samples: i32,
) {
}

/// VST2.4 replacing function.
pub fn process_replacing(
    effect: *mut AEffect,
    raw_inputs: *const *const f32,
    raw_outputs: *mut *mut f32,
    samples: i32,
) {
    // Handle to the VST
    let plugin = unsafe { (*effect).get_plugin() };
    let cache = unsafe { (*effect).get_cache() };
    let info = &mut cache.info;
    let (input_count, output_count) = (info.inputs as usize, info.outputs as usize);
    let mut buffer = unsafe {
        AudioBuffer::from_raw(
            input_count,
            output_count,
            raw_inputs,
            raw_outputs,
            samples as usize,
        )
    };
    plugin.process(&mut buffer);
}

/// VST2.4 replacing function with `f64` values.
pub fn process_replacing_f64(
    effect: *mut AEffect,
    raw_inputs: *const *const f64,
    raw_outputs: *mut *mut f64,
    samples: i32,
) {
    let plugin = unsafe { (*effect).get_plugin() };
    let cache = unsafe { (*effect).get_cache() };
    let info = &mut cache.info;
    let (input_count, output_count) = (info.inputs as usize, info.outputs as usize);
    let mut buffer = unsafe {
        AudioBuffer::from_raw(
            input_count,
            output_count,
            raw_inputs,
            raw_outputs,
            samples as usize,
        )
    };
    plugin.process_f64(&mut buffer);
}

/// VST2.4 set parameter function.
pub fn set_parameter(effect: *mut AEffect, index: i32, value: f32) {
    unsafe { (*effect).get_plugin() }.set_parameter(index, value);
}

/// VST2.4 get parameter function.
pub fn get_parameter(effect: *mut AEffect, index: i32) -> f32 {
    unsafe { (*effect).get_plugin() }.get_parameter(index)
}

/// Copy a string into a destination buffer.
///
/// String will be cut at `max` characters.
fn copy_string(dst: *mut c_void, src: &str, max: usize) -> isize {
    unsafe {
        use std::cmp::min;
        use libc::{c_void, memset, memcpy};

        let dst = dst as *mut c_void;
        memset(dst, 0, max);
        memcpy(dst, src.as_ptr() as *const c_void, min(max, src.as_bytes().len()));
    }

    1 // Success
}

/// VST2.4 dispatch function. This function handles dispatching all opcodes to the VST plugin.
pub fn dispatch(
    effect: *mut AEffect,
    opcode: i32,
    index: i32,
    value: isize,
    ptr: *mut c_void,
    opt: f32,
) -> isize {
    use plugin::{CanDo, OpCode};

    // Convert passed in opcode to enum
    let opcode = OpCode::from(opcode);
    // Plugin handle
    let plugin = unsafe { (*effect).get_plugin() };

    match opcode {
        OpCode::Initialize => plugin.init(),
        OpCode::Shutdown => unsafe {
            (*effect).drop_plugin();
            drop(mem::transmute::<*mut AEffect, Box<AEffect>>(effect));
        },

        OpCode::ChangePreset => plugin.change_preset(value as i32),
        OpCode::GetCurrentPresetNum => return plugin.get_preset_num() as isize,
        OpCode::SetCurrentPresetName => plugin.set_preset_name(read_string(ptr)),
        OpCode::GetCurrentPresetName => {
            let num = plugin.get_preset_num();
            return copy_string(ptr, &plugin.get_preset_name(num), MAX_PRESET_NAME_LEN);
        }

        OpCode::GetParameterLabel => {
            return copy_string(ptr, &plugin.get_parameter_label(index), MAX_PARAM_STR_LEN)
        }
        OpCode::GetParameterDisplay => {
            return copy_string(ptr, &plugin.get_parameter_text(index), MAX_PARAM_STR_LEN)
        }
        OpCode::GetParameterName => {
            return copy_string(ptr, &plugin.get_parameter_name(index), MAX_PARAM_STR_LEN)
        }

        OpCode::SetSampleRate => plugin.set_sample_rate(opt),
        OpCode::SetBlockSize => plugin.set_block_size(value as i64),
        OpCode::StateChanged => {
            if value == 1 {
                plugin.resume();
            } else {
                plugin.suspend();
            }
        }

        OpCode::EditorGetRect => {
            if let Some(editor) = plugin.get_editor() {
                let size = editor.size();
                let pos = editor.position();

                unsafe {
                    // Given a Rect** structure
                    // TODO: Investigate whether we are given a valid Rect** pointer already
                    *(ptr as *mut *mut c_void) = Box::into_raw(Box::new(Rect {
                        left: pos.0 as i16, // x coord of position
                        top: pos.1 as i16, // y coord of position
                        right: (pos.0 + size.0) as i16, // x coord of pos + x coord of size
                        bottom: (pos.1 + size.1) as i16, // y coord of pos + y coord of size
                    })) as *mut _; // TODO: free memory
                }
            }
        }
        OpCode::EditorOpen => {
            if let Some(editor) = plugin.get_editor() {
                editor.open(ptr); //ptr is raw window handle, eg HWND* on windows
            }
        }
        OpCode::EditorClose => {
            if let Some(editor) = plugin.get_editor() {
                editor.close();
            }
        }

        OpCode::EditorIdle => {
            if let Some(editor) = plugin.get_editor() {
                editor.idle();
            }
        }

        OpCode::GetData => {
            let mut chunks = if index == 0 {
                plugin.get_bank_data()
            } else {
                plugin.get_preset_data()
            };

            chunks.shrink_to_fit();
            let len = chunks.len() as isize; // eventually we should be using ffi::size_t

            unsafe {
                *(ptr as *mut *mut c_void) = chunks.as_ptr() as *mut c_void;
            }

            mem::forget(chunks);
            return len;
        }
        OpCode::SetData => {
            let chunks = unsafe { slice::from_raw_parts(ptr as *mut u8, value as usize) };

            if index == 0 {
                plugin.load_bank_data(chunks);
            } else {
                plugin.load_preset_data(chunks);
            }
        }

        OpCode::ProcessEvents => {
            plugin.process_events(unsafe { &*(ptr as *const api::Events) });
        }
        OpCode::CanBeAutomated => return plugin.can_be_automated(index) as isize,
        OpCode::StringToParameter => {
            return plugin.string_to_parameter(index, read_string(ptr)) as isize
        }

        OpCode::GetPresetName => {
            return copy_string(ptr, &plugin.get_preset_name(index), MAX_PRESET_NAME_LEN)
        }

        OpCode::GetInputInfo => {
            if index >= 0 && index < plugin.get_info().inputs {
                unsafe {
                    let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
                    *ptr = plugin.get_input_info(index).into();
                }
            }
        }
        OpCode::GetOutputInfo => {
            if index >= 0 && index < plugin.get_info().outputs {
                unsafe {
                    let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
                    *ptr = plugin.get_output_info(index).into();
                }
            }
        }
        OpCode::GetCategory => {
            return plugin.get_info().category.into();
        }

        OpCode::GetVendorName => {
            return copy_string(ptr, &plugin.get_info().vendor, MAX_VENDOR_STR_LEN)
        }
        OpCode::GetProductName => {
            return copy_string(ptr, &plugin.get_info().name, MAX_PRODUCT_STR_LEN)
        }
        OpCode::GetVendorVersion => return plugin.get_info().version as isize,
        OpCode::VendorSpecific => return plugin.vendor_specific(index, value, ptr, opt),
        OpCode::CanDo => {
            let can_do = CanDo::from_str(&read_string(ptr));
            return plugin.can_do(can_do).into();
        }
        OpCode::GetTailSize => {
            if plugin.get_tail_size() == 0 {
                return 1;
            } else {
                return plugin.get_tail_size();
            }
        }

        //OpCode::GetParamInfo => { /*TODO*/ }
        OpCode::GetApiVersion => return 2400,

        OpCode::EditorKeyDown => {
            if let Some(editor) = plugin.get_editor() {
                editor.key_down(KeyCode {
                    character: index as u8 as char,
                    key: Key::from(value),
                    modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8,
                });
            }
        }
        OpCode::EditorKeyUp => {
            if let Some(editor) = plugin.get_editor() {
                editor.key_up(KeyCode {
                    character: index as u8 as char,
                    key: Key::from(value),
                    modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8,
                });
            }
        }
        OpCode::EditorSetKnobMode => {
            if let Some(editor) = plugin.get_editor() {
                editor.set_knob_mode(KnobMode::from(value));
            }
        }

        OpCode::StartProcess => plugin.start_process(),
        OpCode::StopProcess => plugin.stop_process(),

        OpCode::GetNumMidiInputs => {
            return unsafe { (*effect).get_cache() }.info.midi_inputs as isize
        }
        OpCode::GetNumMidiOutputs => {
            return unsafe { (*effect).get_cache() }.info.midi_outputs as isize
        }

        _ => {
            debug!("Unimplemented opcode ({:?})", opcode);
            trace!(
                "Arguments; index: {}, value: {}, ptr: {:?}, opt: {}",
                index,
                value,
                ptr,
                opt
            );
        }
    }

    0
}

pub fn host_dispatch(
    host: &mut Host,
    effect: *mut AEffect,
    opcode: i32,
    index: i32,
    value: isize,
    ptr: *mut c_void,
    opt: f32,
) -> isize {
    use host::OpCode;

    match OpCode::from(opcode) {
        OpCode::Version => return 2400,
        OpCode::Automate => host.automate(index, opt),

        OpCode::Idle => host.idle(),

        // ...
        OpCode::CanDo => {
            info!("Plugin is asking if host can: {}.", read_string(ptr));
        }

        OpCode::GetVendorVersion => return host.get_info().0,
        OpCode::GetVendorString => return copy_string(ptr, &host.get_info().1, MAX_VENDOR_STR_LEN),
        OpCode::GetProductString => {
            return copy_string(ptr, &host.get_info().2, MAX_PRODUCT_STR_LEN)
        }
        OpCode::ProcessEvents => {
            host.process_events(unsafe { &*(ptr as *const api::Events) });
        }

        OpCode::GetTime => {
            return match host.get_time_info(value as i32) {
                None => 0,
                Some(result) => {
                    thread_local! {
                        static TIME_INFO: Cell<TimeInfo> =
                            Cell::new(TimeInfo::default());
                    }
                    TIME_INFO.with(|time_info| {
                        (*time_info).set(result);
                        time_info.as_ptr() as isize
                    })
                }
            };
        }
        OpCode::GetBlockSize => return host.get_block_size(),

        unimplemented => {
            trace!("VST: Got unimplemented host opcode ({:?})", unimplemented);
            trace!(
                "Arguments; effect: {:?}, index: {}, value: {}, ptr: {:?}, opt: {}",
                effect,
                index,
                value,
                ptr,
                opt
            );
        }
    }
    0
}

// Read a string from the `ptr` buffer
fn read_string(ptr: *mut c_void) -> String {
    use std::ffi::CStr;

    String::from_utf8_lossy(unsafe { CStr::from_ptr(ptr as *mut c_char).to_bytes() }).into_owned()
}
<|endoftext|>


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

use serde::Deserialize;

#[derive(PartialEq, Debug, Deserialize, Default)]
#[serde(rename_all = "kebab-case")]
pub struct TargetFormat {
    #[serde(rename = "format?", default)]
    pub format: bool,
    pub format_options: Option<String>,
}

#[test]
fn deserialize() {
    use pretty_assertions::assert_eq;
    use serde_json::json;

    assert_eq!(
        TargetFormat {
            format: true,
            format_options: Some("-fs ext2".to_string()),
        },
        serde_json::from_value::<TargetFormat>(json!({
            "format?": true,
            "format-options": "-fs ext2"
        }))
        .unwrap()
    );

    assert_eq!(
        TargetFormat {
            format: false,
            format_options: None,
        },
        serde_json::from_value::<TargetFormat>(json!({
            "format?": false,
        }))
        .unwrap()
    );
}
<commit_msg>update_package::object::definitions::TargetFormat: Test default result<commit_after>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use serde::Deserialize;

#[derive(PartialEq, Debug, Deserialize, Default)]
#[serde(rename_all = "kebab-case")]
pub struct TargetFormat {
    #[serde(rename = "format?", default)]
    pub format: bool,
    pub format_options: Option<String>,
}

#[test]
fn deserialize() {
    use pretty_assertions::assert_eq;
    use serde_json::json;

    assert_eq!(
        TargetFormat {
            format: true,
            format_options: Some("-fs ext2".to_string()),
        },
        serde_json::from_value::<TargetFormat>(json!({
            "format?": true,
            "format-options": "-fs ext2"
        }))
        .unwrap()
    );

    assert_eq!(
        TargetFormat {
            format: false,
            format_options: None,
        },
        serde_json::from_value::<TargetFormat>(json!({
            "format?": false,
        }))
        .unwrap()
    );
}

#[test]
fn default() {
    use pretty_assertions::assert_eq;

    assert_eq!(
        TargetFormat {
            format: false,
            format_options: None,
        },
        TargetFormat::default(),
    );
}
<|endoftext|>


<commit_before>extern crate centralgithook;
extern crate tempdir;
#[macro_use] extern crate log;
extern crate env_logger;

mod helpers;

use centralgithook::migrate::RepoHost;
use centralgithook::migrate;
use tempdir::TempDir;

#[test]
fn test_initial_import()
{
    env_logger::init().unwrap();
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let central = helpers::TestRepo::new(&td.path().join("central"));
    let host = helpers::TestHost::new();
    let scratch = migrate::Scratch::new(&td.path().join("scratch"), &host);
    let shell = migrate::Shell { cwd: td.path().to_path_buf() };

    host.create_project("central");
    central.shell.command(&format!("git remote add origin {}", &host.remote_url("central")));

    central.add_file("modules/module_a/initial_a");
    central.add_file("modules/module_b/initial_b");
    let head = central.commit("initial");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch,
                            scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    shell.command(&format!("git clone {}", &host.remote_url("modules/module_a")));
    shell.command(&format!("git clone {}", &host.remote_url("modules/module_b")));
    let module_a = helpers::TestRepo::new(&td.path().join("module_a"));
    let module_b = helpers::TestRepo::new(&td.path().join("module_b"));

    assert!(module_a.has_file("initial_a"));
    assert!(module_b.has_file("initial_b"));

    central.add_file("modules/module_a/added_a");
    central.add_file("modules/module_c/added_c");
    let head = central.commit("add");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch, scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    module_a.shell.command("git pull");
    shell.command(&format!("git clone {}", &host.remote_url("modules/module_c")));
    let module_c = helpers::TestRepo::new(&td.path().join("module_c"));

    assert!(module_a.has_file("added_a"));
    assert!(module_c.has_file("added_c"));

    module_a.add_file("added/in_mod_a");
    let head = module_a.commit("module_a_commit");

    migrate::module_review_upload(&scratch,
                                  scratch.transfer(&head, &module_a.path),
                                  "modules/module_a",
                                  "central")
        .expect("module_review_upload failed");

    central.shell.command("git fetch origin for/master:for/master");
    let for_master = central.rev("for/master");

    migrate::central_submit(&scratch, scratch.transfer(&for_master, &host.repo_dir("central")))
        .expect("call central_submit");

    central.shell.command("git rebase for/master");
    assert_eq!(central.rev("master"), central.rev("for/master"));
    assert_eq!(central.rev("master"), central.rev("HEAD"));
    assert!(central.has_file("modules/module_a/added/in_mod_a"));

    module_a.shell.command("git pull");
    assert_eq!(module_a.rev("origin/master"), head);
}
<commit_msg>fix formating<commit_after>extern crate centralgithook;
extern crate tempdir;
#[macro_use]
extern crate log;
extern crate env_logger;

mod helpers;

use centralgithook::migrate::RepoHost;
use centralgithook::migrate;
use tempdir::TempDir;

#[test]
fn test_initial_import()
{
    env_logger::init().unwrap();
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let central = helpers::TestRepo::new(&td.path().join("central"));
    let host = helpers::TestHost::new();
    let scratch = migrate::Scratch::new(&td.path().join("scratch"), &host);
    let shell = migrate::Shell { cwd: td.path().to_path_buf() };

    host.create_project("central");
    central.shell.command(&format!("git remote add origin {}",
                                   &host.remote_url("central")));

    central.add_file("modules/module_a/initial_a");
    central.add_file("modules/module_b/initial_b");
    let head = central.commit("initial");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch,
                            scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    shell.command(&format!("git clone {}",
                           &host.remote_url("modules/module_a")));
    shell.command(&format!("git clone {}",
                           &host.remote_url("modules/module_b")));
    let module_a = helpers::TestRepo::new(&td.path().join("module_a"));
    let module_b = helpers::TestRepo::new(&td.path().join("module_b"));

    assert!(module_a.has_file("initial_a"));
    assert!(module_b.has_file("initial_b"));

    central.add_file("modules/module_a/added_a");
    central.add_file("modules/module_c/added_c");
    let head = central.commit("add");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch,
                            scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    module_a.shell.command("git pull");
    shell.command(&format!("git clone {}",
                           &host.remote_url("modules/module_c")));
    let module_c = helpers::TestRepo::new(&td.path().join("module_c"));

    assert!(module_a.has_file("added_a"));
    assert!(module_c.has_file("added_c"));

    module_a.add_file("added/in_mod_a");
    let head = module_a.commit("module_a_commit");

    migrate::module_review_upload(&scratch,
                                  scratch.transfer(&head, &module_a.path),
                                  "modules/module_a",
                                  "central")
        .expect("module_review_upload failed");

    central.shell.command("git fetch origin for/master:for/master");
    let for_master = central.rev("for/master");

    migrate::central_submit(&scratch,
                            scratch.transfer(&for_master, &host.repo_dir("central")))
        .expect("call central_submit");

    central.shell.command("git rebase for/master");
    assert_eq!(central.rev("master"), central.rev("for/master"));
    assert_eq!(central.rev("master"), central.rev("HEAD"));
    assert!(central.has_file("modules/module_a/added/in_mod_a"));

    module_a.shell.command("git pull");
    assert_eq!(module_a.rev("origin/master"), head);
}
<|endoftext|>


<commit_before>use std::io;

use byteorder::{ReadBytesExt, LittleEndian};

const EXT4_BLOCK_GROUP_INODES_UNUSED: u16 = 0b1;
const EXT4_BLOCK_GROUP_BLOCKS_UNUSED: u16 = 0b10;

#[derive(Debug)]
struct Entry {
    inode_table_block: u64,
    inodes: u32,
}

#[derive(Debug)]
pub struct BlockGroups{
    groups: Vec<Entry>,
    inodes_per_group: u32,
    pub block_size: u32,
    pub inode_size: u16,
}

impl BlockGroups {
    pub fn new<R>(
        mut inner: R,
        blocks_count: u64,
        s_desc_size: u16,
        s_inodes_per_group: u32,
        block_size: u32,
        inode_size: u16) -> io::Result<BlockGroups>
    where R: io::Read + io::Seek {
        let blocks_count = ::usize_check(blocks_count)?;

        let mut groups = Vec::with_capacity(blocks_count);

        for block in 0..blocks_count {
//            let bg_block_bitmap_lo =
                inner.read_u32::<LittleEndian>()?; /* Blocks bitmap block */
//            let bg_inode_bitmap_lo =
                inner.read_u32::<LittleEndian>()?; /* Inodes bitmap block */
            let bg_inode_table_lo =
                inner.read_u32::<LittleEndian>()?; /* Inodes table block */
//            let bg_free_blocks_count_lo =
                inner.read_u16::<LittleEndian>()?; /* Free blocks count */
            let bg_free_inodes_count_lo =
                inner.read_u16::<LittleEndian>()?; /* Free inodes count */
//            let bg_used_dirs_count_lo =
                inner.read_u16::<LittleEndian>()?; /* Directories count */
            let bg_flags =
                inner.read_u16::<LittleEndian>()?; /* EXT4_BG_flags (INODE_UNINIT, etc) */
//            let bg_exclude_bitmap_lo =
                inner.read_u32::<LittleEndian>()?; /* Exclude bitmap for snapshots */
//            let bg_block_bitmap_csum_lo =
                inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+bbitmap) LE */
//            let bg_inode_bitmap_csum_lo =
                inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+ibitmap) LE */
//            let bg_itable_unused_lo =
                inner.read_u16::<LittleEndian>()?; /* Unused inodes count */
//            let bg_checksum =
                inner.read_u16::<LittleEndian>()?; /* crc16(sb_uuid+group+desc) */

//            let bg_block_bitmap_hi =
                if s_desc_size < 4 { None } else {
                    Some(inner.read_u32::<LittleEndian>()?) /* Blocks bitmap block MSB */
                };
//            let bg_inode_bitmap_hi =
                if s_desc_size < 4 + 4 { None } else {
                    Some(inner.read_u32::<LittleEndian>()?) /* Inodes bitmap block MSB */
                };
            let bg_inode_table_hi =
                if s_desc_size < 4 + 4 + 4 { None } else {
                    Some(inner.read_u32::<LittleEndian>()?) /* Inodes table block MSB */
                };
//            let bg_free_blocks_count_hi =
                if s_desc_size < 4 + 4 + 4 + 2 { None } else {
                    Some(inner.read_u16::<LittleEndian>()?) /* Free blocks count MSB */
                };
            let bg_free_inodes_count_hi =
                if s_desc_size < 4 + 4 + 4 + 2 + 2 { None } else {
                    Some(inner.read_u16::<LittleEndian>()?) /* Free inodes count MSB */
                };

//          let bg_used_dirs_count_hi =
//              inner.read_u16::<LittleEndian>()?; /* Directories count MSB */
//          let bg_itable_unused_hi =
//              inner.read_u16::<LittleEndian>()?; /* Unused inodes count MSB */
//          let bg_exclude_bitmap_hi =
//              inner.read_u32::<LittleEndian>()?; /* Exclude bitmap block MSB */
//          let bg_block_bitmap_csum_hi =
//              inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+bbitmap) BE */
//          let bg_inode_bitmap_csum_hi =
//              inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+ibitmap) BE */

            if s_desc_size > 16 {
                inner.seek(io::SeekFrom::Current((s_desc_size - 16) as i64))?;
            }

            let inode_table_block = bg_inode_table_lo as u64
                | ((bg_inode_table_hi.unwrap_or(0) as u64) << 32);
            let free_inodes_count = bg_free_inodes_count_lo as u32
                | ((bg_free_inodes_count_hi.unwrap_or(0) as u32) << 16);

            let unallocated = bg_flags & EXT4_BLOCK_GROUP_INODES_UNUSED != 0 || bg_flags & EXT4_BLOCK_GROUP_BLOCKS_UNUSED != 0;

            if free_inodes_count > s_inodes_per_group {
                return Err(::parse_error(format!("too many free inodes in group {}: {} > {}",
                                               block, free_inodes_count, s_inodes_per_group)));
            }

            let inodes = if unallocated {
                0
            } else {
                s_inodes_per_group - free_inodes_count
            };

            groups.push(Entry {
                inode_table_block,
                inodes,
            });
        }

        Ok(BlockGroups {
            groups,
            inodes_per_group: s_inodes_per_group,
            block_size,
            inode_size
        })
    }

    pub fn index_of(&self, inode: u32) -> u64 {
        assert_ne!(0, inode);

        let inode = inode - 1;
        let group_number = inode / self.inodes_per_group;
        let group = &self.groups[group_number as usize];
        let inode_index_in_group = inode % self.inodes_per_group;
        assert!(inode_index_in_group < group.inodes,
                "inode <{}> number must fit in group: {} is greater than {} for group {}",
                inode + 1,
                inode_index_in_group, group.inodes, group_number);
        let block = group.inode_table_block;
        block * self.block_size as u64 + inode_index_in_group as u64 * self.inode_size as u64
    }
}
<commit_msg>maths/logic error in block parser -> nonsense<commit_after>use std::io;

use byteorder::{ReadBytesExt, LittleEndian};

const EXT4_BLOCK_GROUP_INODES_UNUSED: u16 = 0b1;
const EXT4_BLOCK_GROUP_BLOCKS_UNUSED: u16 = 0b10;

#[derive(Debug)]
struct Entry {
    inode_table_block: u64,
    inodes: u32,
}

#[derive(Debug)]
pub struct BlockGroups{
    groups: Vec<Entry>,
    inodes_per_group: u32,
    pub block_size: u32,
    pub inode_size: u16,
}

impl BlockGroups {
    pub fn new<R>(
        mut inner: R,
        blocks_count: u64,
        s_desc_size: u16,
        s_inodes_per_group: u32,
        block_size: u32,
        inode_size: u16) -> io::Result<BlockGroups>
    where R: io::Read + io::Seek {
        let blocks_count = ::usize_check(blocks_count)?;

        let mut groups = Vec::with_capacity(blocks_count);

        for block in 0..blocks_count {
//            let bg_block_bitmap_lo =
                inner.read_u32::<LittleEndian>()?; /* Blocks bitmap block */
//            let bg_inode_bitmap_lo =
                inner.read_u32::<LittleEndian>()?; /* Inodes bitmap block */
            let bg_inode_table_lo =
                inner.read_u32::<LittleEndian>()?; /* Inodes table block */
//            let bg_free_blocks_count_lo =
                inner.read_u16::<LittleEndian>()?; /* Free blocks count */
            let bg_free_inodes_count_lo =
                inner.read_u16::<LittleEndian>()?; /* Free inodes count */
//            let bg_used_dirs_count_lo =
                inner.read_u16::<LittleEndian>()?; /* Directories count */
            let bg_flags =
                inner.read_u16::<LittleEndian>()?; /* EXT4_BG_flags (INODE_UNINIT, etc) */
//            let bg_exclude_bitmap_lo =
                inner.read_u32::<LittleEndian>()?; /* Exclude bitmap for snapshots */
//            let bg_block_bitmap_csum_lo =
                inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+bbitmap) LE */
//            let bg_inode_bitmap_csum_lo =
                inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+ibitmap) LE */
//            let bg_itable_unused_lo =
                inner.read_u16::<LittleEndian>()?; /* Unused inodes count */
//            let bg_checksum =
                inner.read_u16::<LittleEndian>()?; /* crc16(sb_uuid+group+desc) */

//            let bg_block_bitmap_hi =
                if s_desc_size < 4 { None } else {
                    Some(inner.read_u32::<LittleEndian>()?) /* Blocks bitmap block MSB */
                };
//            let bg_inode_bitmap_hi =
                if s_desc_size < 4 + 4 { None } else {
                    Some(inner.read_u32::<LittleEndian>()?) /* Inodes bitmap block MSB */
                };
            let bg_inode_table_hi =
                if s_desc_size < 4 + 4 + 4 { None } else {
                    Some(inner.read_u32::<LittleEndian>()?) /* Inodes table block MSB */
                };
//            let bg_free_blocks_count_hi =
                if s_desc_size < 4 + 4 + 4 + 2 { None } else {
                    Some(inner.read_u16::<LittleEndian>()?) /* Free blocks count MSB */
                };
            let bg_free_inodes_count_hi =
                if s_desc_size < 4 + 4 + 4 + 2 + 2 { None } else {
                    Some(inner.read_u16::<LittleEndian>()?) /* Free inodes count MSB */
                };

//          let bg_used_dirs_count_hi =
//              inner.read_u16::<LittleEndian>()?; /* Directories count MSB */
//          let bg_itable_unused_hi =
//              inner.read_u16::<LittleEndian>()?; /* Unused inodes count MSB */
//          let bg_exclude_bitmap_hi =
//              inner.read_u32::<LittleEndian>()?; /* Exclude bitmap block MSB */
//          let bg_block_bitmap_csum_hi =
//              inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+bbitmap) BE */
//          let bg_inode_bitmap_csum_hi =
//              inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+ibitmap) BE */

            if s_desc_size > 16 + 32 {
                inner.seek(io::SeekFrom::Current((s_desc_size - 32 - 16) as i64))?;
            }

            let inode_table_block = bg_inode_table_lo as u64
                | ((bg_inode_table_hi.unwrap_or(0) as u64) << 32);
            let free_inodes_count = bg_free_inodes_count_lo as u32
                | ((bg_free_inodes_count_hi.unwrap_or(0) as u32) << 16);

            let unallocated = bg_flags & EXT4_BLOCK_GROUP_INODES_UNUSED != 0 || bg_flags & EXT4_BLOCK_GROUP_BLOCKS_UNUSED != 0;

            if free_inodes_count > s_inodes_per_group {
                return Err(::parse_error(format!("too many free inodes in group {}: {} > {}",
                                               block, free_inodes_count, s_inodes_per_group)));
            }

            let inodes = if unallocated {
                0
            } else {
                s_inodes_per_group - free_inodes_count
            };

            groups.push(Entry {
                inode_table_block,
                inodes,
            });
        }

        Ok(BlockGroups {
            groups,
            inodes_per_group: s_inodes_per_group,
            block_size,
            inode_size
        })
    }

    pub fn index_of(&self, inode: u32) -> u64 {
        assert_ne!(0, inode);

        let inode = inode - 1;
        let group_number = inode / self.inodes_per_group;
        let group = &self.groups[group_number as usize];
        let inode_index_in_group = inode % self.inodes_per_group;
        assert!(inode_index_in_group < group.inodes,
                "inode <{}> number must fit in group: {} is greater than {} for group {}",
                inode + 1,
                inode_index_in_group, group.inodes, group_number);
        let block = group.inode_table_block;
        block * self.block_size as u64 + inode_index_in_group as u64 * self.inode_size as u64
    }
}
<|endoftext|>


<commit_before>use rustbox::{Color, RustBox, Style};

pub struct UIBuffer {
    width: uint,
    height: uint,
    rows: Vec<Vec<Cell>>
}

impl UIBuffer {
    pub fn new(width: uint, height: uint) -> UIBuffer {
        let rows = Cell::create_grid(width, height, ' ');

        UIBuffer {
            width: width,
            height: height,
            rows: rows,
        }
    }

    pub fn draw_range(&mut self, rb: &RustBox, start: uint, stop: uint) {
        let rows = self.rows.slice_mut(start, stop);
        for row in rows.iter_mut() {
            for cell in row.iter_mut().filter(|cell| cell.dirty) {
                rb.print_char(cell.x, cell.y, Style::empty(), cell.fg, cell.bg, cell.ch);
                cell.dirty = false;
            }
        }
    }

    pub fn draw_everything(&mut self, rb: &RustBox) {
        let height = self.height;
        self.draw_range(rb, 0, height);
    }

    pub fn get_width(&self) -> uint {
        self.width
    }

    pub fn get_height(&self) -> uint {
        self.height
    }

    /// Set all cells to `ch`.
    pub fn fill(&mut self, ch: char) {
        for row in range(0, self.height) {
            for col in range(0, self.width) {
                self.rows[row][col].set_char(ch)
            }
        }
    }

    /// Update the `ch` attribute of an individual cell
    pub fn update_cell_content(&mut self, cell_num: uint, row_num: uint, ch: char) {
        self.rows[row_num][cell_num].set_char(ch);
    }

    /// Update the `ch`, `fg`, and `bg` attributes of an indivudual cell
    pub fn update_cell(&mut self, cell_num: uint, row_num: uint, ch: char, fg: Color, bg: Color) {
        self.get_cell_mut(cell_num, row_num).set(ch, fg, bg);
    }

    pub fn get_cell_mut(&mut self, cell_num: uint, row_num: uint) -> &mut Cell {
        &mut self.rows[row_num][cell_num]
    }
}

pub struct Cell {
    pub bg: Color,
    pub fg: Color,
    pub ch: char,
    pub x: uint,
    pub y: uint,
    pub dirty: bool
}

impl Cell {
    pub fn new() -> Cell {
        Cell {
            bg: Color::Default,
            fg: Color::Default,
            ch: ' ',
            x: 0,
            y: 0,
            dirty: true
        }
    }

    pub fn set_char(&mut self, ch: char) {
        if self.ch != ch {
            self.dirty = true;
            self.ch = ch;
        }
    }

    pub fn set(&mut self, ch: char, fg: Color, bg: Color) {
        if self.ch != ch || self.fg != fg || self.bg != bg {
            self.dirty = true;
        }
        self.ch = ch;
        self.fg = fg;
        self.bg = bg;
    }

    pub fn create_grid(width: uint, height: uint, ch: char) -> Vec<Vec<Cell>> {
        let mut rows = Vec::new();
        for voffset in range(0, height) {
            let mut cells = Vec::new();
            for boffset in range(0, width) {
                let mut cell = Cell::new();
                cell.x = boffset;
                cell.y = voffset;
                cell.ch = ch;
                cells.push(cell);
            }
            rows.push(cells);
        }

        return rows
    }
}

#[cfg(test)]
mod tests {
    use uibuf::UIBuffer;
    use rustbox::Color;

    fn setup_uibuf() -> UIBuffer {
        UIBuffer::new(50, 50)
    }

    #[test]
    fn grid_is_created_correctly() {
        let uibuf = setup_uibuf();
        assert_eq!(uibuf.height, 50);
        assert_eq!(uibuf.width, 50);
        assert_eq!(uibuf.rows.len(), 50);
        assert_eq!(uibuf.rows[0][5].ch, ' ');
    }

    #[test]
    fn fill_updates_contents_of_all_cells() {
        let mut uibuf = setup_uibuf();
        uibuf.fill('x');

        // check some random cells
        assert_eq!(uibuf.rows[20][5].ch, 'x');
        assert_eq!(uibuf.rows[0][30].ch, 'x');
    }

    #[test]
    fn update_cell_content_updates_a_single_cell() {
        let mut uibuf = setup_uibuf();
        // update cell 10 in row 32
        uibuf.update_cell_content(10, 32, 'y');

        assert_eq!(uibuf.rows[32][10].ch, 'y');
    }

    #[test]
    fn update_cell_updates_all_attrs_of_cell() {
        let mut uibuf = setup_uibuf();
        let cell_num = 10u;
        let row_num = 0u;
        let ch = 'q';
        let fg = Color::Red;
        let bg = Color::Blue;

        uibuf.update_cell(cell_num, row_num, ch, fg, bg);

        let cell = &uibuf.rows[row_num][cell_num];
        assert_eq!(cell.ch, ch);

        // FIXME(greg): this fails cos '==' is not implemented for rustbox::Color.
        // assert_eq!(cell.fg, fg);
        // assert_eq!(cell.bg, bg);
    }

}
<commit_msg>Address comments<commit_after>use rustbox::{Color, RustBox, Style};

pub struct UIBuffer {
    width: uint,
    height: uint,
    rows: Vec<Vec<Cell>>
}

impl UIBuffer {
    pub fn new(width: uint, height: uint) -> UIBuffer {
        let rows = Cell::create_grid(width, height, ' ');

        UIBuffer {
            width: width,
            height: height,
            rows: rows,
        }
    }

    pub fn draw_range(&mut self, rb: &RustBox, start: uint, stop: uint) {
        let rows = self.rows.slice_mut(start, stop);
        for row in rows.iter_mut() {
            for cell in row.iter_mut().filter(|cell| cell.dirty) {
                rb.print_char(cell.x, cell.y, Style::empty(), cell.fg, cell.bg, cell.ch);
                cell.dirty = false;
            }
        }
    }

    pub fn draw_everything(&mut self, rb: &RustBox) {
        let height = self.height;
        self.draw_range(rb, 0, height);
    }

    pub fn get_width(&self) -> uint {
        self.width
    }

    pub fn get_height(&self) -> uint {
        self.height
    }

    /// Set all cells to `ch`.
    pub fn fill(&mut self, ch: char) {
        for row in range(0, self.height) {
            for col in range(0, self.width) {
                self.update_cell_content(col, row, ch);
            }
        }
    }

    /// Update the `ch` attribute of an individual cell
    pub fn update_cell_content(&mut self, cell_num: uint, row_num: uint, ch: char) {
        self.rows[row_num][cell_num].set_char(ch);
    }

    /// Update the `ch`, `fg`, and `bg` attributes of an indivudual cell
    pub fn update_cell(&mut self, cell_num: uint, row_num: uint, ch: char, fg: Color, bg: Color) {
        self.get_cell_mut(cell_num, row_num).set(ch, fg, bg);
    }

    pub fn get_cell_mut(&mut self, cell_num: uint, row_num: uint) -> &mut Cell {
        &mut self.rows[row_num][cell_num]
    }
}

pub struct Cell {
    pub bg: Color,
    pub fg: Color,
    pub ch: char,
    pub x: uint,
    pub y: uint,
    pub dirty: bool
}

impl Cell {
    pub fn new() -> Cell {
        Cell {
            bg: Color::Default,
            fg: Color::Default,
            ch: ' ',
            x: 0,
            y: 0,
            dirty: true
        }
    }

    pub fn set_char(&mut self, ch: char) {
        if self.ch != ch {
            self.dirty = true;
            self.ch = ch;
        }
    }

    pub fn set(&mut self, ch: char, fg: Color, bg: Color) {
        if self.ch != ch || self.fg != fg || self.bg != bg {
            self.dirty = true;
        }
        self.ch = ch;
        self.fg = fg;
        self.bg = bg;
    }

    pub fn create_grid(width: uint, height: uint, ch: char) -> Vec<Vec<Cell>> {
        let mut rows = Vec::new();
        for voffset in range(0, height) {
            let mut cells = Vec::new();
            for boffset in range(0, width) {
                let mut cell = Cell::new();
                cell.x = boffset;
                cell.y = voffset;
                cell.ch = ch;
                cells.push(cell);
            }
            rows.push(cells);
        }

        return rows
    }
}

#[cfg(test)]
mod tests {
    use uibuf::UIBuffer;
    use rustbox::Color;

    fn setup_uibuf() -> UIBuffer {
        UIBuffer::new(50, 50)
    }

    #[test]
    fn grid_is_created_correctly() {
        let uibuf = setup_uibuf();
        assert_eq!(uibuf.height, 50);
        assert_eq!(uibuf.width, 50);
        assert_eq!(uibuf.rows.len(), 50);
        assert_eq!(uibuf.rows[0][5].ch, ' ');
    }

    #[test]
    fn fill_updates_contents_of_all_cells() {
        let mut uibuf = setup_uibuf();
        uibuf.fill('x');

        // check some random cells
        assert_eq!(uibuf.rows[20][5].ch, 'x');
        assert_eq!(uibuf.rows[0][30].ch, 'x');
    }

    #[test]
    fn update_cell_content_updates_a_single_cell() {
        let mut uibuf = setup_uibuf();
        // update cell 10 in row 32
        uibuf.update_cell_content(10, 32, 'y');

        assert_eq!(uibuf.rows[32][10].ch, 'y');
    }

    #[test]
    fn update_cell_updates_all_attrs_of_cell() {
        let mut uibuf = setup_uibuf();
        let cell_num = 10u;
        let row_num = 0u;
        let ch = 'q';
        let fg = Color::Red;
        let bg = Color::Blue;

        uibuf.update_cell(cell_num, row_num, ch, fg, bg);

        let cell = &uibuf.rows[row_num][cell_num];
        assert_eq!(cell.ch, ch);

        // FIXME(greg): this fails cos '==' is not implemented for rustbox::Color.
        // assert_eq!(cell.fg, fg);
        // assert_eq!(cell.bg, bg);
    }

}
<|endoftext|>


<commit_before>//! Intermediate representation for C/C++ enumerations.

use clang;
use parse::{ClangItemParser, ParseError};
use super::context::BindgenContext;
use super::item::{Item, ItemId};
use super::ty::TypeKind;

/// A C/C++ enumeration.
#[derive(Debug)]
pub struct Enum {
    /// The representation used for this enum; it should be an `IntKind` type or
    /// an alias to one.
    ///
    /// It's `None` if the enum is a forward declaration and isn't defined
    /// anywhere else, see `tests/headers/func_ptr_in_struct.h`.
    repr: Option<ItemId>,

    /// The different variants, with explicit values.
    variants: Vec<EnumVariant>,
}

impl Enum {
    /// Construct a new `Enum` with the given representation and variants.
    pub fn new(repr: Option<ItemId>, variants: Vec<EnumVariant>) -> Self {
        Enum {
            repr: repr,
            variants: variants,
        }
    }

    /// Get this enumeration's representation.
    pub fn repr(&self) -> Option<ItemId> {
        self.repr
    }

    /// Get this enumeration's variants.
    pub fn variants(&self) -> &[EnumVariant] {
        &self.variants
    }

    /// Construct an enumeration from the given Clang type.
    pub fn from_ty(ty: &clang::Type,
                   ctx: &mut BindgenContext)
                   -> Result<Self, ParseError> {
        use clangll::*;
        if ty.kind() != CXType_Enum {
            return Err(ParseError::Continue);
        }

        let declaration = ty.declaration().canonical();
        let repr = Item::from_ty(&declaration.enum_type(), None, None, ctx)
            .ok();
        let mut variants = vec![];

        let is_signed = match repr {
            Some(repr) => {
                let repr_type = ctx.resolve_type(repr);
                match *repr_type.canonical_type(ctx).kind() {
                    TypeKind::Int(ref int_kind) => int_kind.is_signed(),
                    ref other => {
                        panic!("Since when enums can be non-integers? {:?}",
                               other)
                    }
                }
            }
            // Assume signedness since the default type by the C
            // standard is an
            // int.
            None => true,
        };

        declaration.visit(|cursor| {
            let val = if is_signed {
                cursor.enum_val_signed().map(EnumVariantValue::Signed)
            } else {
                if cursor.kind() == CXCursor_EnumConstantDecl {
                    Some(EnumVariantValue::Unsigned(cursor.enum_val_unsigned()))
                } else {
                    None
                }
            };
            if let Some(val) = val {
                let name = cursor.spelling();
                let comment = cursor.raw_comment();
                variants.push(EnumVariant::new(name, comment, val));
            }
            CXChildVisit_Continue
        });

        Ok(Enum::new(repr, variants))
    }
}

/// A single enum variant, to be contained only in an enum.
#[derive(Debug)]
pub struct EnumVariant {
    /// The name of the variant.
    name: String,

    /// An optional doc comment.
    comment: Option<String>,

    /// The integer value of the variant.
    val: EnumVariantValue,
}

/// A constant value assigned to an enumeration variant.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EnumVariantValue {
    /// A signed constant.
    Signed(i64),

    /// An unsigned constant.
    Unsigned(u64),
}

impl EnumVariant {
    /// Construct a new enumeration variant from the given parts.
    pub fn new(name: String,
               comment: Option<String>,
               val: EnumVariantValue)
               -> Self {
        EnumVariant {
            name: name,
            comment: comment,
            val: val,
        }
    }

    /// Get this variant's name.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get this variant's value.
    pub fn val(&self) -> EnumVariantValue {
        self.val
    }
}
<commit_msg>Restore outer conditional.<commit_after>//! Intermediate representation for C/C++ enumerations.

use clang;
use parse::{ClangItemParser, ParseError};
use super::context::BindgenContext;
use super::item::{Item, ItemId};
use super::ty::TypeKind;

/// A C/C++ enumeration.
#[derive(Debug)]
pub struct Enum {
    /// The representation used for this enum; it should be an `IntKind` type or
    /// an alias to one.
    ///
    /// It's `None` if the enum is a forward declaration and isn't defined
    /// anywhere else, see `tests/headers/func_ptr_in_struct.h`.
    repr: Option<ItemId>,

    /// The different variants, with explicit values.
    variants: Vec<EnumVariant>,
}

impl Enum {
    /// Construct a new `Enum` with the given representation and variants.
    pub fn new(repr: Option<ItemId>, variants: Vec<EnumVariant>) -> Self {
        Enum {
            repr: repr,
            variants: variants,
        }
    }

    /// Get this enumeration's representation.
    pub fn repr(&self) -> Option<ItemId> {
        self.repr
    }

    /// Get this enumeration's variants.
    pub fn variants(&self) -> &[EnumVariant] {
        &self.variants
    }

    /// Construct an enumeration from the given Clang type.
    pub fn from_ty(ty: &clang::Type,
                   ctx: &mut BindgenContext)
                   -> Result<Self, ParseError> {
        use clangll::*;
        if ty.kind() != CXType_Enum {
            return Err(ParseError::Continue);
        }

        let declaration = ty.declaration().canonical();
        let repr = Item::from_ty(&declaration.enum_type(), None, None, ctx)
            .ok();
        let mut variants = vec![];

        let is_signed = match repr {
            Some(repr) => {
                let repr_type = ctx.resolve_type(repr);
                match *repr_type.canonical_type(ctx).kind() {
                    TypeKind::Int(ref int_kind) => int_kind.is_signed(),
                    ref other => {
                        panic!("Since when enums can be non-integers? {:?}",
                               other)
                    }
                }
            }
            // Assume signedness since the default type by the C
            // standard is an
            // int.
            None => true,
        };

        declaration.visit(|cursor| {
            if cursor.kind() == CXCursor_EnumConstantDecl {
                let value = if is_signed {
                    cursor.enum_val_signed().map(EnumVariantValue::Signed)
                } else {
                    Some(EnumVariantValue::Unsigned(cursor.enum_val_unsigned()))
                };
                if let Some(val) = value {
                    let name = cursor.spelling();
                    let comment = cursor.raw_comment();
                    variants.push(EnumVariant::new(name, comment, val));
                }
            }
            CXChildVisit_Continue
        });
        Ok(Enum::new(repr, variants))
    }
}

/// A single enum variant, to be contained only in an enum.
#[derive(Debug)]
pub struct EnumVariant {
    /// The name of the variant.
    name: String,

    /// An optional doc comment.
    comment: Option<String>,

    /// The integer value of the variant.
    val: EnumVariantValue,
}

/// A constant value assigned to an enumeration variant.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EnumVariantValue {
    /// A signed constant.
    Signed(i64),

    /// An unsigned constant.
    Unsigned(u64),
}

impl EnumVariant {
    /// Construct a new enumeration variant from the given parts.
    pub fn new(name: String,
               comment: Option<String>,
               val: EnumVariantValue)
               -> Self {
        EnumVariant {
            name: name,
            comment: comment,
            val: val,
        }
    }

    /// Get this variant's name.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get this variant's value.
    pub fn val(&self) -> EnumVariantValue {
        self.val
    }
}
<|endoftext|>


<commit_before>//! An example drawing semi-transparent venn diagrams
//! using different blend modes.
//!
//! It also shows why you'd usually want to draw canvases
//! using the `Premultiplied` blend mode
//! (for more explanations on this see https://github.com/ggez/ggez/issues/694#issuecomment-853724926)

use ggez::event::{self, EventHandler};
use ggez::graphics::{self, BlendMode, Color, DrawParam, Drawable};
use ggez::{Context, GameResult};
use glam::Vec2;
use std::env;
use std::path;

struct MainState {
    circle: graphics::Mesh,
    canvas: graphics::Canvas,
    font: graphics::Font,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let circle = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            Vec2::new(0.0, 0.0),
            45.0,
            0.5,
            Color::WHITE,
        )?;

        let mut canvas = graphics::Canvas::with_window_size(ctx)?;
        canvas.set_blend_mode(Some(BlendMode::Alpha));

        let font = graphics::Font::new(ctx, "/LiberationMono-Regular.ttf")?;

        let s = Self {
            circle,
            canvas,
            font,
        };
        Ok(s)
    }

    fn draw_venn(&self, ctx: &mut Context, pos: Vec2, name: &str) -> GameResult<()> {
        const TRI_COLORS: [Color; 3] = [
            Color::new(0.8, 0., 0., 0.5),
            Color::new(0., 0.8, 0., 0.5),
            Color::new(0., 0., 0.8, 0.5),
        ];

        const OFFSET: f32 = 24.;
        const REL_POSITIONS: [[f32; 2]; 3] = [
            [-OFFSET, -OFFSET / 2.],
            [OFFSET, -OFFSET / 2.],
            [0., OFFSET],
        ];

        // draw the diagram
        for i in 0..3 {
            self.circle.draw(
                ctx,
                DrawParam::default()
                    .dest(pos + Vec2::from(REL_POSITIONS[i]))
                    .color(TRI_COLORS[i]),
            )?;
        }

        // draw text naming the blend mode
        let text = graphics::Text::new((name, self.font, 20.0));
        let text_offset = Vec2::new(0., -100.);
        graphics::draw(
            ctx,
            &text,
            graphics::DrawParam::new()
                .dest(pos + text_offset)
                .color(Color::WHITE)
                .offset(Vec2::new(0.5, 0.5)),
        )?;
        Ok(())
    }

    fn draw_venn_diagrams(&mut self, ctx: &mut Context) -> GameResult<()> {
        let (w, h) = graphics::drawable_size(ctx);
        let y = h / 4.;
        const MODE_COUNT: usize = 8;
        let x_step = w / (MODE_COUNT + 1) as f32;

        // draw with Alpha
        self.circle.set_blend_mode(Some(BlendMode::Alpha));
        self.draw_venn(ctx, [x_step, y].into(), "Alpha")?;

        // draw with Add
        self.circle.set_blend_mode(Some(BlendMode::Add));
        self.draw_venn(ctx, [x_step * 2., y].into(), "Add")?;

        // draw with Sub
        self.circle.set_blend_mode(Some(BlendMode::Subtract));
        self.draw_venn(ctx, [x_step * 3., y].into(), "Subtract")?;

        // draw with Multiply
        self.circle.set_blend_mode(Some(BlendMode::Multiply));
        self.draw_venn(ctx, [x_step * 4., y].into(), "Multiply")?;

        // draw with Invert
        self.circle.set_blend_mode(Some(BlendMode::Invert));
        self.draw_venn(ctx, [x_step * 5., y].into(), "Invert")?;

        // draw with Replace
        self.circle.set_blend_mode(Some(BlendMode::Replace));
        self.draw_venn(ctx, [x_step * 6., y].into(), "Replace")?;

        // draw with Darken
        self.circle.set_blend_mode(Some(BlendMode::Darken));
        self.draw_venn(ctx, [x_step * 7., y].into(), "Darken")?;

        // draw with Lighten
        self.circle.set_blend_mode(Some(BlendMode::Lighten));
        self.draw_venn(ctx, [x_step * 8., y].into(), "Lighten")?;

        Ok(())
    }
}

impl EventHandler for MainState {
    fn update(&mut self, _: &mut Context) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx, Color::new(0.3, 0.3, 0.3, 1.0));

        // draw everything directly onto the screen once
        self.draw_venn_diagrams(ctx)?;

        // also draw everything onto the canvas
        graphics::set_canvas(ctx, Some(&self.canvas));
        graphics::clear(ctx, Color::new(0., 0., 0., 0.));
        self.draw_venn_diagrams(ctx)?;

        // draw the canvas onto the screen
        graphics::set_canvas(ctx, None);
        let (_, height) = graphics::drawable_size(ctx);
        self.canvas.draw(
            ctx,
            DrawParam::default().dest(mint::Point2 {
                x: 0.,
                y: height / 2.,
            }),
        )?;

        // draw text pointing out which is which
        let (_w, h) = graphics::drawable_size(ctx);
        let y = h / 2.;

        let text = graphics::Text::new(("drawn directly:", self.font, 20.0));
        graphics::draw(
            ctx,
            &text,
            graphics::DrawParam::new()
                .dest(Vec2::new(8., 4.))
                .color(Color::WHITE),
        )?;
        let text = graphics::Text::new(("drawn onto a (transparent) canvas:", self.font, 20.0));
        graphics::draw(
            ctx,
            &text,
            graphics::DrawParam::new()
                .dest(Vec2::new(8., 4. + y))
                .color(Color::WHITE),
        )?;

        graphics::present(ctx)?;
        Ok(())
    }

    fn key_down_event(
        &mut self,
        _ctx: &mut Context,
        _keycode: ggez::event::KeyCode,
        _keymod: ggez::event::KeyMods,
        repeat: bool,
    ) {
        if !repeat {
            if let Some(BlendMode::Alpha) = self.canvas.blend_mode() {
                self.canvas.set_blend_mode(Some(BlendMode::Premultiplied));
                println!("Drawing canvas with premultiplied alpha mode");
            } else {
                self.canvas.set_blend_mode(Some(BlendMode::Alpha));
                println!("Drawing canvas with default alpha mode");
            }
        }
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("blend_modes", "ggez")
        .window_mode(ggez::conf::WindowMode::default().dimensions(1400., 600.))
        .window_setup(
            ggez::conf::WindowSetup::default()
                .title("blend modes -- Press a button to change the canvas blend mode!"),
        )
        .add_resource_path(resource_dir);
    let (mut ctx, event_loop) = cb.build()?;
    let state = MainState::new(&mut ctx)?;
    event::run(ctx, event_loop, state)
}
<commit_msg>mentioned that the canvas is actually transparent black to make it easier to understand what's going on<commit_after>//! An example drawing semi-transparent venn diagrams
//! using different blend modes.
//!
//! It also shows why you'd usually want to draw canvases
//! using the `Premultiplied` blend mode
//! (for more explanations on this see https://github.com/ggez/ggez/issues/694#issuecomment-853724926)

use ggez::event::{self, EventHandler};
use ggez::graphics::{self, BlendMode, Color, DrawParam, Drawable};
use ggez::{Context, GameResult};
use glam::Vec2;
use std::env;
use std::path;

struct MainState {
    circle: graphics::Mesh,
    canvas: graphics::Canvas,
    font: graphics::Font,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let circle = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            Vec2::new(0.0, 0.0),
            45.0,
            0.5,
            Color::WHITE,
        )?;

        let mut canvas = graphics::Canvas::with_window_size(ctx)?;
        canvas.set_blend_mode(Some(BlendMode::Alpha));

        let font = graphics::Font::new(ctx, "/LiberationMono-Regular.ttf")?;

        let s = Self {
            circle,
            canvas,
            font,
        };
        Ok(s)
    }

    fn draw_venn(&self, ctx: &mut Context, pos: Vec2, name: &str) -> GameResult<()> {
        const TRI_COLORS: [Color; 3] = [
            Color::new(0.8, 0., 0., 0.5),
            Color::new(0., 0.8, 0., 0.5),
            Color::new(0., 0., 0.8, 0.5),
        ];

        const OFFSET: f32 = 24.;
        const REL_POSITIONS: [[f32; 2]; 3] = [
            [-OFFSET, -OFFSET / 2.],
            [OFFSET, -OFFSET / 2.],
            [0., OFFSET],
        ];

        // draw the diagram
        for i in 0..3 {
            self.circle.draw(
                ctx,
                DrawParam::default()
                    .dest(pos + Vec2::from(REL_POSITIONS[i]))
                    .color(TRI_COLORS[i]),
            )?;
        }

        // draw text naming the blend mode
        let text = graphics::Text::new((name, self.font, 20.0));
        let text_offset = Vec2::new(0., -100.);
        graphics::draw(
            ctx,
            &text,
            graphics::DrawParam::new()
                .dest(pos + text_offset)
                .color(Color::WHITE)
                .offset(Vec2::new(0.5, 0.5)),
        )?;
        Ok(())
    }

    fn draw_venn_diagrams(&mut self, ctx: &mut Context) -> GameResult<()> {
        let (w, h) = graphics::drawable_size(ctx);
        let y = h / 4.;
        const MODE_COUNT: usize = 8;
        let x_step = w / (MODE_COUNT + 1) as f32;

        // draw with Alpha
        self.circle.set_blend_mode(Some(BlendMode::Alpha));
        self.draw_venn(ctx, [x_step, y].into(), "Alpha")?;

        // draw with Add
        self.circle.set_blend_mode(Some(BlendMode::Add));
        self.draw_venn(ctx, [x_step * 2., y].into(), "Add")?;

        // draw with Sub
        self.circle.set_blend_mode(Some(BlendMode::Subtract));
        self.draw_venn(ctx, [x_step * 3., y].into(), "Subtract")?;

        // draw with Multiply
        self.circle.set_blend_mode(Some(BlendMode::Multiply));
        self.draw_venn(ctx, [x_step * 4., y].into(), "Multiply")?;

        // draw with Invert
        self.circle.set_blend_mode(Some(BlendMode::Invert));
        self.draw_venn(ctx, [x_step * 5., y].into(), "Invert")?;

        // draw with Replace
        self.circle.set_blend_mode(Some(BlendMode::Replace));
        self.draw_venn(ctx, [x_step * 6., y].into(), "Replace")?;

        // draw with Darken
        self.circle.set_blend_mode(Some(BlendMode::Darken));
        self.draw_venn(ctx, [x_step * 7., y].into(), "Darken")?;

        // draw with Lighten
        self.circle.set_blend_mode(Some(BlendMode::Lighten));
        self.draw_venn(ctx, [x_step * 8., y].into(), "Lighten")?;

        Ok(())
    }
}

impl EventHandler for MainState {
    fn update(&mut self, _: &mut Context) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx, Color::new(0.3, 0.3, 0.3, 1.0));

        // draw everything directly onto the screen once
        self.draw_venn_diagrams(ctx)?;

        // also draw everything onto the canvas
        graphics::set_canvas(ctx, Some(&self.canvas));
        graphics::clear(ctx, Color::new(0., 0., 0., 0.));
        self.draw_venn_diagrams(ctx)?;

        // draw the canvas onto the screen
        graphics::set_canvas(ctx, None);
        let (_, height) = graphics::drawable_size(ctx);
        self.canvas.draw(
            ctx,
            DrawParam::default().dest(mint::Point2 {
                x: 0.,
                y: height / 2.,
            }),
        )?;

        // draw text pointing out which is which
        let (_w, h) = graphics::drawable_size(ctx);
        let y = h / 2.;

        let text = graphics::Text::new(("drawn directly:", self.font, 20.0));
        graphics::draw(
            ctx,
            &text,
            graphics::DrawParam::new()
                .dest(Vec2::new(8., 4.))
                .color(Color::WHITE),
        )?;
        let text = graphics::Text::new(("drawn onto a (transparent black) canvas:", self.font, 20.0));
        graphics::draw(
            ctx,
            &text,
            graphics::DrawParam::new()
                .dest(Vec2::new(8., 4. + y))
                .color(Color::WHITE),
        )?;

        graphics::present(ctx)?;
        Ok(())
    }

    fn key_down_event(
        &mut self,
        _ctx: &mut Context,
        _keycode: ggez::event::KeyCode,
        _keymod: ggez::event::KeyMods,
        repeat: bool,
    ) {
        if !repeat {
            if let Some(BlendMode::Alpha) = self.canvas.blend_mode() {
                self.canvas.set_blend_mode(Some(BlendMode::Premultiplied));
                println!("Drawing canvas with premultiplied alpha mode");
            } else {
                self.canvas.set_blend_mode(Some(BlendMode::Alpha));
                println!("Drawing canvas with default alpha mode");
            }
        }
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("blend_modes", "ggez")
        .window_mode(ggez::conf::WindowMode::default().dimensions(1400., 600.))
        .window_setup(
            ggez::conf::WindowSetup::default()
                .title("blend modes -- Press a button to change the canvas blend mode!"),
        )
        .add_resource_path(resource_dir);
    let (mut ctx, event_loop) = cb.build()?;
    let state = MainState::new(&mut ctx)?;
    event::run(ctx, event_loop, state)
}
<|endoftext|>


<commit_before>extern crate ggez;
use ggez::conf;
use ggez::event;
use ggez::{GameResult, Context};
use ggez::graphics;
use std::time::Duration;

// First we make a structure to contain the game's state
struct MainState {
    text: graphics::Text,
}

// Then we implement the `ggez::game::GameState` trait on it, which
// requires callbacks for creating the game state, updating it each
// frame, and drawing it.
//
// The `GameState` trait also contains callbacks for event handling
// that you can override if you wish, but the defaults are fine.
impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let font = graphics::Font::new(ctx, "DejaVuSerif.ttf", 48)?;
        let text = graphics::Text::new(ctx, "Hello world!", &font)?;

        let s = MainState { text: text };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context, _dt: Duration) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);
        let dest_point = graphics::Point::new(0.0, 0.0);
        graphics::draw(ctx, &mut self.text, dest_point, 0.0)?;
        graphics::present(ctx);
        Ok(())
    }
}

// Now our main function, which does three things:
//
// * First, create a new `ggez::conf::Conf`
// object which contains configuration info on things such
// as screen resolution and window title,
// * Second, create a `ggez::game::Game` object which will
// do the work of creating our MainState and running our game,
// * then just call `game.run()` which runs the `Game` mainloop.
pub fn main() {
    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("helloworld", "ggez", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    if let Err(e) = event::run(ctx, state) {
        println!("Error encountered: {}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<commit_msg>fix hello_world example drawing outside the window<commit_after>extern crate ggez;
use ggez::conf;
use ggez::event;
use ggez::{GameResult, Context};
use ggez::graphics;
use std::time::Duration;

// First we make a structure to contain the game's state
struct MainState {
    text: graphics::Text,
}

// Then we implement the `ggez::game::GameState` trait on it, which
// requires callbacks for creating the game state, updating it each
// frame, and drawing it.
//
// The `GameState` trait also contains callbacks for event handling
// that you can override if you wish, but the defaults are fine.
impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let font = graphics::Font::new(ctx, "DejaVuSerif.ttf", 48)?;
        let text = graphics::Text::new(ctx, "Hello world!", &font)?;

        let s = MainState { text: text };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context, _dt: Duration) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);
        // Drawables are drawn from their center.
        let dest_point = graphics::Point::new(self.text.width() as f32 / 2.0 + 10.0,
                                              self.text.height() as f32 / 2.0 + 10.0);
        graphics::draw(ctx, &mut self.text, dest_point, 0.0)?;
        graphics::present(ctx);
        Ok(())
    }
}

// Now our main function, which does three things:
//
// * First, create a new `ggez::conf::Conf`
// object which contains configuration info on things such
// as screen resolution and window title,
// * Second, create a `ggez::game::Game` object which will
// do the work of creating our MainState and running our game,
// * then just call `game.run()` which runs the `Game` mainloop.
pub fn main() {
    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("helloworld", "ggez", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    if let Err(e) = event::run(ctx, state) {
        println!("Error encountered: {}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<|endoftext|>


<commit_before>extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;
use gitlab::issues;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new(&hostname, &token);

    let issues = gl.issues().list();
    println!("issues: {:?}", issues);

    let opened_issues = gl.issues().state(issues::State::Opened).list();
    println!("opened_issues: {:?}", opened_issues);

    let closed_issues = gl.issues().state(issues::State::Closed).list();
    println!("closed_issues: {:?}", closed_issues);

//     let listing = issues::single::Listing::new(142, 739);
//     let issue = gl.issue(listing).unwrap();
//     println!("issue: {:?}", issue);
//
//     let listing = issues::group::Listing::new(21).state(issues::ListingState::Closed).clone();
//     let group_issues = gl.group_issues(listing).unwrap();
//     println!("group_issues: {:?}", group_issues);
//
//     let listing = issues::project::Listing::new(142).state(issues::ListingState::Closed).clone();
//     let project_issues = gl.project_issues(listing).unwrap();
//     println!("project_issues: {:?}", project_issues);
}
<commit_msg>Re-activate single issue example<commit_after>extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;
use gitlab::issues;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new(&hostname, &token);

    let issues = gl.issues().list();
    println!("issues: {:?}", issues);

    let opened_issues = gl.issues().state(issues::State::Opened).list();
    println!("opened_issues: {:?}", opened_issues);

    let closed_issues = gl.issues().state(issues::State::Closed).list();
    println!("closed_issues: {:?}", closed_issues);

    let issue = gl.issues().single(142, 739).list();
    println!("issue: {:?}", issue);

//     let listing = issues::group::Listing::new(21).state(issues::ListingState::Closed).clone();
//     let group_issues = gl.group_issues(listing).unwrap();
//     println!("group_issues: {:?}", group_issues);
//
//     let listing = issues::project::Listing::new(142).state(issues::ListingState::Closed).clone();
//     let project_issues = gl.project_issues(listing).unwrap();
//     println!("project_issues: {:?}", project_issues);
}
<|endoftext|>


<commit_before>use support::rustc_host;
use support::{basic_lib_manifest, project};

#[test]
fn pathless_tools() {
    let target = rustc_host();

    let foo = project()
        .file("Cargo.toml", &basic_lib_manifest("foo"))
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.{}]
            ar = "nonexistent-ar"
            linker = "nonexistent-linker"
        "#,
                target
            ),
        ).build();

    foo.cargo("build --verbose")
        .with_stderr(
            "\
[COMPILING] foo v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C ar=nonexistent-ar -C linker=nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        ).run();
}

#[test]
fn absolute_tools() {
    let target = rustc_host();
    let root = if cfg!(windows) { r#"C:\"# } else { "/" };

    // Escaped as they appear within a TOML config file
    let config = if cfg!(windows) {
        (
            r#"C:\\bogus\\nonexistent-ar"#,
            r#"C:\\bogus\\nonexistent-linker"#,
        )
    } else {
        (r#"/bogus/nonexistent-ar"#, r#"/bogus/nonexistent-linker"#)
    };

    let foo = project()
        .file("Cargo.toml", &basic_lib_manifest("foo"))
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.{target}]
            ar = "{ar}"
            linker = "{linker}"
        "#,
                target = target,
                ar = config.0,
                linker = config.1
            ),
        ).build();

    foo.cargo("build --verbose").with_stderr(&format!(
            "\
[COMPILING] foo v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C ar={root}bogus/nonexistent-ar -C linker={root}bogus/nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
            root = root,
        )).run();
}

#[test]
fn relative_tools() {
    let target = rustc_host();

    // Escaped as they appear within a TOML config file
    let config = if cfg!(windows) {
        (r#".\\nonexistent-ar"#, r#".\\tools\\nonexistent-linker"#)
    } else {
        (r#"./nonexistent-ar"#, r#"./tools/nonexistent-linker"#)
    };

    // Funky directory structure to test that relative tool paths are made absolute
    // by reference to the `.cargo/..` directory and not to (for example) the CWD.
    let p = project()
        .no_manifest()
        .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
        .file("bar/src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.{target}]
            ar = "{ar}"
            linker = "{linker}"
        "#,
                target = target,
                ar = config.0,
                linker = config.1
            ),
        ).build();

    let prefix = p.root().into_os_string().into_string().unwrap();

    p.cargo("build --verbose").cwd(p.root().join("bar")).with_stderr(&format!(
            "\
[COMPILING] bar v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C ar={prefix}/./nonexistent-ar -C linker={prefix}/./tools/nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
            prefix = prefix,
        )).run();
}

#[test]
fn custom_runner() {
    let target = rustc_host();

    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file("tests/test.rs", "")
        .file("benches/bench.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.{}]
            runner = "nonexistent-runner -r"
        "#,
                target
            ),
        ).build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        ).run();

    p.cargo("test --test test --verbose -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r [..]/target/debug/deps/test-[..][EXE] --param`
",
        ).run();

    p.cargo("bench --bench bench --verbose -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]`
[RUNNING] `rustc [..]`
[FINISHED] release [optimized] target(s) in [..]
[RUNNING] `nonexistent-runner -r [..]/target/release/deps/bench-[..][EXE] --param --bench`
",
        ).run();
}

// can set a custom runner via `target.'cfg(..)'.runner`
#[test]
fn custom_runner_cfg() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
            [target.'cfg(not(target_os = "none"))']
            runner = "nonexistent-runner -r"
            "#,
        ).build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(&format!(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )).run();
}

// custom runner set via `target.$triple.runner` have precende over `target.'cfg(..)'.runner`
#[test]
fn custom_runner_cfg_precedence() {
    let target = rustc_host();

    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.'cfg(not(target_os = "none"))']
            runner = "ignored-runner"

            [target.{}]
            runner = "nonexistent-runner -r"
        "#,
                target
            ),
        ).build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(&format!(
            "\
            [COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )).run();
}

#[test]
fn custom_runner_cfg_collision() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
            [target.'cfg(not(target_arch = "avr"))']
            runner = "true"

            [target.'cfg(not(target_os = "none"))']
            runner = "false"
            "#,
        ).build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(&format!(
            "\
[ERROR] several matching instances of `target.'cfg(..)'.runner` in `.cargo/config`
",
        )).run();
}
<commit_msg>Simplify tool_paths::absolute_tools test<commit_after>use support::rustc_host;
use support::{basic_lib_manifest, project};

#[test]
fn pathless_tools() {
    let target = rustc_host();

    let foo = project()
        .file("Cargo.toml", &basic_lib_manifest("foo"))
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.{}]
            ar = "nonexistent-ar"
            linker = "nonexistent-linker"
        "#,
                target
            ),
        ).build();

    foo.cargo("build --verbose")
        .with_stderr(
            "\
[COMPILING] foo v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C ar=nonexistent-ar -C linker=nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        ).run();
}

#[test]
fn absolute_tools() {
    let target = rustc_host();

    // Escaped as they appear within a TOML config file
    let config = if cfg!(windows) {
        (
            r#"C:\\bogus\\nonexistent-ar"#,
            r#"C:\\bogus\\nonexistent-linker"#,
        )
    } else {
        (r#"/bogus/nonexistent-ar"#, r#"/bogus/nonexistent-linker"#)
    };

    let foo = project()
        .file("Cargo.toml", &basic_lib_manifest("foo"))
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.{target}]
            ar = "{ar}"
            linker = "{linker}"
        "#,
                target = target,
                ar = config.0,
                linker = config.1
            ),
        ).build();

    foo.cargo("build --verbose").with_stderr("\
[COMPILING] foo v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C ar=[ROOT]bogus/nonexistent-ar -C linker=[ROOT]bogus/nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
").run();
}

#[test]
fn relative_tools() {
    let target = rustc_host();

    // Escaped as they appear within a TOML config file
    let config = if cfg!(windows) {
        (r#".\\nonexistent-ar"#, r#".\\tools\\nonexistent-linker"#)
    } else {
        (r#"./nonexistent-ar"#, r#"./tools/nonexistent-linker"#)
    };

    // Funky directory structure to test that relative tool paths are made absolute
    // by reference to the `.cargo/..` directory and not to (for example) the CWD.
    let p = project()
        .no_manifest()
        .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
        .file("bar/src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.{target}]
            ar = "{ar}"
            linker = "{linker}"
        "#,
                target = target,
                ar = config.0,
                linker = config.1
            ),
        ).build();

    let prefix = p.root().into_os_string().into_string().unwrap();

    p.cargo("build --verbose").cwd(p.root().join("bar")).with_stderr(&format!(
            "\
[COMPILING] bar v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C ar={prefix}/./nonexistent-ar -C linker={prefix}/./tools/nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
            prefix = prefix,
        )).run();
}

#[test]
fn custom_runner() {
    let target = rustc_host();

    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file("tests/test.rs", "")
        .file("benches/bench.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.{}]
            runner = "nonexistent-runner -r"
        "#,
                target
            ),
        ).build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        ).run();

    p.cargo("test --test test --verbose -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r [..]/target/debug/deps/test-[..][EXE] --param`
",
        ).run();

    p.cargo("bench --bench bench --verbose -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]`
[RUNNING] `rustc [..]`
[FINISHED] release [optimized] target(s) in [..]
[RUNNING] `nonexistent-runner -r [..]/target/release/deps/bench-[..][EXE] --param --bench`
",
        ).run();
}

// can set a custom runner via `target.'cfg(..)'.runner`
#[test]
fn custom_runner_cfg() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
            [target.'cfg(not(target_os = "none"))']
            runner = "nonexistent-runner -r"
            "#,
        ).build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(&format!(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )).run();
}

// custom runner set via `target.$triple.runner` have precende over `target.'cfg(..)'.runner`
#[test]
fn custom_runner_cfg_precedence() {
    let target = rustc_host();

    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            &format!(
                r#"
            [target.'cfg(not(target_os = "none"))']
            runner = "ignored-runner"

            [target.{}]
            runner = "nonexistent-runner -r"
        "#,
                target
            ),
        ).build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(&format!(
            "\
            [COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )).run();
}

#[test]
fn custom_runner_cfg_collision() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
            [target.'cfg(not(target_arch = "avr"))']
            runner = "true"

            [target.'cfg(not(target_os = "none"))']
            runner = "false"
            "#,
        ).build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(&format!(
            "\
[ERROR] several matching instances of `target.'cfg(..)'.runner` in `.cargo/config`
",
        )).run();
}
<|endoftext|>