<commit_before>use super::{ColumnSettings, ColumnStartWith, ColumnUpdateWith, Component, Settings};
use {Run, Segment, TimeSpan, Timer, TimingMethod};

#[test]
fn zero_visual_split_count_always_shows_all_splits() {
    let mut run = Run::new();
    for _ in 0..32 {
        run.push_segment(Segment::new(""));
    }
    let timer = Timer::new(run).unwrap();
    let layout_settings = Default::default();
    let mut component = Component::with_settings(Settings {
        visual_split_count: 0,
        ..Default::default()
    });

    let mut state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits.len(), 32);

    component.scroll_down();
    state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits.len(), 32);

    component.scroll_down();
    state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits.len(), 32);

    component.scroll_up();
    state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits.len(), 32);
}

#[test]
fn negative_segment_times() {
    let mut run = Run::new();
    run.push_segment(Segment::new(""));
    let mut timer = Timer::new(run).unwrap();
    let layout_settings = Default::default();
    let mut component = Component::with_settings(Settings {
        columns: vec![ColumnSettings {
            start_with: ColumnStartWith::Empty,
            update_with: ColumnUpdateWith::SegmentTime,
            ..Default::default()
        }],
        ..Default::default()
    });

    timer.start();

    // Emulate a negative offset through game time.
    timer.set_current_timing_method(TimingMethod::GameTime);
    timer.initialize_game_time();
    timer.pause_game_time();
    timer.set_game_time(TimeSpan::from_seconds(-1.0));

    let state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits[0].columns[0].value, "−0:01");
}
<commit_msg>Add tests for different column types<commit_after>use super::{ColumnSettings, ColumnStartWith, ColumnUpdateWith, Component, Settings, State};
use settings::SemanticColor;
use tests_helper::{run_with_splits_opt, start_run};
use {Run, Segment, TimeSpan, Timer, TimingMethod};

const NONE: SemanticColor = SemanticColor::Default;
const BEST: SemanticColor = SemanticColor::BestSegment;
const BEHIND_LOSING: SemanticColor = SemanticColor::BehindLosingTime;
const BEHIND_GAINING: SemanticColor = SemanticColor::BehindGainingTime;
const AHEAD_GAINING: SemanticColor = SemanticColor::AheadGainingTime;

type Values = [([&'static str; 6], [SemanticColor; 6]); 7];

fn run() -> Run {
    let mut run = Run::new();

    run.push_segment(Segment::new("A"));
    run.push_segment(Segment::new("B"));
    run.push_segment(Segment::new("C"));
    run.push_segment(Segment::new("D"));
    run.push_segment(Segment::new("E"));
    run.push_segment(Segment::new("F"));

    run
}

fn timer() -> Timer {
    Timer::new(run()).unwrap()
}

fn check_column_state(state: &State, state_index: usize, expected_values: &Values) {
    let actual_values = state
        .splits
        .iter()
        .map(|split| split.columns[0].value.as_str())
        .collect::<Vec<_>>();
    let actual_colors = state
        .splits
        .iter()
        .map(|split| split.columns[0].semantic_color)
        .collect::<Vec<_>>();
    let actual_state = (actual_values, actual_colors);
    let (expected_values, expected_colors) = &expected_values[state_index];
    let expected_state = (expected_values.to_vec(), expected_colors.to_vec());
    assert_eq!(actual_state, expected_state, "State index: {}", state_index);
}

#[test]
fn zero_visual_split_count_always_shows_all_splits() {
    let mut run = Run::new();
    for _ in 0..32 {
        run.push_segment(Segment::new(""));
    }
    let timer = Timer::new(run).unwrap();
    let layout_settings = Default::default();
    let mut component = Component::with_settings(Settings {
        visual_split_count: 0,
        ..Default::default()
    });

    let mut state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits.len(), 32);

    component.scroll_down();
    state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits.len(), 32);

    component.scroll_down();
    state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits.len(), 32);

    component.scroll_up();
    state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits.len(), 32);
}

#[test]
fn negative_segment_times() {
    let mut run = Run::new();
    run.push_segment(Segment::new(""));
    let mut timer = Timer::new(run).unwrap();
    let layout_settings = Default::default();
    let mut component = Component::with_settings(Settings {
        columns: vec![ColumnSettings {
            start_with: ColumnStartWith::Empty,
            update_with: ColumnUpdateWith::SegmentTime,
            ..Default::default()
        }],
        ..Default::default()
    });

    timer.start();

    // Emulate a negative offset through game time.
    timer.set_current_timing_method(TimingMethod::GameTime);
    timer.initialize_game_time();
    timer.pause_game_time();
    timer.set_game_time(TimeSpan::from_seconds(-1.0));

    let state = component.state(&timer, &layout_settings);
    assert_eq!(state.splits[0].columns[0].value, "−0:01");
}

#[test]
fn column_empty_delta() {
    check_columns(
        ColumnStartWith::Empty,
        ColumnUpdateWith::Delta,
        [
            (
                ["", "", "", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "", "", "", "", ""],
                [BEHIND_LOSING, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "", "", "", ""],
                [BEHIND_LOSING, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "", "", ""],
                [BEHIND_LOSING, NONE, BEST, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "+2.5", "", ""],
                [BEHIND_LOSING, NONE, BEST, BEHIND_GAINING, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "+2.5", "—", ""],
                [BEHIND_LOSING, NONE, BEST, BEHIND_GAINING, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "+2.5", "—", "−1:00"],
                [
                    BEHIND_LOSING,
                    NONE,
                    BEST,
                    BEHIND_GAINING,
                    NONE,
                    AHEAD_GAINING,
                ],
            ),
        ],
    );
}

#[test]
fn column_empty_segment_delta() {
    check_columns(
        ColumnStartWith::Empty,
        ColumnUpdateWith::SegmentDelta,
        [
            (
                ["", "", "", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "", "", "", "", ""],
                [BEHIND_LOSING, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "", "", "", ""],
                [BEHIND_LOSING, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "", "", ""],
                [BEHIND_LOSING, NONE, BEST, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "−1.0", "", ""],
                [BEHIND_LOSING, NONE, BEST, AHEAD_GAINING, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "−1.0", "—", ""],
                [BEHIND_LOSING, NONE, BEST, AHEAD_GAINING, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "−1.0", "—", "−1:02"],
                [
                    BEHIND_LOSING,
                    NONE,
                    BEST,
                    AHEAD_GAINING,
                    NONE,
                    AHEAD_GAINING,
                ],
            ),
        ],
    )
}

#[test]
fn column_empty_split_time() {
    check_columns(
        ColumnStartWith::Empty,
        ColumnUpdateWith::SplitTime,
        [
            (
                ["", "", "", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "", "", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:10", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:10", "0:17", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:10", "0:17", "—", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:10", "0:17", "—", "0:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
        ],
    )
}

#[test]
fn column_empty_segment_time() {
    check_columns(
        ColumnStartWith::Empty,
        ColumnUpdateWith::SegmentTime,
        [
            (
                ["0:00", "", "", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "0:00", "", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:00", "", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:01", "0:00", "", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:01", "0:07", "0:00", ""],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:01", "0:07", "—", "0:00"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:01", "0:07", "—", "0:07"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
        ],
    )
}

#[test]
fn column_comparison_time_split_time() {
    check_columns(
        ColumnStartWith::ComparisonTime,
        ColumnUpdateWith::SplitTime,
        [
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:10", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:10", "0:17", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:10", "0:17", "—", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:10", "0:17", "—", "0:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
        ],
    )
}

#[test]
fn column_comparison_segment_time_segment_time() {
    check_columns(
        ColumnStartWith::ComparisonSegmentTime,
        ColumnUpdateWith::SegmentTime,
        [
            (
                ["0:00", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "0:00", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:00", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:01", "0:00", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:01", "0:07", "0:00", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:01", "0:07", "—", "0:00"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:08", "—", "0:01", "0:07", "—", "0:07"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
        ],
    )
}

#[test]
fn column_comparison_time_delta() {
    check_columns(
        ColumnStartWith::ComparisonTime,
        ColumnUpdateWith::Delta,
        [
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "0:15", "0:20", "1:25"],
                [BEHIND_LOSING, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "0:15", "0:20", "1:25"],
                [BEHIND_LOSING, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                // In the original LiveSplit, we showed the split time for this column type if the comparison time was missing
                // Instead, we show a dash for the third segment rather than showing the split time
                ["+3.5", "—", "—", "0:15", "0:20", "1:25"],
                [BEHIND_LOSING, NONE, BEST, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "+2.5", "0:20", "1:25"],
                [BEHIND_LOSING, NONE, BEST, BEHIND_GAINING, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "+2.5", "—", "1:25"],
                [BEHIND_LOSING, NONE, BEST, BEHIND_GAINING, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "+2.5", "—", "−1:00"],
                [
                    BEHIND_LOSING,
                    NONE,
                    BEST,
                    BEHIND_GAINING,
                    NONE,
                    AHEAD_GAINING,
                ],
            ),
        ],
    )
}

#[test]
fn column_comparison_segment_time_segment_delta() {
    check_columns(
        ColumnStartWith::ComparisonSegmentTime,
        ColumnUpdateWith::SegmentDelta,
        [
            (
                ["0:05", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "0:10", "0:05", "1:05"],
                [BEHIND_LOSING, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "0:10", "0:05", "1:05"],
                [BEHIND_LOSING, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                // In the original LiveSplit, we showed the segment time for this column type if the comparison segment time was missing
                // Instead, we show a dash for the third segment rather than showing the segment time
                ["+3.5", "—", "—", "0:10", "0:05", "1:05"],
                [BEHIND_LOSING, NONE, BEST, NONE, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "−1.0", "0:05", "1:05"],
                [BEHIND_LOSING, NONE, BEST, AHEAD_GAINING, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "−1.0", "—", "1:05"],
                [BEHIND_LOSING, NONE, BEST, AHEAD_GAINING, NONE, NONE],
            ),
            (
                ["+3.5", "—", "—", "−1.0", "—", "−1:02"],
                [
                    BEHIND_LOSING,
                    NONE,
                    BEST,
                    AHEAD_GAINING,
                    NONE,
                    AHEAD_GAINING,
                ],
            ),
        ],
    )
}

#[test]
fn column_comparison_time_dont_update() {
    check_columns(
        ColumnStartWith::ComparisonTime,
        ColumnUpdateWith::DontUpdate,
        [
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:15", "0:20", "1:25"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
        ],
    )
}

#[test]
fn column_comparison_segment_time_dont_update() {
    check_columns(
        ColumnStartWith::ComparisonSegmentTime,
        ColumnUpdateWith::DontUpdate,
        [
            (
                ["0:05", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
            (
                ["0:05", "—", "—", "0:10", "0:05", "1:05"],
                [NONE, NONE, NONE, NONE, NONE, NONE],
            ),
        ],
    )
}

fn check_columns(
    start_with: ColumnStartWith,
    update_with: ColumnUpdateWith,
    expected_values: Values,
) {
    let mut timer = timer();

    // Set initial best segment times
    run_with_splits_opt(
        &mut timer,
        &[
            Some(6.0),
            None,
            Some(100.0),
            Some(101.0),
            Some(102.0),
            Some(103.0),
        ],
    );

    // Set personal best times
    run_with_splits_opt(
        &mut timer,
        &[Some(5.0), None, None, Some(15.0), Some(20.0), Some(85.0)],
    );

    start_run(&mut timer);

    let layout_settings = Default::default();
    let mut component = Component::with_settings(Settings {
        columns: vec![ColumnSettings {
            start_with,
            update_with,
            ..Default::default()
        }],
        fill_with_blank_space: false,
        ..Default::default()
    });

    let state = component.state(&timer, &layout_settings);
    check_column_state(&state, 0, &expected_values);

    let first = TimeSpan::from_seconds(8.5);
    timer.set_game_time(first);
    timer.split();

    let state = component.state(&timer, &layout_settings);
    check_column_state(&state, 1, &expected_values);

    timer.skip_split();

    let state = component.state(&timer, &layout_settings);
    check_column_state(&state, 2, &expected_values);

    let third = TimeSpan::from_seconds(10.0);
    timer.set_game_time(third);
    timer.split();

    let state = component.state(&timer, &layout_settings);
    check_column_state(&state, 3, &expected_values);

    let fourth = TimeSpan::from_seconds(17.5);
    timer.set_game_time(fourth);
    timer.split();

    let state = component.state(&timer, &layout_settings);
    check_column_state(&state, 4, &expected_values);

    timer.skip_split();

    let state = component.state(&timer, &layout_settings);
    check_column_state(&state, 5, &expected_values);

    let sixth = TimeSpan::from_seconds(25.0);
    timer.set_game_time(sixth);
    timer.split();

    let state = component.state(&timer, &layout_settings);
    check_column_state(&state, 6, &expected_values);
}
<|endoftext|>


<commit_before>// TODO
// should directly test the plugins, because why not?
// maybe ladspa should have some testing facilities built in.

use super::get_ladspa_descriptor;
use ladspa::{Data, Port, PortConnection, PortData};
use std::cell::RefCell;
use std::thread;
use std::time::Duration;

const SAMPLE_RATE: u64 = 44100;

#[derive(Debug)]
enum OwnedPortData {
    AudioInput(Vec<Data>),
    AudioOutput(Vec<Data>),
    ControlInput(Data),
    ControlOutput(Data),
}

impl PartialEq for OwnedPortData {
    fn eq(&self, other: &Self) -> bool {
        use self::OwnedPortData::*;

        match *self {
            AudioInput(ref a) | AudioOutput(ref a) => {
                match *other {
                    AudioInput(ref b) | AudioOutput(ref b) => a == b,
                    _ => false,
                }
            }
            ControlInput(ref a) | ControlOutput(ref a) => {
                match *other {
                    ControlInput(ref b) | ControlOutput(ref b) => a == b,
                    _ => false,
                }
            }
        }
    }
}

struct OwnedPortConnection {
    port: Port,
    data: OwnedPortData,
}

fn make_owned_port_connections(ports: &[Port], size: usize) -> Vec<OwnedPortConnection> {
    use ladspa::PortDescriptor::*;

    let mut out = Vec::new();
    for port in ports {
        let data = match port.desc {
            AudioInput => OwnedPortData::AudioInput(vec![0.0; size]),
            AudioOutput => OwnedPortData::AudioOutput(vec![0.0; size]),
            ControlInput => OwnedPortData::ControlInput(0.0),
            ControlOutput => OwnedPortData::ControlOutput(0.0),
            Invalid => panic!(),
        };
        out.push(OwnedPortConnection {
            port: port.clone(),
            data: data,
        });
    }
    out
}

trait Tagged {
    fn set_tags(&mut self, port_tag: f32, input_tag: f32, output_tag: f32);
}

impl Tagged for Vec<OwnedPortConnection> {
    fn set_tags(&mut self, port_tag: f32, input_tag: f32, output_tag: f32) {
        use self::OwnedPortData::*;

        for port in self {
            match port.data {
                AudioInput(ref mut v) => {
                    for x in v.iter_mut() {
                        *x = input_tag;
                    }
                }
                AudioOutput(ref mut v) => {
                    for x in v.iter_mut() {
                        *x = output_tag;
                    }
                }
                ControlInput(ref mut x) => {
                    match port.port.name {
                        "Channel" => *x = port_tag,
                        _ => *x = 0.0,
                    }
                }
                ControlOutput(ref mut x) => {
                    *x = 0.0;
                }
            }
        }
    }
}

fn make_port_connections<'a>(owned: &'a mut [OwnedPortConnection]) -> Vec<PortConnection<'a>> {
    let mut out = Vec::new();
    for port in owned {
        let data = match port.data {
            OwnedPortData::AudioInput(ref data) => PortData::AudioInput(data),
            OwnedPortData::AudioOutput(ref mut data) => PortData::AudioOutput(RefCell::new(data)),
            OwnedPortData::ControlInput(ref data) => PortData::ControlInput(data),
            OwnedPortData::ControlOutput(ref mut data) => {
                PortData::ControlOutput(RefCell::new(data))
            }
        };

        out.push(PortConnection {
            port: port.port,
            data: data,
        });
    }
    out
}

fn borrow_port_connections<'a>(ports: &'a [PortConnection<'a>]) -> Vec<&'a PortConnection<'a>> {
    ports.iter().map(|x| x).collect()
}

#[test]
fn test_working_basic() {
    let sample_count = super::packet::BUFFER_SIZE;
    test_sample_count(sample_count, 0);
}

#[test]
fn test_working_multi_packet() {
    let sample_count = super::packet::BUFFER_SIZE * 32;
    test_sample_count(sample_count, 1);
}

fn test_sample_count(sample_count: usize, port: u8) {
    let tx_desc = get_ladspa_descriptor(0).unwrap();
    let rx_desc = get_ladspa_descriptor(1).unwrap();
    let mut tx = (tx_desc.new)(&tx_desc, SAMPLE_RATE);
    let mut rx = (rx_desc.new)(&rx_desc, SAMPLE_RATE);

    rx.activate();
    tx.activate();

    let mut tx_owned = make_owned_port_connections(&tx_desc.ports, sample_count);
    tx_owned.set_tags(port as f32, 1.0, 0.0);
    let mut rx_owned = make_owned_port_connections(&rx_desc.ports, sample_count);
    rx_owned.set_tags(port as f32, 0.0, 0.0);

    // run once to handle channel change
    {
        let tx_ports = make_port_connections(&mut tx_owned);
        let rx_ports = make_port_connections(&mut rx_owned);
        let tx_ports = borrow_port_connections(&tx_ports);
        let rx_ports = borrow_port_connections(&rx_ports);

        rx.run(sample_count, &rx_ports);
        tx.run(sample_count, &tx_ports);
    }

    // reset state
    rx.deactivate();
    tx.deactivate();
    rx.activate();
    thread::sleep(Duration::from_millis(100));
    tx.activate();
    thread::sleep(Duration::from_millis(100));

    tx_owned.set_tags(port as f32, 1.0, 0.0);
    rx_owned.set_tags(port as f32, 0.0, 0.0);

    // run again to do the computation
    {
        let tx_ports = make_port_connections(&mut tx_owned);
        let rx_ports = make_port_connections(&mut rx_owned);
        let tx_ports = borrow_port_connections(&tx_ports);
        let rx_ports = borrow_port_connections(&rx_ports);

        tx.run(sample_count, &tx_ports);
        thread::sleep(Duration::from_millis(100)); // wait for recv
        rx.run(sample_count, &rx_ports);
    }

    for i in 0..2 {
        assert_eq!(tx_owned[i].data, rx_owned[i + 2].data);
    }

    rx.deactivate();
    tx.deactivate();
}
<commit_msg>add sad explanation of weird code<commit_after>// TODO
// should directly test the plugins, because why not?
// maybe ladspa should have some testing facilities built in.

use super::get_ladspa_descriptor;
use ladspa::{Data, Port, PortConnection, PortData};
use std::cell::RefCell;
use std::thread;
use std::time::Duration;

const SAMPLE_RATE: u64 = 44100;

// TODO this port connection stuff is a mess because the Plugin trait in ladspa is too specific.
// it would be a breaking change to fix it, but should be done at some point because this is nuts.

#[derive(Debug)]
enum OwnedPortData {
    AudioInput(Vec<Data>),
    AudioOutput(Vec<Data>),
    ControlInput(Data),
    ControlOutput(Data),
}

impl PartialEq for OwnedPortData {
    fn eq(&self, other: &Self) -> bool {
        use self::OwnedPortData::*;

        match *self {
            AudioInput(ref a) | AudioOutput(ref a) => {
                match *other {
                    AudioInput(ref b) | AudioOutput(ref b) => a == b,
                    _ => false,
                }
            }
            ControlInput(ref a) | ControlOutput(ref a) => {
                match *other {
                    ControlInput(ref b) | ControlOutput(ref b) => a == b,
                    _ => false,
                }
            }
        }
    }
}

struct OwnedPortConnection {
    port: Port,
    data: OwnedPortData,
}

fn make_owned_port_connections(ports: &[Port], size: usize) -> Vec<OwnedPortConnection> {
    use ladspa::PortDescriptor::*;

    let mut out = Vec::new();
    for port in ports {
        let data = match port.desc {
            AudioInput => OwnedPortData::AudioInput(vec![0.0; size]),
            AudioOutput => OwnedPortData::AudioOutput(vec![0.0; size]),
            ControlInput => OwnedPortData::ControlInput(0.0),
            ControlOutput => OwnedPortData::ControlOutput(0.0),
            Invalid => panic!(),
        };
        out.push(OwnedPortConnection {
            port: port.clone(),
            data: data,
        });
    }
    out
}

trait Tagged {
    fn set_tags(&mut self, port_tag: f32, input_tag: f32, output_tag: f32);
}

impl Tagged for Vec<OwnedPortConnection> {
    fn set_tags(&mut self, port_tag: f32, input_tag: f32, output_tag: f32) {
        use self::OwnedPortData::*;

        for port in self {
            match port.data {
                AudioInput(ref mut v) => {
                    for x in v.iter_mut() {
                        *x = input_tag;
                    }
                }
                AudioOutput(ref mut v) => {
                    for x in v.iter_mut() {
                        *x = output_tag;
                    }
                }
                ControlInput(ref mut x) => {
                    match port.port.name {
                        "Channel" => *x = port_tag,
                        _ => *x = 0.0,
                    }
                }
                ControlOutput(ref mut x) => {
                    *x = 0.0;
                }
            }
        }
    }
}

fn make_port_connections<'a>(owned: &'a mut [OwnedPortConnection]) -> Vec<PortConnection<'a>> {
    let mut out = Vec::new();
    for port in owned {
        let data = match port.data {
            OwnedPortData::AudioInput(ref data) => PortData::AudioInput(data),
            OwnedPortData::AudioOutput(ref mut data) => PortData::AudioOutput(RefCell::new(data)),
            OwnedPortData::ControlInput(ref data) => PortData::ControlInput(data),
            OwnedPortData::ControlOutput(ref mut data) => {
                PortData::ControlOutput(RefCell::new(data))
            }
        };

        out.push(PortConnection {
            port: port.port,
            data: data,
        });
    }
    out
}

fn borrow_port_connections<'a>(ports: &'a [PortConnection<'a>]) -> Vec<&'a PortConnection<'a>> {
    ports.iter().map(|x| x).collect()
}

#[test]
fn test_working_basic() {
    let sample_count = super::packet::BUFFER_SIZE;
    test_sample_count(sample_count, 0);
}

#[test]
fn test_working_multi_packet() {
    let sample_count = super::packet::BUFFER_SIZE * 32;
    test_sample_count(sample_count, 1);
}

fn test_sample_count(sample_count: usize, port: u8) {
    let tx_desc = get_ladspa_descriptor(0).unwrap();
    let rx_desc = get_ladspa_descriptor(1).unwrap();
    let mut tx = (tx_desc.new)(&tx_desc, SAMPLE_RATE);
    let mut rx = (rx_desc.new)(&rx_desc, SAMPLE_RATE);

    rx.activate();
    tx.activate();

    let mut tx_owned = make_owned_port_connections(&tx_desc.ports, sample_count);
    tx_owned.set_tags(port as f32, 1.0, 0.0);
    let mut rx_owned = make_owned_port_connections(&rx_desc.ports, sample_count);
    rx_owned.set_tags(port as f32, 0.0, 0.0);

    // run once to handle channel change
    {
        let tx_ports = make_port_connections(&mut tx_owned);
        let rx_ports = make_port_connections(&mut rx_owned);
        let tx_ports = borrow_port_connections(&tx_ports);
        let rx_ports = borrow_port_connections(&rx_ports);

        rx.run(sample_count, &rx_ports);
        tx.run(sample_count, &tx_ports);
    }

    // reset state
    rx.deactivate();
    tx.deactivate();
    rx.activate();
    thread::sleep(Duration::from_millis(100));
    tx.activate();
    thread::sleep(Duration::from_millis(100));

    tx_owned.set_tags(port as f32, 1.0, 0.0);
    rx_owned.set_tags(port as f32, 0.0, 0.0);

    // run again to do the computation
    {
        let tx_ports = make_port_connections(&mut tx_owned);
        let rx_ports = make_port_connections(&mut rx_owned);
        let tx_ports = borrow_port_connections(&tx_ports);
        let rx_ports = borrow_port_connections(&rx_ports);

        tx.run(sample_count, &tx_ports);
        thread::sleep(Duration::from_millis(100)); // wait for recv
        rx.run(sample_count, &rx_ports);
    }

    for i in 0..2 {
        assert_eq!(tx_owned[i].data, rx_owned[i + 2].data);
    }

    rx.deactivate();
    tx.deactivate();
}
<|endoftext|>


<commit_before>use std::env;

fn newmat(x: usize, y: usize) -> Vec<Vec<f64>> {
  let mut r = Vec::new();
  for _ in 0..x {
    let mut c = Vec::new();
    for _ in 0..y { c.push(0_f64); }
    r.push(c);
  }
  r
}

fn matgen(n: usize) -> Vec<Vec<f64>> {
  let mut a = newmat(n, n);
  let tmp = 1_f64 / (n as f64) / (n as f64);
  for i in 0..n {
    for j in 0..n {
      let val = tmp * (i as f64 - j as f64) * (i as f64 + j as f64);
      *a.get_mut(i).unwrap().get_mut(j).unwrap() = val; // Wtf, rust O_o
    }
  }
  a
}

fn matmul(a: Vec<Vec<f64>>, b: Vec<Vec<f64>>) -> Vec<Vec<f64>> {
  let m = a.len();
  let n = a[0].len();
  let p = b[0].len();

  let mut b2 = newmat(n, p);
  for i in 0..n {
    for j in 0..p {
      *b2.get_mut(j).unwrap().get_mut(i).unwrap() = b[i][j];
    }
  }

  let mut c = newmat(m, p);
  for i in 0..m {
    for j in 0..p {
      let mut s = 0_f64;
      let ref ai = a[i];
      let ref b2j = b2[j];
      for k in 0..n {
        s += ai[k] * b2j[k];
      }
      *c.get_mut(i).unwrap().get_mut(j).unwrap() = s;
    }
  }

  c
}

fn main() {
  let mut n = 100;
  if env::args().len() > 1 {
    let arg1 = env::args().nth(1).unwrap();
    n = ::std::str::FromStr::from_str(&arg1).unwrap();
  }
  n = n / 2 * 2;

  let a = matgen(n);
  let b = matgen(n);
  let c = matmul(a, b);
  print!("{}\n", c[n / 2][n / 2]);
}
<commit_msg>O_o rust<commit_after>use std::env;

fn newmat(x: usize, y: usize) -> Vec<Vec<f64>> {
  let mut r = Vec::new();
  for _ in 0..x {
    let mut c = Vec::new();
    for _ in 0..y { c.push(0_f64); }
    r.push(c);
  }
  r
}

fn matgen(n: usize) -> Vec<Vec<f64>> {
  let mut a = newmat(n, n);
  let tmp = 1_f64 / (n as f64) / (n as f64);
  for i in 0..n {
    for j in 0..n {
      let val = tmp * (i as f64 - j as f64) * (i as f64 + j as f64);
      a[i][j] = val;
    }
  }
  a
}

fn matmul(a: Vec<Vec<f64>>, b: Vec<Vec<f64>>) -> Vec<Vec<f64>> {
  let m = a.len();
  let n = a[0].len();
  let p = b[0].len();

  let mut b2 = newmat(n, p);
  for i in 0..n {
    for j in 0..p {
      b2[j][i] = b[i][j];
    }
  }

  let mut c = newmat(m, p);
  for i in 0..m {
    for j in 0..p {
      let mut s = 0_f64;
      let ref ai = a[i];
      let ref b2j = b2[j];
      for k in 0..n {
        s += ai[k] * b2j[k];
      }
      c[i][j] = s;
    }
  }

  c
}

fn main() {
  let mut n = 100;
  if env::args().len() > 1 {
    let arg1 = env::args().nth(1).unwrap();
    n = ::std::str::FromStr::from_str(&arg1).unwrap();
  }
  n = n / 2 * 2;

  let a = matgen(n);
  let b = matgen(n);
  let c = matmul(a, b);
  print!("{}\n", c[n / 2][n / 2]);
}
<|endoftext|>


<commit_before>#[macro_use] extern crate iron;
extern crate iron_sessionstorage;

use iron::prelude::*;

use iron_sessionstorage::traits::*;
use iron_sessionstorage::SessionStorage;
use iron_sessionstorage::backends::SignedCookieBackend;

struct Aaa(String);

impl iron_sessionstorage::Value for Aaa {
    fn get_key() -> &'static str { "foo" }
    fn into_raw(self) -> String { self.0 }
    fn from_raw(value: &str) -> Option<Self> {
        // Maybe validate that only 'a's are in the string
        Some(Aaa(value.to_owned()))
    }
}

fn handler(req: &mut Request) -> IronResult<Response> {
    let mut value = match try!(req.session().get::<Aaa>()) {
        Some(aaa) => aaa,
        None => Aaa("".to_owned())
    };

    let res = Ok(Response::with(
        format!("Reload this page to add an a: {}\n\n \
                 Clear cookies to reset.", &value.0)
    ));

    value.0.push('a');
    try!(req.session().set(value));
    res
}

fn main() {
    let my_secret = b"verysecret".to_vec();
    let mut ch = Chain::new(handler);
    ch.link_around(SessionStorage::new(SignedCookieBackend::new(my_secret)));
    let _res = Iron::new(ch).http("localhost:8080");
    println!("Listening on 8080.");
}
<commit_msg>Fix basic example<commit_after>#[macro_use] extern crate iron;
extern crate iron_sessionstorage;

use iron::prelude::*;

use iron_sessionstorage::traits::*;
use iron_sessionstorage::SessionStorage;
use iron_sessionstorage::backends::SignedCookieBackend;

struct Aaa(String);

impl iron_sessionstorage::Value for Aaa {
    fn get_key() -> &'static str { "foo" }
    fn into_raw(self) -> String { self.0 }
    fn from_raw(value: String) -> Option<Self> {
        // Maybe validate that only 'a's are in the string
        Some(Aaa(value))
    }
}

fn handler(req: &mut Request) -> IronResult<Response> {
    let mut value = match try!(req.session().get::<Aaa>()) {
        Some(aaa) => aaa,
        None => Aaa("".to_owned())
    };

    let res = Ok(Response::with(
        format!("Reload this page to add an a: {}\n\n \
                 Clear cookies to reset.", &value.0)
    ));

    value.0.push('a');
    try!(req.session().set(value));
    res
}

fn main() {
    let my_secret = b"verysecret".to_vec();
    let mut ch = Chain::new(handler);
    ch.link_around(SessionStorage::new(SignedCookieBackend::new(my_secret)));
    let _res = Iron::new(ch).http("localhost:8080");
    println!("Listening on 8080.");
}
<|endoftext|>


<commit_before>/// unit creates a type representing a single unit.
///
/// # Examples
///
/// ```
/// #[macro_use(unit)]
/// extern crate fiz_math;
/// use std::fmt::Debug;
///
/// // GoldCoins are golden!
/// unit!(GoldCoins);
///
/// // SilverCoins are like gold coins, only worse!
/// unit!(SilverCoins);
///
/// fn collect<T: Debug>(coins: GoldCoins<T>) {
///     println!("We've collected {:?} golden coins!", coins.0);
/// }
///
/// fn main() {
///     let x = GoldCoins(5);
///     collect(x);
///
///     let y = SilverCoins(6);
///
///     // Try uncommenting the line below and see:
///     //
///     // error: mismatched types: expected `GoldCoins<_>`, found `SilverCoins<_>`"
///     //
///     //collect(y);
///
///     // add, subtract, multiply, divide:
///     assert_eq!(y + SilverCoins(4), SilverCoins(10));
///     assert_eq!(y - SilverCoins(3), SilverCoins(3));
///     assert_eq!(y * SilverCoins(3), SilverCoins(18));
///     assert_eq!(y / SilverCoins(2), SilverCoins(3));
///
///     // ordering and equality:
///     assert!(y < SilverCoins(7));
///     assert!(y > SilverCoins(5));
///     assert!(y <= SilverCoins(6));
///     assert!(y >= SilverCoins(6));
///     assert!(y == SilverCoins(6));
/// }
/// ```
///
#[macro_export]
macro_rules! unit {
    ( $ident:ident ) => {
        #[derive(Copy, Clone, Debug)]
        pub struct $ident<T>(pub T);

        // addition
        impl<T: ::std::ops::Add<Output = T>> ::std::ops::Add for $ident<T> {
            type Output = Self;

            fn add(self, _rhs: Self) -> Self {
                $ident(self.0 + _rhs.0)
            }
        }

        // subtraction
        impl<T: ::std::ops::Sub<Output = T>> ::std::ops::Sub for $ident<T> {
            type Output = Self;

            fn sub(self, _rhs: Self) -> Self {
                $ident(self.0 - _rhs.0)
            }
        }

        // multiplication
        impl<T: ::std::ops::Mul<Output = T>> ::std::ops::Mul for $ident<T> {
            type Output = Self;

            fn mul(self, _rhs: Self) -> Self {
                $ident(self.0 * _rhs.0)
            }
        }

        // division
        impl<T: ::std::ops::Div<Output = T>> ::std::ops::Div for $ident<T> {
            type Output = Self;

            fn div(self, _rhs: Self) -> Self {
                $ident(self.0 / _rhs.0)
            }
        }

        // remainder
        impl<T: ::std::ops::Rem<Output = T>> ::std::ops::Rem for $ident<T> {
            type Output = Self;

            fn rem(self, rhs: Self) -> Self { $ident(self.0 % rhs.0) }
        }

        // negation
        impl<T: ::std::ops::Neg<Output = T>> ::std::ops::Neg for $ident<T> {
            type Output = Self;

            fn neg(self) -> Self::Output { $ident(-self.0) }
        }

        // not
        impl<T: ::std::ops::Not<Output = T>> ::std::ops::Not for $ident<T> {
            type Output = Self;

            fn not(self) -> Self::Output { $ident(!self.0) }
        }

        // bitwise and
        impl<T: ::std::ops::BitAnd<Output = T>> ::std::ops::BitAnd for $ident<T> {
            type Output = Self;

            fn bitand(self, rhs: Self) -> Self::Output { $ident(self.0 & rhs.0) }
        }

        // bitwise or
        impl<T: ::std::ops::BitOr<Output = T>> ::std::ops::BitOr for $ident<T> {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output { $ident(self.0 | rhs.0) }
        }

        // partial equality
        impl<T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for $ident<T> {
            fn eq(&self, _rhs: &Self) -> bool {
                self.0 == _rhs.0
            }
        }

        // equality
        impl<T: ::std::cmp::Eq> ::std::cmp::Eq for $ident<T> {}

        // partial ordering
        impl<T: ::std::cmp::PartialOrd> ::std::cmp::PartialOrd for $ident<T> {
            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
                if self.0 < other.0 {
                    Some(::std::cmp::Ordering::Less)
                } else if self.0 > other.0 {
                    Some(::std::cmp::Ordering::Greater)
                } else if self == other {
                    Some(::std::cmp::Ordering::Equal)
                } else {
                    None
                }
            }
        }

        // total ordering
        impl<T: ::std::cmp::Ord> ::std::cmp::Ord for $ident<T> {
            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                if self.0 < other.0 {
                    ::std::cmp::Ordering::Less
                } else if self.0 > other.0 {
                    ::std::cmp::Ordering::Greater
                } else {
                    ::std::cmp::Ordering::Equal
                }
            }
        }
    };
}
<commit_msg>unit! implement bitwise xor operator<commit_after>/// unit creates a type representing a single unit.
///
/// # Examples
///
/// ```
/// #[macro_use(unit)]
/// extern crate fiz_math;
/// use std::fmt::Debug;
///
/// // GoldCoins are golden!
/// unit!(GoldCoins);
///
/// // SilverCoins are like gold coins, only worse!
/// unit!(SilverCoins);
///
/// fn collect<T: Debug>(coins: GoldCoins<T>) {
///     println!("We've collected {:?} golden coins!", coins.0);
/// }
///
/// fn main() {
///     let x = GoldCoins(5);
///     collect(x);
///
///     let y = SilverCoins(6);
///
///     // Try uncommenting the line below and see:
///     //
///     // error: mismatched types: expected `GoldCoins<_>`, found `SilverCoins<_>`"
///     //
///     //collect(y);
///
///     // add, subtract, multiply, divide:
///     assert_eq!(y + SilverCoins(4), SilverCoins(10));
///     assert_eq!(y - SilverCoins(3), SilverCoins(3));
///     assert_eq!(y * SilverCoins(3), SilverCoins(18));
///     assert_eq!(y / SilverCoins(2), SilverCoins(3));
///
///     // ordering and equality:
///     assert!(y < SilverCoins(7));
///     assert!(y > SilverCoins(5));
///     assert!(y <= SilverCoins(6));
///     assert!(y >= SilverCoins(6));
///     assert!(y == SilverCoins(6));
/// }
/// ```
///
#[macro_export]
macro_rules! unit {
    ( $ident:ident ) => {
        #[derive(Copy, Clone, Debug)]
        pub struct $ident<T>(pub T);

        // addition
        impl<T: ::std::ops::Add<Output = T>> ::std::ops::Add for $ident<T> {
            type Output = Self;

            fn add(self, _rhs: Self) -> Self {
                $ident(self.0 + _rhs.0)
            }
        }

        // subtraction
        impl<T: ::std::ops::Sub<Output = T>> ::std::ops::Sub for $ident<T> {
            type Output = Self;

            fn sub(self, _rhs: Self) -> Self {
                $ident(self.0 - _rhs.0)
            }
        }

        // multiplication
        impl<T: ::std::ops::Mul<Output = T>> ::std::ops::Mul for $ident<T> {
            type Output = Self;

            fn mul(self, _rhs: Self) -> Self {
                $ident(self.0 * _rhs.0)
            }
        }

        // division
        impl<T: ::std::ops::Div<Output = T>> ::std::ops::Div for $ident<T> {
            type Output = Self;

            fn div(self, _rhs: Self) -> Self {
                $ident(self.0 / _rhs.0)
            }
        }

        // remainder
        impl<T: ::std::ops::Rem<Output = T>> ::std::ops::Rem for $ident<T> {
            type Output = Self;

            fn rem(self, rhs: Self) -> Self { $ident(self.0 % rhs.0) }
        }

        // negation
        impl<T: ::std::ops::Neg<Output = T>> ::std::ops::Neg for $ident<T> {
            type Output = Self;

            fn neg(self) -> Self::Output { $ident(-self.0) }
        }

        // not
        impl<T: ::std::ops::Not<Output = T>> ::std::ops::Not for $ident<T> {
            type Output = Self;

            fn not(self) -> Self::Output { $ident(!self.0) }
        }

        // bitwise and
        impl<T: ::std::ops::BitAnd<Output = T>> ::std::ops::BitAnd for $ident<T> {
            type Output = Self;

            fn bitand(self, rhs: Self) -> Self::Output { $ident(self.0 & rhs.0) }
        }

        // bitwise or
        impl<T: ::std::ops::BitOr<Output = T>> ::std::ops::BitOr for $ident<T> {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output { $ident(self.0 | rhs.0) }
        }

        // bitwise xor
        impl<T: ::std::ops::BitXor<Output = T>> ::std::ops::BitXor for $ident<T> {
            type Output = Self;

            fn bitxor(self, rhs: Self) -> Self::Output { $ident(self.0 ^ rhs.0) }
        }

        // partial equality
        impl<T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for $ident<T> {
            fn eq(&self, _rhs: &Self) -> bool {
                self.0 == _rhs.0
            }
        }

        // equality
        impl<T: ::std::cmp::Eq> ::std::cmp::Eq for $ident<T> {}

        // partial ordering
        impl<T: ::std::cmp::PartialOrd> ::std::cmp::PartialOrd for $ident<T> {
            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
                if self.0 < other.0 {
                    Some(::std::cmp::Ordering::Less)
                } else if self.0 > other.0 {
                    Some(::std::cmp::Ordering::Greater)
                } else if self == other {
                    Some(::std::cmp::Ordering::Equal)
                } else {
                    None
                }
            }
        }

        // total ordering
        impl<T: ::std::cmp::Ord> ::std::cmp::Ord for $ident<T> {
            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                if self.0 < other.0 {
                    ::std::cmp::Ordering::Less
                } else if self.0 > other.0 {
                    ::std::cmp::Ordering::Greater
                } else {
                    ::std::cmp::Ordering::Equal
                }
            }
        }
    };
}
<|endoftext|>


<commit_before>/// unit creates a type representing a single unit.
///
/// # Examples
///
/// ```
/// #[macro_use(unit)]
/// extern crate fiz_math;
/// use std::fmt::Debug;
///
/// // GoldCoins are golden!
/// unit!(GoldCoins);
///
/// // SilverCoins are like gold coins, only worse!
/// unit!(SilverCoins);
///
/// fn collect<T: Debug>(coins: GoldCoins<T>) {
///     println!("We've collected {:?} golden coins!", coins.0);
/// }
///
/// fn main() {
///     let x = GoldCoins(5);
///     collect(x);
///
///     let y = SilverCoins(6);
///
///     // Try uncommenting the line below and see:
///     //
///     // error: mismatched types: expected `GoldCoins<_>`, found `SilverCoins<_>`"
///     //
///     //collect(y);
///
///     // add, subtract, multiply, divide:
///     assert_eq!(y + SilverCoins(4), SilverCoins(10));
///     assert_eq!(y - SilverCoins(3), SilverCoins(3));
///     assert_eq!(y * SilverCoins(3), SilverCoins(18));
///     assert_eq!(y / SilverCoins(2), SilverCoins(3));
///
///     // ordering and equality:
///     assert!(y < SilverCoins(7));
///     assert!(y > SilverCoins(5));
///     assert!(y <= SilverCoins(6));
///     assert!(y >= SilverCoins(6));
///     assert!(y == SilverCoins(6));
/// }
/// ```
///
#[macro_export]
macro_rules! unit {
    ( $ident:ident ) => {
        #[derive(Copy, Clone, Debug)]
        pub struct $ident<T>(pub T);

        unit!(impl_std_ops, $ident);
        unit!(impl_std_cmp, $ident);
        unit!(impl_num_traits, $ident);
    };

    (impl_std_ops, $ident:ident ) => {
        // addition
        impl<T: ::std::ops::Add<Output = T>> ::std::ops::Add for $ident<T> {
            type Output = Self;

            fn add(self, _rhs: Self) -> Self {
                $ident(self.0 + _rhs.0)
            }
        }

        // subtraction
        impl<T: ::std::ops::Sub<Output = T>> ::std::ops::Sub for $ident<T> {
            type Output = Self;

            fn sub(self, _rhs: Self) -> Self {
                $ident(self.0 - _rhs.0)
            }
        }

        // multiplication
        impl<T: ::std::ops::Mul<Output = T>> ::std::ops::Mul for $ident<T> {
            type Output = Self;

            fn mul(self, _rhs: Self) -> Self {
                $ident(self.0 * _rhs.0)
            }
        }

        // division
        impl<T: ::std::ops::Div<Output = T>> ::std::ops::Div for $ident<T> {
            type Output = Self;

            fn div(self, _rhs: Self) -> Self {
                $ident(self.0 / _rhs.0)
            }
        }

        // remainder
        impl<T: ::std::ops::Rem<Output = T>> ::std::ops::Rem for $ident<T> {
            type Output = Self;

            fn rem(self, rhs: Self) -> Self { $ident(self.0 % rhs.0) }
        }

        // negation
        impl<T: ::std::ops::Neg<Output = T>> ::std::ops::Neg for $ident<T> {
            type Output = Self;

            fn neg(self) -> Self::Output { $ident(-self.0) }
        }

        // not
        impl<T: ::std::ops::Not<Output = T>> ::std::ops::Not for $ident<T> {
            type Output = Self;

            fn not(self) -> Self::Output { $ident(!self.0) }
        }

        // bitwise and
        impl<T: ::std::ops::BitAnd<Output = T>> ::std::ops::BitAnd for $ident<T> {
            type Output = Self;

            fn bitand(self, rhs: Self) -> Self::Output { $ident(self.0 & rhs.0) }
        }

        // bitwise or
        impl<T: ::std::ops::BitOr<Output = T>> ::std::ops::BitOr for $ident<T> {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output { $ident(self.0 | rhs.0) }
        }

        // bitwise xor
        impl<T: ::std::ops::BitXor<Output = T>> ::std::ops::BitXor for $ident<T> {
            type Output = Self;

            fn bitxor(self, rhs: Self) -> Self::Output { $ident(self.0 ^ rhs.0) }
        }

        // shift left
        impl<T: ::std::ops::Shl<usize>> ::std::ops::Shl<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shl(self, rhs: usize) -> Self::Output { $ident(self.0 << rhs) }
        }

        // shift right
        impl<T: ::std::ops::Shr<usize>> ::std::ops::Shr<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shr(self, rhs: usize) -> Self::Output { $ident(self.0 >> rhs) }
        }
    };

    (impl_std_cmp, $ident:ident ) => {
        // partial equality
        impl<T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for $ident<T> {
            fn eq(&self, _rhs: &Self) -> bool {
                self.0 == _rhs.0
            }
        }

        // equality
        impl<T: ::std::cmp::Eq> ::std::cmp::Eq for $ident<T> {}

        // partial ordering
        impl<T: ::std::cmp::PartialOrd> ::std::cmp::PartialOrd for $ident<T> {
            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
                if self.0 < other.0 {
                    Some(::std::cmp::Ordering::Less)
                } else if self.0 > other.0 {
                    Some(::std::cmp::Ordering::Greater)
                } else if self == other {
                    Some(::std::cmp::Ordering::Equal)
                } else {
                    None
                }
            }
        }

        // total ordering
        impl<T: ::std::cmp::Ord> ::std::cmp::Ord for $ident<T> {
            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                if self.0 < other.0 {
                    ::std::cmp::Ordering::Less
                } else if self.0 > other.0 {
                    ::std::cmp::Ordering::Greater
                } else {
                    ::std::cmp::Ordering::Equal
                }
            }
        }
    };

    (impl_num_traits, $ident:ident ) => {
        impl<T: $crate::num_export::traits::Zero> $crate::num_export::traits::Zero for $ident<T> {
            fn zero() -> Self { $ident(T::zero()) }
            fn is_zero(&self) -> bool { self.0.is_zero() }
        }
    };
}
<commit_msg>unit! impl num::traits::One<commit_after>/// unit creates a type representing a single unit.
///
/// # Examples
///
/// ```
/// #[macro_use(unit)]
/// extern crate fiz_math;
/// use std::fmt::Debug;
///
/// // GoldCoins are golden!
/// unit!(GoldCoins);
///
/// // SilverCoins are like gold coins, only worse!
/// unit!(SilverCoins);
///
/// fn collect<T: Debug>(coins: GoldCoins<T>) {
///     println!("We've collected {:?} golden coins!", coins.0);
/// }
///
/// fn main() {
///     let x = GoldCoins(5);
///     collect(x);
///
///     let y = SilverCoins(6);
///
///     // Try uncommenting the line below and see:
///     //
///     // error: mismatched types: expected `GoldCoins<_>`, found `SilverCoins<_>`"
///     //
///     //collect(y);
///
///     // add, subtract, multiply, divide:
///     assert_eq!(y + SilverCoins(4), SilverCoins(10));
///     assert_eq!(y - SilverCoins(3), SilverCoins(3));
///     assert_eq!(y * SilverCoins(3), SilverCoins(18));
///     assert_eq!(y / SilverCoins(2), SilverCoins(3));
///
///     // ordering and equality:
///     assert!(y < SilverCoins(7));
///     assert!(y > SilverCoins(5));
///     assert!(y <= SilverCoins(6));
///     assert!(y >= SilverCoins(6));
///     assert!(y == SilverCoins(6));
/// }
/// ```
///
#[macro_export]
macro_rules! unit {
    ( $ident:ident ) => {
        #[derive(Copy, Clone, Debug)]
        pub struct $ident<T>(pub T);

        unit!(impl_std_ops, $ident);
        unit!(impl_std_cmp, $ident);
        unit!(impl_num_traits, $ident);
    };

    (impl_std_ops, $ident:ident ) => {
        // addition
        impl<T: ::std::ops::Add<Output = T>> ::std::ops::Add for $ident<T> {
            type Output = Self;

            fn add(self, _rhs: Self) -> Self {
                $ident(self.0 + _rhs.0)
            }
        }

        // subtraction
        impl<T: ::std::ops::Sub<Output = T>> ::std::ops::Sub for $ident<T> {
            type Output = Self;

            fn sub(self, _rhs: Self) -> Self {
                $ident(self.0 - _rhs.0)
            }
        }

        // multiplication
        impl<T: ::std::ops::Mul<Output = T>> ::std::ops::Mul for $ident<T> {
            type Output = Self;

            fn mul(self, _rhs: Self) -> Self {
                $ident(self.0 * _rhs.0)
            }
        }

        // division
        impl<T: ::std::ops::Div<Output = T>> ::std::ops::Div for $ident<T> {
            type Output = Self;

            fn div(self, _rhs: Self) -> Self {
                $ident(self.0 / _rhs.0)
            }
        }

        // remainder
        impl<T: ::std::ops::Rem<Output = T>> ::std::ops::Rem for $ident<T> {
            type Output = Self;

            fn rem(self, rhs: Self) -> Self { $ident(self.0 % rhs.0) }
        }

        // negation
        impl<T: ::std::ops::Neg<Output = T>> ::std::ops::Neg for $ident<T> {
            type Output = Self;

            fn neg(self) -> Self::Output { $ident(-self.0) }
        }

        // not
        impl<T: ::std::ops::Not<Output = T>> ::std::ops::Not for $ident<T> {
            type Output = Self;

            fn not(self) -> Self::Output { $ident(!self.0) }
        }

        // bitwise and
        impl<T: ::std::ops::BitAnd<Output = T>> ::std::ops::BitAnd for $ident<T> {
            type Output = Self;

            fn bitand(self, rhs: Self) -> Self::Output { $ident(self.0 & rhs.0) }
        }

        // bitwise or
        impl<T: ::std::ops::BitOr<Output = T>> ::std::ops::BitOr for $ident<T> {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output { $ident(self.0 | rhs.0) }
        }

        // bitwise xor
        impl<T: ::std::ops::BitXor<Output = T>> ::std::ops::BitXor for $ident<T> {
            type Output = Self;

            fn bitxor(self, rhs: Self) -> Self::Output { $ident(self.0 ^ rhs.0) }
        }

        // shift left
        impl<T: ::std::ops::Shl<usize>> ::std::ops::Shl<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shl(self, rhs: usize) -> Self::Output { $ident(self.0 << rhs) }
        }

        // shift right
        impl<T: ::std::ops::Shr<usize>> ::std::ops::Shr<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shr(self, rhs: usize) -> Self::Output { $ident(self.0 >> rhs) }
        }
    };

    (impl_std_cmp, $ident:ident ) => {
        // partial equality
        impl<T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for $ident<T> {
            fn eq(&self, _rhs: &Self) -> bool {
                self.0 == _rhs.0
            }
        }

        // equality
        impl<T: ::std::cmp::Eq> ::std::cmp::Eq for $ident<T> {}

        // partial ordering
        impl<T: ::std::cmp::PartialOrd> ::std::cmp::PartialOrd for $ident<T> {
            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
                if self.0 < other.0 {
                    Some(::std::cmp::Ordering::Less)
                } else if self.0 > other.0 {
                    Some(::std::cmp::Ordering::Greater)
                } else if self == other {
                    Some(::std::cmp::Ordering::Equal)
                } else {
                    None
                }
            }
        }

        // total ordering
        impl<T: ::std::cmp::Ord> ::std::cmp::Ord for $ident<T> {
            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                if self.0 < other.0 {
                    ::std::cmp::Ordering::Less
                } else if self.0 > other.0 {
                    ::std::cmp::Ordering::Greater
                } else {
                    ::std::cmp::Ordering::Equal
                }
            }
        }
    };

    (impl_num_traits, $ident:ident ) => {
        impl<T: $crate::num_export::traits::Zero> $crate::num_export::traits::Zero for $ident<T> {
            fn zero() -> Self { $ident(T::zero()) }
            fn is_zero(&self) -> bool { self.0.is_zero() }
        }

        impl<T: $crate::num_export::traits::One> $crate::num_export::traits::One for $ident<T> {
            fn one() -> Self { $ident(T::one()) }
        }
    };
}
<|endoftext|>


<commit_before>//! # SysTick for the LM4F120
//!
//! Each Cortex-M4 has a timer peripheral typically used for OS scheduling tick.
//! Here we configure it as a countdown timer that overflows every 2**24 ticks
//! (so about once a second at 16MHz), and maintain a separate atomic overflow
//! count to accurately track time since power-up.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use cortex_m::peripheral as cm_periph;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

/// SysTick is a 24-bit timer
pub const SYSTICK_MAX: usize = (1 << 24) - 1;

lazy_static! {
    /// total number of times SysTick has wrapped
    pub static ref SYSTICK_WRAP_COUNT:AtomicUsize = ATOMIC_USIZE_INIT;
}

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// *****************************************************************************
//
// The following are defines for the bit fields in the NVIC_ST_CTRL register.
//
// *****************************************************************************
const NVIC_ST_CTRL_INTEN: usize = 0x00000002; // Interrupt Enable
const NVIC_ST_CTRL_ENABLE: usize = 0x00000001; // Enable

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Initialises the SysTick system.
///
/// We configure SysTick to run at PIOSC / 4, with the full 24 bit range.
pub fn init() {
    unsafe {
        let syst = cm_periph::syst_mut();
        syst.rvr.write(SYSTICK_MAX as u32);
        // A write to current resets the timer
        syst.cvr.write(0);
        // Set to multi-shot mode, with interrupts on and on the PIOSC / 4
        syst.csr.write((NVIC_ST_CTRL_ENABLE | NVIC_ST_CTRL_INTEN) as u32);
    }
}

/// Should be attached to the SysTick vector in the interrupt vector table.
/// Called when SysTick hits zero. Increments an overflow counter atomically.
pub fn isr() {
    SYSTICK_WRAP_COUNT.fetch_add(1, Ordering::Relaxed);
}

/// Returns how many times SysTick has overflowed.
pub fn get_overflows() -> usize {
    SYSTICK_WRAP_COUNT.load(Ordering::Relaxed)
}

/// Gets the current SysTick value
pub fn get_ticks() -> usize {
    cm_periph::syst().cvr.read() as usize
}

/// Returns (overflows, ticks), correctly handling the case that it overflowed
/// between the two separate reads that are required.
pub fn get_overflows_ticks() -> (usize, usize) {
    let overflow1 = get_overflows();
    let ticks = get_ticks();
    let overflow2 = get_overflows();
    if overflow1 != overflow2 {
        // A overflow occurred while we were reading the tick register
        // Should be safe to try again
        (overflow2, get_ticks())
    } else {
        // No overflow, good to go
        (overflow1, ticks)
    }
}

/// Calculates the elapsed period in SysTicks between `start` and the current value.
pub fn get_since(start: usize) -> usize {
    let now = get_ticks();
    // SysTick counts down! This subtraction is opposite to what you expect.
    let delta = start.wrapping_sub(now) & SYSTICK_MAX;
    delta
}

/// How long since the system booted in ticks.
/// The u64 is good for 584,000 years.
pub fn run_time_ticks() -> u64 {
    let (overflows, ticks) = get_overflows_ticks();
    let mut result: u64;
    result = overflows as u64;
    result *= (SYSTICK_MAX + 1) as u64;
    result += (SYSTICK_MAX - ticks) as u64;
    result
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

// None

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>Fix comments in generic systick code.<commit_after>//! # SysTick for the Cortex-M4F
//!
//! Each Cortex-M4 has a timer peripheral typically used for OS scheduling tick.
//! Here we configure it as a countdown timer that overflows every 2**24 ticks
//! (so about once a second at 16MHz), and maintain a separate atomic overflow
//! count to accurately track time since power-up.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use cortex_m::peripheral as cm_periph;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

/// SysTick is a 24-bit timer
pub const SYSTICK_MAX: usize = (1 << 24) - 1;

lazy_static! {
    /// total number of times SysTick has wrapped
    pub static ref SYSTICK_WRAP_COUNT:AtomicUsize = ATOMIC_USIZE_INIT;
}

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// *****************************************************************************
//
// The following are defines for the bit fields in the NVIC_ST_CTRL register.
//
// *****************************************************************************
const NVIC_ST_CTRL_INTEN: usize = 0x00000002; // Interrupt Enable
const NVIC_ST_CTRL_ENABLE: usize = 0x00000001; // Enable

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Initialises the SysTick system.
///
/// We configure SysTick to run at PIOSC / 4, with the full 24 bit range.
pub fn init() {
    unsafe {
        let syst = cm_periph::syst_mut();
        syst.rvr.write(SYSTICK_MAX as u32);
        // A write to current resets the timer
        syst.cvr.write(0);
        // Set to multi-shot mode, with interrupts on and on the PIOSC / 4
        syst.csr.write((NVIC_ST_CTRL_ENABLE | NVIC_ST_CTRL_INTEN) as u32);
    }
}

/// Should be attached to the SysTick vector in the interrupt vector table.
/// Called when SysTick hits zero. Increments an overflow counter atomically.
pub fn isr() {
    SYSTICK_WRAP_COUNT.fetch_add(1, Ordering::Relaxed);
}

/// Returns how many times SysTick has overflowed.
pub fn get_overflows() -> usize {
    SYSTICK_WRAP_COUNT.load(Ordering::Relaxed)
}

/// Gets the current SysTick value
pub fn get_ticks() -> usize {
    cm_periph::syst().cvr.read() as usize
}

/// Returns (overflows, ticks), correctly handling the case that it overflowed
/// between the two separate reads that are required.
pub fn get_overflows_ticks() -> (usize, usize) {
    let overflow1 = get_overflows();
    let ticks = get_ticks();
    let overflow2 = get_overflows();
    if overflow1 != overflow2 {
        // A overflow occurred while we were reading the tick register
        // Should be safe to try again
        (overflow2, get_ticks())
    } else {
        // No overflow, good to go
        (overflow1, ticks)
    }
}

/// Calculates the elapsed period in SysTicks between `start` and the current value.
pub fn get_since(start: usize) -> usize {
    let now = get_ticks();
    // SysTick counts down! This subtraction is opposite to what you expect.
    let delta = start.wrapping_sub(now) & SYSTICK_MAX;
    delta
}

/// How long since the system booted in ticks.
/// The u64 is good for 584,000 years.
pub fn run_time_ticks() -> u64 {
    let (overflows, ticks) = get_overflows_ticks();
    let mut result: u64;
    result = overflows as u64;
    result *= (SYSTICK_MAX + 1) as u64;
    result += (SYSTICK_MAX - ticks) as u64;
    result
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

// None

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>


<commit_before>use std::ffi::{CStr, CString};

use types;

pub fn str_as_ptr(str: &str) -> *const types::c_char {
    CString::new(str).unwrap().as_ptr()
}

pub fn cstr_as_str(str: *const types::c_char) -> String {
    unsafe {
        CStr::from_ptr(str).to_string_lossy().into_owned()
    }
}
<commit_msg>Rename cstr_as_str to cstr_as_string<commit_after>use std::ffi::{CStr, CString};

use types;

pub fn str_as_ptr(str: &str) -> *const types::c_char {
    CString::new(str).unwrap().as_ptr()
}

pub fn cstr_as_string(str: *const types::c_char) -> String {
    unsafe {
        CStr::from_ptr(str).to_string_lossy().into_owned()
    }
}
<|endoftext|>


<commit_before>extern crate orbclient;
extern crate orbtk;

use orbtk::{ Color, Window, List, Entry, Label };
use orbtk::traits::{ Place, Text, Click };

use std::{fs, io};
use std::cell::RefCell;
use std::cmp::Ordering;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::rc::Rc;

#[derive(Clone, Debug, Eq, PartialEq)]
struct FolderItem {
    path: PathBuf,
    name: String,
    dir: bool,
}

impl Ord for FolderItem {
    fn cmp(&self, other: &Self) -> Ordering {
        if self.dir && ! other.dir {
            Ordering::Less
        } else if ! self.dir && other.dir {
            Ordering::Greater
        } else {
            self.name.cmp(&other.name)
        }
    }
}

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

impl FolderItem {
    pub fn scan<P: AsRef<Path>>(path: P) -> io::Result<Vec<Result<Self, String>>> {
        let canon = path.as_ref().canonicalize()?;

        let mut items = vec![];

        if let Some(parent) = canon.parent() {
            items.push(Ok(FolderItem {
                path: parent.to_owned(),
                name: "..".to_string(),
                dir: true,
            }));
        }

        for entry_res in fs::read_dir(&canon)? {
            let item = match entry_res {
                Ok(entry) => match entry.file_name().into_string() {
                    Ok(name) => match entry.file_type() {
                        Ok(file_type) => Ok(FolderItem {
                            path: entry.path(),
                            name: name,
                            dir: file_type.is_dir(),
                        }),
                        Err(err) => Err(format!("{}", err))
                    },
                    Err(os_str) => Err(format!("Invalid filename: {:?}", os_str))
                },
                Err(err) => Err(format!("{}", err))
            };

            items.push(item);
        }

        items.sort();

        Ok(items)
    }
}

fn file_dialog<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
    let path_opt = Rc::new(RefCell::new(
        Some(path.as_ref().to_owned())
    ));

    let w = 640;
    let h = 480;

    let mut orb_window = Some(orbclient::Window::new(-1, -1, w, h, "File Dialog").unwrap());

    loop {
        let path = match path_opt.borrow_mut().take() {
            Some(path) => if ! path.is_dir() {
                return Some(path);
            } else {
                path
            },
            None => return None
        };

        let mut window = Box::new(Window::from_inner(orb_window.take().unwrap()));

        let list = List::new();
        list.position(2, 2).size(w - 4, h - 4);

        match FolderItem::scan(&path) {
            Ok(items) => for item_res in items {
                let entry = Entry::new(24);

                let label = Label::new();
                label.position(2, 2).size(w - 8, 20).text_offset(2, 2);
                label.bg.set(Color::rgb(255, 255, 255));
                entry.add(&label);

                match item_res {
                    Ok(item) => {
                        let mut name = item.name.clone();
                        if item.dir {
                            name.push('/');
                        }
                        label.text(name);

                        let window = window.deref() as *const Window;
                        let path_opt = path_opt.clone();
                        entry.on_click(move |_, _| {
                            println!("{}", item.name);
                            *path_opt.borrow_mut() = Some(item.path.clone());
                            unsafe { (*window).close(); }
                        });
                    },
                    Err(err) => {
                        label.text(err);
                    }
                }

                list.push(&entry);
            },
            Err(err) => {
                let entry = Entry::new(24);

                let label = Label::new();
                label.position(2, 2).size(w - 8, 20).text_offset(2, 2);
                label.bg.set(Color::rgb(242, 222, 222));
                entry.add(&label);

                label.text(format!("{}", err));

                list.push(&entry);
            }
        }

        window.add(&list);

        window.exec();

        orb_window = Some(window.into_inner());
    }
}

fn main() {
    println!("{:?}", file_dialog("."));
}
<commit_msg>Remove prints<commit_after>extern crate orbclient;
extern crate orbtk;

use orbtk::{ Color, Window, List, Entry, Label };
use orbtk::traits::{ Place, Text, Click };

use std::{fs, io};
use std::cell::RefCell;
use std::cmp::Ordering;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::rc::Rc;

#[derive(Clone, Debug, Eq, PartialEq)]
struct FolderItem {
    path: PathBuf,
    name: String,
    dir: bool,
}

impl Ord for FolderItem {
    fn cmp(&self, other: &Self) -> Ordering {
        if self.dir && ! other.dir {
            Ordering::Less
        } else if ! self.dir && other.dir {
            Ordering::Greater
        } else {
            self.name.cmp(&other.name)
        }
    }
}

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

impl FolderItem {
    pub fn scan<P: AsRef<Path>>(path: P) -> io::Result<Vec<Result<Self, String>>> {
        let canon = path.as_ref().canonicalize()?;

        let mut items = vec![];

        if let Some(parent) = canon.parent() {
            items.push(Ok(FolderItem {
                path: parent.to_owned(),
                name: "..".to_string(),
                dir: true,
            }));
        }

        for entry_res in fs::read_dir(&canon)? {
            let item = match entry_res {
                Ok(entry) => match entry.file_name().into_string() {
                    Ok(name) => match entry.file_type() {
                        Ok(file_type) => Ok(FolderItem {
                            path: entry.path(),
                            name: name,
                            dir: file_type.is_dir(),
                        }),
                        Err(err) => Err(format!("{}", err))
                    },
                    Err(os_str) => Err(format!("Invalid filename: {:?}", os_str))
                },
                Err(err) => Err(format!("{}", err))
            };

            items.push(item);
        }

        items.sort();

        Ok(items)
    }
}

fn file_dialog<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
    let path_opt = Rc::new(RefCell::new(
        Some(path.as_ref().to_owned())
    ));

    let w = 640;
    let h = 480;

    let mut orb_window = Some(orbclient::Window::new(-1, -1, w, h, "File Dialog").unwrap());

    loop {
        let path = match path_opt.borrow_mut().take() {
            Some(path) => if ! path.is_dir() {
                return Some(path);
            } else {
                path
            },
            None => return None
        };

        let mut window = Box::new(Window::from_inner(orb_window.take().unwrap()));

        let list = List::new();
        list.position(2, 2).size(w - 4, h - 4);

        match FolderItem::scan(&path) {
            Ok(items) => for item_res in items {
                let entry = Entry::new(24);

                let label = Label::new();
                label.position(2, 2).size(w - 8, 20).text_offset(2, 2);
                label.bg.set(Color::rgb(255, 255, 255));
                entry.add(&label);

                match item_res {
                    Ok(item) => {
                        let mut name = item.name.clone();
                        if item.dir {
                            name.push('/');
                        }
                        label.text(name);

                        let window = window.deref() as *const Window;
                        let path_opt = path_opt.clone();
                        entry.on_click(move |_, _| {
                            *path_opt.borrow_mut() = Some(item.path.clone());
                            unsafe { (*window).close(); }
                        });
                    },
                    Err(err) => {
                        label.text(err);
                    }
                }

                list.push(&entry);
            },
            Err(err) => {
                let entry = Entry::new(24);

                let label = Label::new();
                label.position(2, 2).size(w - 8, 20).text_offset(2, 2);
                label.bg.set(Color::rgb(242, 222, 222));
                entry.add(&label);

                label.text(format!("{}", err));

                list.push(&entry);
            }
        }

        window.add(&list);

        window.exec();

        orb_window = Some(window.into_inner());
    }
}

fn main() {
    println!("{:?}", file_dialog("."));
}
<|endoftext|>


<commit_before>#![feature(core,libc,old_io,convert)]

extern crate libusb_sys as ffi;
extern crate libc;

use libc::{c_int,c_uint,c_uchar};

use std::mem;
use std::slice;

use std::str::FromStr;
use std::old_io::{MemReader,Reader};

#[derive(Debug)]
struct Endpoint {
  config: u8,
  iface: u8,
  setting: u8,
  address: u8
}

fn main() {
  let args: Vec<String> = std::env::args().collect();

  if args.len() < 3 {
    println!("usage: show_device <vendor-id> <product-id>");
    return;
  }

  let vid: u16 = FromStr::from_str(args[1].as_ref()).unwrap();
  let pid: u16 = FromStr::from_str(args[2].as_ref()).unwrap();

  let mut context: *mut ::ffi::libusb_context = unsafe { mem::uninitialized() };
  let mut device_list: *const *mut ::ffi::libusb_device = unsafe { mem::uninitialized() };

  match unsafe { ::ffi::libusb_init(&mut context) } {
    0 => (),
    e => panic!("libusb_init: {}", e)
  };

  let handle = unsafe { ::ffi::libusb_open_device_with_vid_pid(context, vid, pid) };

  if !handle.is_null() {
    match unsafe { ::ffi::libusb_reset_device(handle) } {
      0 => {
        unsafe { ::ffi::libusb_set_auto_detach_kernel_driver(handle, 0) };

        let device = unsafe { ::ffi::libusb_get_device(handle) };
        unsafe { ::ffi::libusb_ref_device(device) };

        if unsafe { ::ffi::libusb_get_device_list(context, &mut device_list) } >= 0 {
          print_device_tree(device);
          println!("");

          unsafe { ::ffi::libusb_free_device_list(device_list, 1) };
        }

        let languages = get_language_ids(handle);
        println!("Supported languages: {:?}", languages);

        let mut active_config: c_int = unsafe { mem::uninitialized() };
        match unsafe { ::ffi::libusb_get_configuration(handle, &mut active_config) } {
          0 => println!("Active configuration: {}", active_config),
          e => println!("libusb_get_configuration: {}", e)
        }
        println!("");

        match find_readable_endpoint(device, ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT) {
          Some(ep) => read_endpoint(handle, device, ep, ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT),
          None => println!("No readable interrupt endpoint")
        }
        println!("");

        match find_readable_endpoint(device, ::ffi::LIBUSB_TRANSFER_TYPE_BULK) {
          Some(ep) => read_endpoint(handle, device, ep, ::ffi::LIBUSB_TRANSFER_TYPE_BULK),
          None => println!("No readable bulk endpoint")
        }

        unsafe { ::ffi::libusb_unref_device(device) };
      },
      e => println!("libusb_reset_device: {}", e)
    }

    unsafe { ::ffi::libusb_close(handle) };
  }

  unsafe { ::ffi::libusb_exit(context) };
}

fn print_device_tree(device: *mut ::ffi::libusb_device) -> usize {
  if device.is_null() {
    return 0;
  }

  let parent = unsafe { ::ffi::libusb_get_parent(device) };
  let depth = print_device_tree(parent);

  for _ in (0..depth) {
    print!("  ");
  }

  let bus = unsafe { ::ffi::libusb_get_bus_number(device) };
  let address = unsafe { ::ffi::libusb_get_device_address(device) };

  println!("Bus {:03} Device {:03}", bus, address);

  return depth + 1;
}

fn get_language_ids(handle: *mut ::ffi::libusb_device_handle) -> Vec<u16> {
  let mut buf = Vec::<u8>::with_capacity(255);
  let len = unsafe { ::ffi::libusb_get_string_descriptor(handle, 0, 0, (&buf[..]).as_ptr() as *mut c_uchar, buf.capacity() as c_int) };

  let mut languages = Vec::<u16>::new();

  if len >= 0 {
    unsafe { buf.set_len(len as usize) };

    if buf.len() >= 2 {
      let num_languages = (buf.len() - 2) / 2;
      languages.reserve(num_languages);

      let mut reader = MemReader::new(buf);

      match reader.read_le_u16() {
        Ok(_) => (),
        Err(_) => return languages
      }

      for _ in (0..num_languages) {
        match reader.read_le_u16() {
          Ok(n) => languages.push(n),
          Err(_) => return languages
        }
      }
    }
  }
  else {
    println!("libusb_get_string_descriptor: {}", len);
  }

  languages
}

fn find_readable_endpoint(device: *mut ::ffi::libusb_device, transfer_type: u8) -> Option<Endpoint> {
  let mut device_descriptor: ::ffi::libusb_device_descriptor = unsafe { mem::uninitialized() };

  match unsafe { ::ffi::libusb_get_device_descriptor(device, &mut device_descriptor) } {
    0 => {
      for i in (0..device_descriptor.bNumConfigurations) {
        let mut config_ptr: *const ::ffi::libusb_config_descriptor = unsafe { mem::uninitialized() };

        match unsafe { ::ffi::libusb_get_config_descriptor(device, i, &mut config_ptr) } {
          0 => {
            let config_descriptor = unsafe { config_ptr.as_ref() }.unwrap();
            let interfaces = unsafe { slice::from_raw_parts(config_descriptor.interface, config_descriptor.bNumInterfaces as usize) };

            for iface in interfaces {
              let settings = unsafe { slice::from_raw_parts(iface.altsetting, iface.num_altsetting as usize) };

              for iface_descriptor in settings {
                let endpoints = unsafe { slice::from_raw_parts(iface_descriptor.endpoint, iface_descriptor.bNumEndpoints as usize) };

                for endpoint_descriptor in endpoints {
                  let is_input = endpoint_descriptor.bEndpointAddress & ::ffi::LIBUSB_ENDPOINT_DIR_MASK == ::ffi::LIBUSB_ENDPOINT_IN;
                  let matches_type = endpoint_descriptor.bmAttributes & ::ffi::LIBUSB_TRANSFER_TYPE_MASK == transfer_type;

                  if is_input && matches_type {
                    return Some(Endpoint {
                      config: config_descriptor.bConfigurationValue,
                      iface: iface_descriptor.bInterfaceNumber,
                      setting: iface_descriptor.bAlternateSetting,
                      address: endpoint_descriptor.bEndpointAddress
                    });
                  }
                }
              }
            }
          },
          e => println!("libusb_get_config_descriptor: {}", e)
        }
      }

      None
    },
    e => {
      println!("libusb_get_device_descriptor: {}", e);
      None
    }
  }
}

fn read_endpoint(handle: *mut ::ffi::libusb_device_handle, device: *mut ::ffi::libusb_device, endpoint: Endpoint, transfer_type: u8) {
  println!("Reading from endpoint: {:?}", endpoint);

  let has_kernel_driver = unsafe {
    if ::ffi::libusb_kernel_driver_active(handle, endpoint.iface as c_int) == 1 {
      match ::ffi::libusb_detach_kernel_driver(handle, endpoint.iface as c_int) {
        0 => (),
        e => println!("libusb_detach_kernel_driver: {}", e)
      }

      true
    }
    else {
      false
    }
  };

  println!(" - kernel driver? {}", has_kernel_driver);

  match unsafe { ::ffi::libusb_set_configuration(handle, endpoint.config as c_int) } {
    0 => {
      println!(" - max packet size: {}", unsafe { ::ffi::libusb_get_max_packet_size(device, endpoint.address as c_uchar) });
      println!(" - max iso packet size: {}", unsafe { ::ffi::libusb_get_max_iso_packet_size(device, endpoint.address as c_uchar) });

      match unsafe { ::ffi::libusb_claim_interface(handle, endpoint.iface as c_int) } {
        0 => {
          match unsafe { ::ffi::libusb_set_interface_alt_setting(handle, endpoint.iface as c_int, endpoint.setting as c_int) } {
            0 => {
              let mut vec = Vec::<u8>::with_capacity(256);
              let timeout: c_uint = 1000;

              let mut transferred: c_int = unsafe { mem::uninitialized() };

              match transfer_type {
                ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT => {
                  match unsafe { ::ffi::libusb_interrupt_transfer(handle, endpoint.address as c_uchar, (&vec[..]).as_ptr() as *mut c_uchar, vec.capacity() as c_int, &mut transferred, timeout) } {
                    0 => {
                      unsafe { vec.set_len(transferred as usize) };
                      println!(" - read: {:?}", vec);
                    },
                    e => println!("libusb_interrupt_transfer: {}", e)
                  }
                },
                ::ffi::LIBUSB_TRANSFER_TYPE_BULK => {
                  match unsafe { ::ffi::libusb_bulk_transfer(handle, endpoint.address as c_uchar, (&vec[..]).as_ptr() as *mut c_uchar, vec.capacity() as c_int, &mut transferred, timeout) } {
                    0 => {
                      unsafe { vec.set_len(transferred as usize) };
                      println!(" - read: {:?}", vec);
                    },
                    e => println!("libusb_interrupt_transfer: {}", e)
                  }
                },
                tt => println!(" - can't read endpoint with transfer type {}", tt)
              }
            },
            e => println!("libusb_set_interface_alt_setting: {}", e)
          }

          match unsafe { ::ffi::libusb_release_interface(handle, endpoint.iface as c_int) } {
            0 => (),
            e => println!("libusb_release_interface: {}", e)
          }
        },
        e => println!("libusb_claim_interface: {}", e)
      }
    },
    e => println!("libusb_set_configuration: {}", e)
  }

  if has_kernel_driver {
    match unsafe { ::ffi::libusb_attach_kernel_driver(handle, endpoint.iface as c_int) } {
      0 => (),
      e => println!("libusb_attach_kernel_driver: {}", e)
    }
  }
}
<commit_msg>replaces use of MemReader with Cursor<commit_after>#![feature(core,libc)]

extern crate libusb_sys as ffi;
extern crate libc;

use libc::{c_int,c_uint,c_uchar};

use std::mem;
use std::slice;

use std::io::{Read,Cursor};
use std::str::FromStr;

#[derive(Debug)]
struct Endpoint {
  config: u8,
  iface: u8,
  setting: u8,
  address: u8
}

fn main() {
  let args: Vec<String> = std::env::args().collect();

  if args.len() < 3 {
    println!("usage: show_device <vendor-id> <product-id>");
    return;
  }

  let vid: u16 = FromStr::from_str(args[1].as_ref()).unwrap();
  let pid: u16 = FromStr::from_str(args[2].as_ref()).unwrap();

  let mut context: *mut ::ffi::libusb_context = unsafe { mem::uninitialized() };
  let mut device_list: *const *mut ::ffi::libusb_device = unsafe { mem::uninitialized() };

  match unsafe { ::ffi::libusb_init(&mut context) } {
    0 => (),
    e => panic!("libusb_init: {}", e)
  };

  let handle = unsafe { ::ffi::libusb_open_device_with_vid_pid(context, vid, pid) };

  if !handle.is_null() {
    match unsafe { ::ffi::libusb_reset_device(handle) } {
      0 => {
        unsafe { ::ffi::libusb_set_auto_detach_kernel_driver(handle, 0) };

        let device = unsafe { ::ffi::libusb_get_device(handle) };
        unsafe { ::ffi::libusb_ref_device(device) };

        if unsafe { ::ffi::libusb_get_device_list(context, &mut device_list) } >= 0 {
          print_device_tree(device);
          println!("");

          unsafe { ::ffi::libusb_free_device_list(device_list, 1) };
        }

        let languages = get_language_ids(handle);
        println!("Supported languages: {:?}", languages);

        let mut active_config: c_int = unsafe { mem::uninitialized() };
        match unsafe { ::ffi::libusb_get_configuration(handle, &mut active_config) } {
          0 => println!("Active configuration: {}", active_config),
          e => println!("libusb_get_configuration: {}", e)
        }
        println!("");

        match find_readable_endpoint(device, ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT) {
          Some(ep) => read_endpoint(handle, device, ep, ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT),
          None => println!("No readable interrupt endpoint")
        }
        println!("");

        match find_readable_endpoint(device, ::ffi::LIBUSB_TRANSFER_TYPE_BULK) {
          Some(ep) => read_endpoint(handle, device, ep, ::ffi::LIBUSB_TRANSFER_TYPE_BULK),
          None => println!("No readable bulk endpoint")
        }

        unsafe { ::ffi::libusb_unref_device(device) };
      },
      e => println!("libusb_reset_device: {}", e)
    }

    unsafe { ::ffi::libusb_close(handle) };
  }

  unsafe { ::ffi::libusb_exit(context) };
}

fn print_device_tree(device: *mut ::ffi::libusb_device) -> usize {
  if device.is_null() {
    return 0;
  }

  let parent = unsafe { ::ffi::libusb_get_parent(device) };
  let depth = print_device_tree(parent);

  for _ in (0..depth) {
    print!("  ");
  }

  let bus = unsafe { ::ffi::libusb_get_bus_number(device) };
  let address = unsafe { ::ffi::libusb_get_device_address(device) };

  println!("Bus {:03} Device {:03}", bus, address);

  return depth + 1;
}

fn get_language_ids(handle: *mut ::ffi::libusb_device_handle) -> Vec<u16> {
  let mut buf = Vec::<u8>::with_capacity(255);
  let len = unsafe { ::ffi::libusb_get_string_descriptor(handle, 0, 0, (&mut buf[..]).as_mut_ptr() as *mut c_uchar, buf.capacity() as c_int) };

  let mut languages = Vec::<u16>::new();

  if len >= 0 {
    unsafe { buf.set_len(len as usize) };

    if buf.len() >= 2 {
      let num_languages = (buf.len() - 2) / 2;
      languages.reserve(num_languages);

      let mut cursor = Cursor::new(buf);
      cursor.set_position(2);

      for _ in (0..num_languages) {
        let mut bytes = Vec::<u8>::with_capacity(2);

        match cursor.read(unsafe { slice::from_raw_parts_mut((&mut bytes[..]).as_mut_ptr(), bytes.capacity()) }) {
          Ok(len) => {
            if len == 2 {
              unsafe { bytes.set_len(len) };

              let langid = (bytes[1] as u16) << 8 | (bytes[0] as u16);
              languages.push(langid)
            }
            else {
              return languages;
            }
          },
          Err(_) => return languages
        }
      }
    }
  }
  else {
    println!("libusb_get_string_descriptor: {}", len);
  }

  languages
}

fn find_readable_endpoint(device: *mut ::ffi::libusb_device, transfer_type: u8) -> Option<Endpoint> {
  let mut device_descriptor: ::ffi::libusb_device_descriptor = unsafe { mem::uninitialized() };

  match unsafe { ::ffi::libusb_get_device_descriptor(device, &mut device_descriptor) } {
    0 => {
      for i in (0..device_descriptor.bNumConfigurations) {
        let mut config_ptr: *const ::ffi::libusb_config_descriptor = unsafe { mem::uninitialized() };

        match unsafe { ::ffi::libusb_get_config_descriptor(device, i, &mut config_ptr) } {
          0 => {
            let config_descriptor = unsafe { config_ptr.as_ref() }.unwrap();
            let interfaces = unsafe { slice::from_raw_parts(config_descriptor.interface, config_descriptor.bNumInterfaces as usize) };

            for iface in interfaces {
              let settings = unsafe { slice::from_raw_parts(iface.altsetting, iface.num_altsetting as usize) };

              for iface_descriptor in settings {
                let endpoints = unsafe { slice::from_raw_parts(iface_descriptor.endpoint, iface_descriptor.bNumEndpoints as usize) };

                for endpoint_descriptor in endpoints {
                  let is_input = endpoint_descriptor.bEndpointAddress & ::ffi::LIBUSB_ENDPOINT_DIR_MASK == ::ffi::LIBUSB_ENDPOINT_IN;
                  let matches_type = endpoint_descriptor.bmAttributes & ::ffi::LIBUSB_TRANSFER_TYPE_MASK == transfer_type;

                  if is_input && matches_type {
                    return Some(Endpoint {
                      config: config_descriptor.bConfigurationValue,
                      iface: iface_descriptor.bInterfaceNumber,
                      setting: iface_descriptor.bAlternateSetting,
                      address: endpoint_descriptor.bEndpointAddress
                    });
                  }
                }
              }
            }
          },
          e => println!("libusb_get_config_descriptor: {}", e)
        }
      }

      None
    },
    e => {
      println!("libusb_get_device_descriptor: {}", e);
      None
    }
  }
}

fn read_endpoint(handle: *mut ::ffi::libusb_device_handle, device: *mut ::ffi::libusb_device, endpoint: Endpoint, transfer_type: u8) {
  println!("Reading from endpoint: {:?}", endpoint);

  let has_kernel_driver = unsafe {
    if ::ffi::libusb_kernel_driver_active(handle, endpoint.iface as c_int) == 1 {
      match ::ffi::libusb_detach_kernel_driver(handle, endpoint.iface as c_int) {
        0 => (),
        e => println!("libusb_detach_kernel_driver: {}", e)
      }

      true
    }
    else {
      false
    }
  };

  println!(" - kernel driver? {}", has_kernel_driver);

  match unsafe { ::ffi::libusb_set_configuration(handle, endpoint.config as c_int) } {
    0 => {
      println!(" - max packet size: {}", unsafe { ::ffi::libusb_get_max_packet_size(device, endpoint.address as c_uchar) });
      println!(" - max iso packet size: {}", unsafe { ::ffi::libusb_get_max_iso_packet_size(device, endpoint.address as c_uchar) });

      match unsafe { ::ffi::libusb_claim_interface(handle, endpoint.iface as c_int) } {
        0 => {
          match unsafe { ::ffi::libusb_set_interface_alt_setting(handle, endpoint.iface as c_int, endpoint.setting as c_int) } {
            0 => {
              let mut vec = Vec::<u8>::with_capacity(256);
              let timeout: c_uint = 1000;

              let mut transferred: c_int = unsafe { mem::uninitialized() };

              match transfer_type {
                ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT => {
                  match unsafe { ::ffi::libusb_interrupt_transfer(handle, endpoint.address as c_uchar, (&vec[..]).as_ptr() as *mut c_uchar, vec.capacity() as c_int, &mut transferred, timeout) } {
                    0 => {
                      unsafe { vec.set_len(transferred as usize) };
                      println!(" - read: {:?}", vec);
                    },
                    e => println!("libusb_interrupt_transfer: {}", e)
                  }
                },
                ::ffi::LIBUSB_TRANSFER_TYPE_BULK => {
                  match unsafe { ::ffi::libusb_bulk_transfer(handle, endpoint.address as c_uchar, (&vec[..]).as_ptr() as *mut c_uchar, vec.capacity() as c_int, &mut transferred, timeout) } {
                    0 => {
                      unsafe { vec.set_len(transferred as usize) };
                      println!(" - read: {:?}", vec);
                    },
                    e => println!("libusb_interrupt_transfer: {}", e)
                  }
                },
                tt => println!(" - can't read endpoint with transfer type {}", tt)
              }
            },
            e => println!("libusb_set_interface_alt_setting: {}", e)
          }

          match unsafe { ::ffi::libusb_release_interface(handle, endpoint.iface as c_int) } {
            0 => (),
            e => println!("libusb_release_interface: {}", e)
          }
        },
        e => println!("libusb_claim_interface: {}", e)
      }
    },
    e => println!("libusb_set_configuration: {}", e)
  }

  if has_kernel_driver {
    match unsafe { ::ffi::libusb_attach_kernel_driver(handle, endpoint.iface as c_int) } {
      0 => (),
      e => println!("libusb_attach_kernel_driver: {}", e)
    }
  }
}
<|endoftext|>