<commit_before>extern crate tui;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate termion;
extern crate rand;

use std::thread;
use std::time;
use std::sync::mpsc;
use std::io::stdin;

use rand::distributions::{IndependentSample, Range};

use termion::event;
use termion::input::TermRead;

use log::LogLevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};

use tui::Terminal;
use tui::widgets::{Widget, Block, List, Gauge, Sparkline, Text, border, Chart, Axis, Dataset,
                   BarChart, Marker};
use tui::layout::{Group, Direction, Size, Rect};
use tui::style::Color;

#[derive(Clone)]
struct RandomSignal {
    range: Range<u64>,
    rng: rand::ThreadRng,
}

impl RandomSignal {
    fn new(r: Range<u64>) -> RandomSignal {
        RandomSignal {
            range: r,
            rng: rand::thread_rng(),
        }
    }
}

impl Iterator for RandomSignal {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        Some(self.range.ind_sample(&mut self.rng))
    }
}

#[derive(Clone)]
struct SinSignal {
    x: f64,
    interval: f64,
    period: f64,
    scale: f64,
}

impl SinSignal {
    fn new(interval: f64, period: f64, scale: f64) -> SinSignal {
        SinSignal {
            x: 0.0,
            interval: interval,
            period: period,
            scale: scale,
        }
    }
}

impl Iterator for SinSignal {
    type Item = (f64, f64);
    fn next(&mut self) -> Option<(f64, f64)> {
        self.x += self.interval;
        Some((self.x, ((self.x * 1.0 / self.period).sin() + 1.0) * self.scale))
    }
}

struct App<'a> {
    size: Rect,
    items: Vec<&'a str>,
    items2: Vec<&'a str>,
    selected: usize,
    show_chart: bool,
    progress: u16,
    data: Vec<u64>,
    data2: Vec<(f64, f64)>,
    data3: Vec<(f64, f64)>,
    data4: Vec<(&'a str, u64)>,
    window: [f64; 2],
    colors: [Color; 2],
    color_index: usize,
}

enum Event {
    Input(event::Key),
    Tick,
}

fn main() {

    let log = FileAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{l} / {d(%H:%M:%S)} / {M}:{L}{n}{m}{n}{n}")))
        .build("prototype.log")
        .unwrap();

    let config = Config::builder()
        .appender(Appender::builder().build("log", Box::new(log)))
        .build(Root::builder().appender("log").build(LogLevelFilter::Debug))
        .unwrap();

    log4rs::init_config(config).unwrap();
    info!("Start");

    let mut rand_signal = RandomSignal::new(Range::new(0, 100));
    let mut sin_signal = SinSignal::new(1.0, 4.0, 20.0);
    let mut sin_signal2 = SinSignal::new(0.1, 2.0, 10.0);

    let mut app = App {
        size: Rect::default(),
        items: vec!["Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8",
                    "Item9", "Item10"],
        items2: vec!["Event1", "Event2", "Event3", "Event4", "Event5", "Event6", "Event7",
                     "Event8", "Event9", "Event10", "Event11", "Event12", "Event13", "Event14",
                     "Event15", "Event16", "Event17", "Event18", "Event19"],
        selected: 0,
        show_chart: true,
        progress: 0,
        data: rand_signal.clone().take(200).collect(),
        data2: sin_signal.clone().take(20).collect(),
        data3: sin_signal2.clone().take(200).collect(),
        data4: vec![("B1", 9),
                    ("B2", 12),
                    ("B3", 5),
                    ("B4", 8),
                    ("B5", 2),
                    ("B6", 4),
                    ("B7", 5),
                    ("B8", 9),
                    ("B9", 14),
                    ("B10", 15),
                    ("B11", 1),
                    ("B12", 0),
                    ("B13", 4),
                    ("B14", 6),
                    ("B15", 4)],
        window: [0.0, 20.0],
        colors: [Color::Magenta, Color::Red],
        color_index: 0,
    };
    let (tx, rx) = mpsc::channel();
    let input_tx = tx.clone();

    for _ in 0..20 {
        sin_signal.next();
    }
    for _ in 0..200 {
        sin_signal2.next();
    }

    thread::spawn(move || {
        let stdin = stdin();
        for c in stdin.keys() {
            let evt = c.unwrap();
            input_tx.send(Event::Input(evt)).unwrap();
            if evt == event::Key::Char('q') {
                break;
            }
        }
    });

    thread::spawn(move || {
        let tx = tx.clone();
        loop {
            tx.send(Event::Tick).unwrap();
            thread::sleep(time::Duration::from_millis(1000));
        }
    });

    let mut terminal = Terminal::new().unwrap();
    terminal.clear();
    terminal.hide_cursor();

    loop {
        let size = Terminal::size().unwrap();
        if size != app.size {
            terminal.resize(size);
            app.size = size;
        }
        draw(&mut terminal, &app);
        let evt = rx.recv().unwrap();
        match evt {
            Event::Input(input) => {
                match input {
                    event::Key::Char('q') => {
                        break;
                    }
                    event::Key::Up => {
                        if app.selected > 0 {
                            app.selected -= 1
                        };
                    }
                    event::Key::Down => {
                        if app.selected < app.items.len() - 1 {
                            app.selected += 1;
                        }
                    }
                    event::Key::Char('t') => {
                        app.show_chart = !app.show_chart;
                    }
                    _ => {}
                }
            }
            Event::Tick => {
                app.progress += 5;
                if app.progress > 100 {
                    app.progress = 0;
                }
                app.data.insert(0, rand_signal.next().unwrap());
                app.data.pop();
                app.data2.remove(0);
                app.data2.push(sin_signal.next().unwrap());
                for _ in 0..10 {
                    app.data3.remove(0);
                }
                for _ in 0..10 {
                    app.data3.push(sin_signal2.next().unwrap());
                }
                let i = app.data4.pop().unwrap();
                app.data4.insert(0, i);
                app.window[0] += 1.0;
                app.window[1] += 1.0;
                let i = app.items2.pop().unwrap();
                app.items2.insert(0, i);
                app.color_index += 1;
                if app.color_index >= app.colors.len() {
                    app.color_index = 0;
                }
            }
        }
    }
    terminal.show_cursor();
}

fn draw(t: &mut Terminal, app: &App) {

    Group::default()
        .direction(Direction::Vertical)
        .sizes(&[Size::Fixed(7), Size::Min(7), Size::Fixed(7)])
        .render(t, &app.size, |t, chunks| {
            Block::default().borders(border::ALL).title("Graphs").render(&chunks[0], t);
            Group::default()
                .direction(Direction::Vertical)
                .margin(1)
                .sizes(&[Size::Fixed(2), Size::Fixed(3)])
                .render(t, &chunks[0], |t, chunks| {
                    Gauge::default()
                        .block(Block::default().title("Gauge:"))
                        .color(Color::Magenta)
                        .percent(app.progress)
                        .render(&chunks[0], t);
                    Sparkline::default()
                        .block(Block::default().title("Sparkline:"))
                        .color(Color::Green)
                        .data(&app.data)
                        .render(&chunks[1], t);
                });
            let sizes = if app.show_chart {
                vec![Size::Percent(50), Size::Percent(50)]
            } else {
                vec![Size::Percent(100)]
            };
            Group::default()
                .direction(Direction::Horizontal)
                .sizes(&sizes)
                .render(t, &chunks[1], |t, chunks| {
                    Group::default()
                        .direction(Direction::Vertical)
                        .sizes(&[Size::Percent(50), Size::Percent(50)])
                        .render(t, &chunks[0], |t, chunks| {
                            Group::default()
                                .direction(Direction::Horizontal)
                                .sizes(&[Size::Percent(50), Size::Percent(50)])
                                .render(t, &chunks[0], |t, chunks| {
                                    List::default()
                                        .block(Block::default().borders(border::ALL).title("List"))
                                        .items(&app.items)
                                        .select(app.selected)
                                        .selection_color(Color::Yellow)
                                        .selection_symbol(">")
                                        .render(&chunks[0], t);
                                    List::default()
                                        .block(Block::default().borders(border::ALL).title("List"))
                                        .items(&app.items2)
                                        .render(&chunks[1], t);
                                });
                            BarChart::default()
                                .block(Block::default().borders(border::ALL).title("Bar chart"))
                                .data(&app.data4)
                                .bar_width(3)
                                .bar_gap(2)
                                .bar_color(Color::Green)
                                .value_color(Color::Black)
                                .label_color(Color::Yellow)
                                .render(&chunks[1], t);
                        });
                    if app.show_chart {
                        Chart::default()
                            .block(Block::default().title("Chart"))
                            .x_axis(Axis::default()
                                .title("X Axis")
                                .color(Color::Gray)
                                .bounds(app.window)
                                .labels(&[&format!("{}", app.window[0]),
                                          &format!("{}", (app.window[0] + app.window[1]) / 2.0),
                                          &format!("{}", app.window[1])]))
                            .y_axis(Axis::default()
                                .title("Y Axis")
                                .color(Color::Gray)
                                .bounds([0.0, 40.0])
                                .labels(&["0", "20", "40"]))
                            .datasets(&[Dataset::default()
                                            .marker(Marker::Dot)
                                            .color(Color::Cyan)
                                            .data(&app.data2),
                                        Dataset::default()
                                            .marker(Marker::Braille)
                                            .color(Color::Yellow)
                                            .data(&app.data3)])
                            .render(&chunks[1], t);
                    }
                });
            Text::default()
                .block(Block::default().borders(border::ALL).title("Footer"))
                .wrap(true)
                .fg(app.colors[app.color_index])
                .text("This a paragraph with several lines.\nYou can change the color.\nUse \
                       \\{[color] [text]} to highlight the text with the color. For example, \
                       {red u}{green n}{yellow d}{magenta e}{cyan r} {gray t}{light_gray \
                       h}{light_red e} {light_green r}{light_yellow a}{light_magenta \
                       i}{light_cyan n}{white b}{red o}{green w}.\nOh, and if you didn't notice \
                       you can automatically wrap your text =).")
                .render(&chunks[2], t);
        });
    t.finish();
}
<commit_msg>Update prototype<commit_after>extern crate tui;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate termion;
extern crate rand;

use std::thread;
use std::time;
use std::sync::mpsc;
use std::io::stdin;

use rand::distributions::{IndependentSample, Range};

use termion::event;
use termion::input::TermRead;

use log::LogLevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};

use tui::Terminal;
use tui::widgets::{Widget, Block, List, Gauge, Sparkline, Text, border, Chart, Axis, Dataset,
                   BarChart, Marker, Tabs};
use tui::layout::{Group, Direction, Size, Rect};
use tui::style::Color;

#[derive(Clone)]
struct RandomSignal {
    range: Range<u64>,
    rng: rand::ThreadRng,
}

impl RandomSignal {
    fn new(r: Range<u64>) -> RandomSignal {
        RandomSignal {
            range: r,
            rng: rand::thread_rng(),
        }
    }
}

impl Iterator for RandomSignal {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        Some(self.range.ind_sample(&mut self.rng))
    }
}

#[derive(Clone)]
struct SinSignal {
    x: f64,
    interval: f64,
    period: f64,
    scale: f64,
}

impl SinSignal {
    fn new(interval: f64, period: f64, scale: f64) -> SinSignal {
        SinSignal {
            x: 0.0,
            interval: interval,
            period: period,
            scale: scale,
        }
    }
}

impl Iterator for SinSignal {
    type Item = (f64, f64);
    fn next(&mut self) -> Option<(f64, f64)> {
        self.x += self.interval;
        Some((self.x, ((self.x * 1.0 / self.period).sin() + 1.0) * self.scale))
    }
}

struct MyTabs {
    titles: [&'static str; 2],
    selection: usize,
}

impl MyTabs {
    fn next(&mut self) {
        self.selection = (self.selection + 1) % self.titles.len();
    }

    fn previous(&mut self) {
        if self.selection > 0 {
            self.selection -= 1;
        }
    }
}

struct App<'a> {
    size: Rect,
    items: Vec<&'a str>,
    items2: Vec<&'a str>,
    selected: usize,
    tabs: MyTabs,
    show_chart: bool,
    progress: u16,
    data: Vec<u64>,
    data2: Vec<(f64, f64)>,
    data3: Vec<(f64, f64)>,
    data4: Vec<(&'a str, u64)>,
    window: [f64; 2],
    colors: [Color; 2],
    color_index: usize,
}

enum Event {
    Input(event::Key),
    Tick,
}

fn main() {

    let log = FileAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{l} / {d(%H:%M:%S)} / {M}:{L}{n}{m}{n}{n}")))
        .build("prototype.log")
        .unwrap();

    let config = Config::builder()
        .appender(Appender::builder().build("log", Box::new(log)))
        .build(Root::builder().appender("log").build(LogLevelFilter::Debug))
        .unwrap();

    log4rs::init_config(config).unwrap();
    info!("Start");

    let mut rand_signal = RandomSignal::new(Range::new(0, 100));
    let mut sin_signal = SinSignal::new(1.0, 4.0, 20.0);
    let mut sin_signal2 = SinSignal::new(0.1, 2.0, 10.0);

    let mut app = App {
        size: Rect::default(),
        items: vec!["Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8",
                    "Item9", "Item10"],
        items2: vec!["Event1", "Event2", "Event3", "Event4", "Event5", "Event6", "Event7",
                     "Event8", "Event9", "Event10", "Event11", "Event12", "Event13", "Event14",
                     "Event15", "Event16", "Event17", "Event18", "Event19"],
        selected: 0,
        tabs: MyTabs {
            titles: ["Main", "Map"],
            selection: 0,
        },
        show_chart: true,
        progress: 0,
        data: rand_signal.clone().take(200).collect(),
        data2: sin_signal.clone().take(20).collect(),
        data3: sin_signal2.clone().take(200).collect(),
        data4: vec![("B1", 9),
                    ("B2", 12),
                    ("B3", 5),
                    ("B4", 8),
                    ("B5", 2),
                    ("B6", 4),
                    ("B7", 5),
                    ("B8", 9),
                    ("B9", 14),
                    ("B10", 15),
                    ("B11", 1),
                    ("B12", 0),
                    ("B13", 4),
                    ("B14", 6),
                    ("B15", 4)],
        window: [0.0, 20.0],
        colors: [Color::Magenta, Color::Red],
        color_index: 0,
    };
    let (tx, rx) = mpsc::channel();
    let input_tx = tx.clone();

    for _ in 0..20 {
        sin_signal.next();
    }
    for _ in 0..200 {
        sin_signal2.next();
    }

    thread::spawn(move || {
        let stdin = stdin();
        for c in stdin.keys() {
            let evt = c.unwrap();
            input_tx.send(Event::Input(evt)).unwrap();
            if evt == event::Key::Char('q') {
                break;
            }
        }
    });

    thread::spawn(move || {
        let tx = tx.clone();
        loop {
            tx.send(Event::Tick).unwrap();
            thread::sleep(time::Duration::from_millis(1000));
        }
    });

    let mut terminal = Terminal::new().unwrap();
    terminal.clear();
    terminal.hide_cursor();

    loop {
        let size = Terminal::size().unwrap();
        if size != app.size {
            terminal.resize(size);
            app.size = size;
        }
        draw(&mut terminal, &app);
        let evt = rx.recv().unwrap();
        match evt {
            Event::Input(input) => {
                match input {
                    event::Key::Char('q') => {
                        break;
                    }
                    event::Key::Up => {
                        if app.selected > 0 {
                            app.selected -= 1
                        };
                    }
                    event::Key::Down => {
                        if app.selected < app.items.len() - 1 {
                            app.selected += 1;
                        }
                    }
                    event::Key::Left => {
                        app.tabs.previous();
                    }
                    event::Key::Right => {
                        app.tabs.next();
                    }
                    event::Key::Char('t') => {
                        app.show_chart = !app.show_chart;
                    }
                    _ => {}
                }
            }
            Event::Tick => {
                app.progress += 5;
                if app.progress > 100 {
                    app.progress = 0;
                }
                app.data.insert(0, rand_signal.next().unwrap());
                app.data.pop();
                app.data2.remove(0);
                app.data2.push(sin_signal.next().unwrap());
                for _ in 0..10 {
                    app.data3.remove(0);
                }
                for _ in 0..10 {
                    app.data3.push(sin_signal2.next().unwrap());
                }
                let i = app.data4.pop().unwrap();
                app.data4.insert(0, i);
                app.window[0] += 1.0;
                app.window[1] += 1.0;
                let i = app.items2.pop().unwrap();
                app.items2.insert(0, i);
                app.color_index += 1;
                if app.color_index >= app.colors.len() {
                    app.color_index = 0;
                }
            }
        }
    }
    terminal.show_cursor();
}

fn draw(t: &mut Terminal, app: &App) {

    Group::default()
        .direction(Direction::Vertical)
        .sizes(&[Size::Fixed(3), Size::Min(0)])
        .render(t, &app.size, |t, chunks| {
            Tabs::default()
                .block(Block::default().borders(border::ALL).title("Tabs"))
                .titles(&app.tabs.titles)
                .highlight_color(Color::Yellow)
                .select(app.tabs.selection)
                .render(&chunks[0], t);
            match app.tabs.selection {
                0 => {
                    draw_main(t, app, &chunks[1]);
                }
                1 => {}
                _ => {}
            };
        });
    t.finish();
}

fn draw_main(t: &mut Terminal, app: &App, area: &Rect) {
    Group::default()
        .direction(Direction::Vertical)
        .sizes(&[Size::Fixed(7), Size::Min(7), Size::Fixed(7)])
        .render(t, area, |t, chunks| {
            Block::default()
                .borders(border::ALL)
                .title("Graphs")
                .render(&chunks[0], t);
            Group::default()
                .direction(Direction::Vertical)
                .margin(1)
                .sizes(&[Size::Fixed(2), Size::Fixed(3)])
                .render(t, &chunks[0], |t, chunks| {
                    Gauge::default()
                        .block(Block::default().title("Gauge:"))
                        .color(Color::Magenta)
                        .percent(app.progress)
                        .render(&chunks[0], t);
                    Sparkline::default()
                        .block(Block::default().title("Sparkline:"))
                        .color(Color::Green)
                        .data(&app.data)
                        .render(&chunks[1], t);
                });
            let sizes = if app.show_chart {
                vec![Size::Percent(50), Size::Percent(50)]
            } else {
                vec![Size::Percent(100)]
            };
            Group::default()
                .direction(Direction::Horizontal)
                .sizes(&sizes)
                .render(t, &chunks[1], |t, chunks| {
                    Group::default()
                        .direction(Direction::Vertical)
                        .sizes(&[Size::Percent(50), Size::Percent(50)])
                        .render(t, &chunks[0], |t, chunks| {
                            Group::default()
                                .direction(Direction::Horizontal)
                                .sizes(&[Size::Percent(50), Size::Percent(50)])
                                .render(t, &chunks[0], |t, chunks| {
                                    List::default()
                                        .block(Block::default()
                                            .borders(border::ALL)
                                            .title("List"))
                                        .items(&app.items)
                                        .select(app.selected)
                                        .selection_color(Color::Yellow)
                                        .selection_symbol(">")
                                        .render(&chunks[0], t);
                                    List::default()
                                        .block(Block::default()
                                            .borders(border::ALL)
                                            .title("List"))
                                        .items(&app.items2)
                                        .render(&chunks[1], t);
                                });
                            BarChart::default()
                                .block(Block::default()
                                    .borders(border::ALL)
                                    .title("Bar chart"))
                                .data(&app.data4)
                                .bar_width(3)
                                .bar_gap(2)
                                .bar_color(Color::Green)
                                .value_color(Color::Black)
                                .label_color(Color::Yellow)
                                .render(&chunks[1], t);
                        });
                    if app.show_chart {
                        Chart::default()
                            .block(Block::default().title("Chart"))
                            .x_axis(Axis::default()
                                .title("X Axis")
                                .color(Color::Gray)
                                .bounds(app.window)
                                .labels(&[&format!("{}", app.window[0]),
                                          &format!("{}", (app.window[0] + app.window[1]) / 2.0),
                                          &format!("{}", app.window[1])]))
                            .y_axis(Axis::default()
                                .title("Y Axis")
                                .color(Color::Gray)
                                .bounds([0.0, 40.0])
                                .labels(&["0", "20", "40"]))
                            .datasets(&[Dataset::default()
                                            .marker(Marker::Dot)
                                            .color(Color::Cyan)
                                            .data(&app.data2),
                                        Dataset::default()
                                            .marker(Marker::Braille)
                                            .color(Color::Yellow)
                                            .data(&app.data3)])
                            .render(&chunks[1], t);
                    }
                });
            Text::default()
                .block(Block::default().borders(border::ALL).title("Footer"))
                .wrap(true)
                .fg(app.colors[app.color_index])
                .text("This a paragraph with several lines.\nYou can change the \
                               color.\nUse \\{[color] [text]} to highlight the text with the \
                               color. For example, {red u}{green n}{yellow d}{magenta e}{cyan r} \
                               {gray t}{light_gray h}{light_red e} {light_green r}{light_yellow \
                               a}{light_magenta i}{light_cyan n}{white b}{red o}{green w}.\nOh, \
                               and if you didn't notice you can automatically wrap your text =).")
                .render(&chunks[2], t);
        });
}
<|endoftext|>


<commit_before>extern crate tui;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate termion;
extern crate rand;

use std::thread;
use std::time;
use std::sync::mpsc;
use std::io::stdin;

use rand::distributions::{IndependentSample, Range};

use termion::event;
use termion::input::TermRead;

use log::LogLevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};

use tui::Terminal;
use tui::widgets::{Widget, Block, List, Gauge, Sparkline, Text, border, Chart, Axis, Dataset,
                   BarChart};
use tui::layout::{Group, Direction, Alignment, Size};
use tui::style::Color;

#[derive(Clone)]
struct RandomSignal {
    range: Range<u64>,
    rng: rand::ThreadRng,
}

impl RandomSignal {
    fn new(r: Range<u64>) -> RandomSignal {
        RandomSignal {
            range: r,
            rng: rand::thread_rng(),
        }
    }
}

impl Iterator for RandomSignal {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        Some(self.range.ind_sample(&mut self.rng))
    }
}

#[derive(Clone)]
struct SinSignal {
    x: f64,
    period: f64,
    scale: f64,
}

impl SinSignal {
    fn new(period: f64, scale: f64) -> SinSignal {
        SinSignal {
            x: 0.0,
            period: period,
            scale: scale,
        }
    }
}

impl Iterator for SinSignal {
    type Item = (f64, f64);
    fn next(&mut self) -> Option<(f64, f64)> {
        self.x += 1.0;
        Some((self.x, ((self.x * 1.0 / self.period).sin() + 1.0) * self.scale))
    }
}

struct App<'a> {
    name: String,
    items: Vec<&'a str>,
    items2: Vec<&'a str>,
    selected: usize,
    show_chart: bool,
    progress: u16,
    data: Vec<u64>,
    data2: Vec<(f64, f64)>,
    data3: Vec<(f64, f64)>,
    data4: Vec<(&'a str, u64)>,
    window: [f64; 2],
    colors: [Color; 2],
    color_index: usize,
}

enum Event {
    Input(event::Key),
    Tick,
}

fn main() {

    let log = FileAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{l} / {d(%H:%M:%S)} / {M}:{L}{n}{m}{n}{n}")))
        .build("prototype.log")
        .unwrap();

    let config = Config::builder()
        .appender(Appender::builder().build("log", Box::new(log)))
        .build(Root::builder().appender("log").build(LogLevelFilter::Debug))
        .unwrap();

    log4rs::init_config(config).unwrap();
    info!("Start");

    let mut rand_signal = RandomSignal::new(Range::new(0, 100));
    let mut sin_signal = SinSignal::new(4.0, 20.0);
    let mut sin_signal2 = SinSignal::new(2.0, 10.0);

    let mut app = App {
        name: String::from("Test app"),
        items: vec!["Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8",
                    "Item9", "Item10"],
        items2: vec!["Event1", "Event2", "Event3", "Event4", "Event5", "Event6", "Event7",
                     "Event8", "Event9", "Event10", "Event11", "Event12", "Event13", "Event14",
                     "Event15", "Event16", "Event17"],
        selected: 0,
        show_chart: true,
        progress: 0,
        data: rand_signal.clone().take(200).collect(),
        data2: sin_signal.clone().take(20).collect(),
        data3: sin_signal2.clone().take(20).collect(),
        data4: vec![("B1", 9),
                    ("B2", 12),
                    ("B3", 5),
                    ("B4", 8),
                    ("B5", 2),
                    ("B6", 4),
                    ("B7", 5),
                    ("B8", 9),
                    ("B9", 14),
                    ("B10", 15),
                    ("B11", 1),
                    ("B12", 0)],
        window: [0.0, 20.0],
        colors: [Color::Magenta, Color::Red],
        color_index: 0,
    };
    let (tx, rx) = mpsc::channel();
    let input_tx = tx.clone();

    for i in 0..20 {
        sin_signal.next();
        sin_signal2.next();
    }

    thread::spawn(move || {
        let stdin = stdin();
        for c in stdin.keys() {
            let evt = c.unwrap();
            input_tx.send(Event::Input(evt)).unwrap();
            if evt == event::Key::Char('q') {
                break;
            }
        }
    });

    thread::spawn(move || {
        let tx = tx.clone();
        loop {
            tx.send(Event::Tick).unwrap();
            thread::sleep(time::Duration::from_millis(500));
        }
    });

    let mut terminal = Terminal::new().unwrap();
    terminal.clear();
    terminal.hide_cursor();

    loop {
        terminal.clear();
        draw(&mut terminal, &app);
        let evt = rx.recv().unwrap();
        match evt {
            Event::Input(input) => {
                match input {
                    event::Key::Char('q') => {
                        break;
                    }
                    event::Key::Up => {
                        if app.selected > 0 {
                            app.selected -= 1
                        };
                    }
                    event::Key::Down => {
                        if app.selected < app.items.len() - 1 {
                            app.selected += 1;
                        }
                    }
                    event::Key::Char('t') => {
                        app.show_chart = !app.show_chart;
                    }
                    _ => {}
                }
            }
            Event::Tick => {
                app.progress += 5;
                if app.progress > 100 {
                    app.progress = 0;
                }
                app.data.insert(0, rand_signal.next().unwrap());
                app.data.pop();
                app.data2.remove(0);
                app.data2.push(sin_signal.next().unwrap());
                app.data3.remove(0);
                app.data3.push(sin_signal2.next().unwrap());
                let i = app.data4.pop().unwrap();
                app.data4.insert(0, i);
                app.window[0] += 1.0;
                app.window[1] += 1.0;
                app.selected += 1;
                if app.selected >= app.items.len() {
                    app.selected = 0;
                }
                let i = app.items2.pop().unwrap();
                app.items2.insert(0, i);
                app.color_index += 1;
                if app.color_index >= app.colors.len() {
                    app.color_index = 0;
                }
            }
        }
    }
    terminal.show_cursor();
}

fn draw(t: &mut Terminal, app: &App) {

    let size = Terminal::size().unwrap();

    Group::default()
        .direction(Direction::Vertical)
        .alignment(Alignment::Left)
        .chunks(&[Size::Fixed(7), Size::Min(5), Size::Fixed(5)])
        .render(t, &size, |t, chunks| {
            Block::default().borders(border::ALL).title("Graphs").render(&chunks[0], t);
            Group::default()
                .direction(Direction::Vertical)
                .alignment(Alignment::Left)
                .margin(1)
                .chunks(&[Size::Fixed(2), Size::Fixed(3)])
                .render(t, &chunks[0], |t, chunks| {
                    Gauge::default()
                        .block(Block::default().title("Gauge:"))
                        .bg(Color::Magenta)
                        .percent(app.progress)
                        .render(&chunks[0], t);
                    Sparkline::default()
                        .block(Block::default().title("Sparkline:"))
                        .fg(Color::Green)
                        .data(&app.data)
                        .render(&chunks[1], t);
                });
            let sizes = if app.show_chart {
                vec![Size::Max(40), Size::Min(20)]
            } else {
                vec![Size::Max(40)]
            };
            Group::default()
                .direction(Direction::Horizontal)
                .alignment(Alignment::Left)
                .chunks(&sizes)
                .render(t, &chunks[1], |t, chunks| {
                    Group::default()
                        .direction(Direction::Vertical)
                        .chunks(&[Size::Min(20), Size::Max(40)])
                        .render(t, &chunks[0], |t, chunks| {
                            Group::default()
                                .direction(Direction::Horizontal)
                                .chunks(&[Size::Max(20), Size::Min(0)])
                                .render(t, &chunks[0], |t, chunks| {
                                    List::default()
                                        .block(Block::default().borders(border::ALL).title("List"))
                                        .items(&app.items)
                                        .select(app.selected)
                                        .selection_color(Color::LightYellow)
                                        .selection_symbol(">")
                                        .render(&chunks[0], t);
                                    List::default()
                                        .block(Block::default().borders(border::ALL).title("List"))
                                        .items(&app.items2)
                                        .render(&chunks[1], t);
                                });
                            BarChart::default()
                                .block(Block::default().borders(border::ALL).title("Bar chart"))
                                .data(&app.data4)
                                .bar_width(3)
                                .bar_gap(2)
                                .bar_color(Color::LightGreen)
                                .value_color(Color::Black)
                                .label_color(Color::LightYellow)
                                .render(&chunks[1], t);
                        });
                    if app.show_chart {
                        Chart::default()
                            .block(Block::default().title("Chart"))
                            .x_axis(Axis::default()
                                .title("X Axis")
                                .color(Color::Gray)
                                .bounds(app.window)
                                .labels(&[&format!("{}", app.window[0]),
                                          &format!("{}", (app.window[0] + app.window[1]) / 2.0),
                                          &format!("{}", app.window[1])]))
                            .y_axis(Axis::default()
                                .title("Y Axis")
                                .color(Color::Gray)
                                .bounds([0.0, 40.0])
                                .labels(&["0", "20", "40"]))
                            .datasets(&[Dataset::default().color(Color::Cyan).data(&app.data2),
                                        Dataset::default().color(Color::Yellow).data(&app.data3)])
                            .render(&chunks[1], t);
                    }
                });
            Text::default()
                .block(Block::default().borders(border::ALL).title("Footer"))
                .fg(app.colors[app.color_index])
                .text("日本国 UTF-8 charaters")
                .render(&chunks[2], t);
        });
}
<commit_msg>Update prototype<commit_after>extern crate tui;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate termion;
extern crate rand;

use std::thread;
use std::time;
use std::sync::mpsc;
use std::io::stdin;

use rand::distributions::{IndependentSample, Range};

use termion::event;
use termion::input::TermRead;

use log::LogLevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};

use tui::Terminal;
use tui::widgets::{Widget, Block, List, Gauge, Sparkline, Text, border, Chart, Axis, Dataset,
                   BarChart};
use tui::layout::{Group, Direction, Alignment, Size};
use tui::style::Color;

#[derive(Clone)]
struct RandomSignal {
    range: Range<u64>,
    rng: rand::ThreadRng,
}

impl RandomSignal {
    fn new(r: Range<u64>) -> RandomSignal {
        RandomSignal {
            range: r,
            rng: rand::thread_rng(),
        }
    }
}

impl Iterator for RandomSignal {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        Some(self.range.ind_sample(&mut self.rng))
    }
}

#[derive(Clone)]
struct SinSignal {
    x: f64,
    period: f64,
    scale: f64,
}

impl SinSignal {
    fn new(period: f64, scale: f64) -> SinSignal {
        SinSignal {
            x: 0.0,
            period: period,
            scale: scale,
        }
    }
}

impl Iterator for SinSignal {
    type Item = (f64, f64);
    fn next(&mut self) -> Option<(f64, f64)> {
        self.x += 1.0;
        Some((self.x, ((self.x * 1.0 / self.period).sin() + 1.0) * self.scale))
    }
}

struct App<'a> {
    items: Vec<&'a str>,
    items2: Vec<&'a str>,
    selected: usize,
    show_chart: bool,
    progress: u16,
    data: Vec<u64>,
    data2: Vec<(f64, f64)>,
    data3: Vec<(f64, f64)>,
    data4: Vec<(&'a str, u64)>,
    window: [f64; 2],
    colors: [Color; 2],
    color_index: usize,
}

enum Event {
    Input(event::Key),
    Tick,
}

fn main() {

    let log = FileAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{l} / {d(%H:%M:%S)} / {M}:{L}{n}{m}{n}{n}")))
        .build("prototype.log")
        .unwrap();

    let config = Config::builder()
        .appender(Appender::builder().build("log", Box::new(log)))
        .build(Root::builder().appender("log").build(LogLevelFilter::Debug))
        .unwrap();

    log4rs::init_config(config).unwrap();
    info!("Start");

    let mut rand_signal = RandomSignal::new(Range::new(0, 100));
    let mut sin_signal = SinSignal::new(4.0, 20.0);
    let mut sin_signal2 = SinSignal::new(2.0, 10.0);

    let mut app = App {
        items: vec!["Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8",
                    "Item9", "Item10"],
        items2: vec!["Event1", "Event2", "Event3", "Event4", "Event5", "Event6", "Event7",
                     "Event8", "Event9", "Event10", "Event11", "Event12", "Event13", "Event14",
                     "Event15", "Event16", "Event17"],
        selected: 0,
        show_chart: true,
        progress: 0,
        data: rand_signal.clone().take(200).collect(),
        data2: sin_signal.clone().take(20).collect(),
        data3: sin_signal2.clone().take(20).collect(),
        data4: vec![("B1", 9),
                    ("B2", 12),
                    ("B3", 5),
                    ("B4", 8),
                    ("B5", 2),
                    ("B6", 4),
                    ("B7", 5),
                    ("B8", 9),
                    ("B9", 14),
                    ("B10", 15),
                    ("B11", 1),
                    ("B12", 0)],
        window: [0.0, 20.0],
        colors: [Color::Magenta, Color::Red],
        color_index: 0,
    };
    let (tx, rx) = mpsc::channel();
    let input_tx = tx.clone();

    for _ in 0..20 {
        sin_signal.next();
        sin_signal2.next();
    }

    thread::spawn(move || {
        let stdin = stdin();
        for c in stdin.keys() {
            let evt = c.unwrap();
            input_tx.send(Event::Input(evt)).unwrap();
            if evt == event::Key::Char('q') {
                break;
            }
        }
    });

    thread::spawn(move || {
        let tx = tx.clone();
        loop {
            tx.send(Event::Tick).unwrap();
            thread::sleep(time::Duration::from_millis(1000));
        }
    });

    let mut terminal = Terminal::new().unwrap();
    terminal.clear();
    terminal.hide_cursor();

    loop {
        terminal.clear();
        draw(&mut terminal, &app);
        let evt = rx.recv().unwrap();
        match evt {
            Event::Input(input) => {
                match input {
                    event::Key::Char('q') => {
                        break;
                    }
                    event::Key::Up => {
                        if app.selected > 0 {
                            app.selected -= 1
                        };
                    }
                    event::Key::Down => {
                        if app.selected < app.items.len() - 1 {
                            app.selected += 1;
                        }
                    }
                    event::Key::Char('t') => {
                        app.show_chart = !app.show_chart;
                    }
                    _ => {}
                }
            }
            Event::Tick => {
                app.progress += 5;
                if app.progress > 100 {
                    app.progress = 0;
                }
                app.data.insert(0, rand_signal.next().unwrap());
                app.data.pop();
                app.data2.remove(0);
                app.data2.push(sin_signal.next().unwrap());
                app.data3.remove(0);
                app.data3.push(sin_signal2.next().unwrap());
                let i = app.data4.pop().unwrap();
                app.data4.insert(0, i);
                app.window[0] += 1.0;
                app.window[1] += 1.0;
                app.selected += 1;
                if app.selected >= app.items.len() {
                    app.selected = 0;
                }
                let i = app.items2.pop().unwrap();
                app.items2.insert(0, i);
                app.color_index += 1;
                if app.color_index >= app.colors.len() {
                    app.color_index = 0;
                }
            }
        }
    }
    terminal.show_cursor();
}

fn draw(t: &mut Terminal, app: &App) {

    let size = Terminal::size().unwrap();

    Group::default()
        .direction(Direction::Vertical)
        .alignment(Alignment::Left)
        .chunks(&[Size::Fixed(7), Size::Min(5), Size::Fixed(7)])
        .render(t, &size, |t, chunks| {
            Block::default().borders(border::ALL).title("Graphs").render(&chunks[0], t);
            Group::default()
                .direction(Direction::Vertical)
                .alignment(Alignment::Left)
                .margin(1)
                .chunks(&[Size::Fixed(2), Size::Fixed(3)])
                .render(t, &chunks[0], |t, chunks| {
                    Gauge::default()
                        .block(Block::default().title("Gauge:"))
                        .bg(Color::Magenta)
                        .percent(app.progress)
                        .render(&chunks[0], t);
                    Sparkline::default()
                        .block(Block::default().title("Sparkline:"))
                        .fg(Color::Green)
                        .data(&app.data)
                        .render(&chunks[1], t);
                });
            let sizes = if app.show_chart {
                vec![Size::Max(40), Size::Min(20)]
            } else {
                vec![Size::Max(40)]
            };
            Group::default()
                .direction(Direction::Horizontal)
                .alignment(Alignment::Left)
                .chunks(&sizes)
                .render(t, &chunks[1], |t, chunks| {
                    Group::default()
                        .direction(Direction::Vertical)
                        .chunks(&[Size::Min(20), Size::Max(40)])
                        .render(t, &chunks[0], |t, chunks| {
                            Group::default()
                                .direction(Direction::Horizontal)
                                .chunks(&[Size::Max(20), Size::Min(0)])
                                .render(t, &chunks[0], |t, chunks| {
                                    List::default()
                                        .block(Block::default().borders(border::ALL).title("List"))
                                        .items(&app.items)
                                        .select(app.selected)
                                        .selection_color(Color::LightYellow)
                                        .selection_symbol(">")
                                        .render(&chunks[0], t);
                                    List::default()
                                        .block(Block::default().borders(border::ALL).title("List"))
                                        .items(&app.items2)
                                        .render(&chunks[1], t);
                                });
                            BarChart::default()
                                .block(Block::default().borders(border::ALL).title("Bar chart"))
                                .data(&app.data4)
                                .bar_width(3)
                                .bar_gap(2)
                                .bar_color(Color::LightGreen)
                                .value_color(Color::Black)
                                .label_color(Color::LightYellow)
                                .render(&chunks[1], t);
                        });
                    if app.show_chart {
                        Chart::default()
                            .block(Block::default().title("Chart"))
                            .x_axis(Axis::default()
                                .title("X Axis")
                                .color(Color::Gray)
                                .bounds(app.window)
                                .labels(&[&format!("{}", app.window[0]),
                                          &format!("{}", (app.window[0] + app.window[1]) / 2.0),
                                          &format!("{}", app.window[1])]))
                            .y_axis(Axis::default()
                                .title("Y Axis")
                                .color(Color::Gray)
                                .bounds([0.0, 40.0])
                                .labels(&["0", "20", "40"]))
                            .datasets(&[Dataset::default().color(Color::Cyan).data(&app.data2),
                                        Dataset::default().color(Color::Yellow).data(&app.data3)])
                            .render(&chunks[1], t);
                    }
                });
            Text::default()
                .block(Block::default().borders(border::ALL).title("Footer"))
                .wrap(true)
                .fg(app.colors[app.color_index])
                .text("This a paragraph with several lines.\nYou can change the color.\nUse \
                       \\{[color] [text]} to highlight the text with the color. For example, \
                       {red u}{green n}{yellow d}{magenta e}{cyan r} {gray t}{light_gray \
                       h}{light_red e} {light_green r}{light_yellow a}{light_magenta \
                       i}{light_cyan n}{white b}{red o}{green w}.\nOh, and if you didn't notice \
                       you can automatically wrap your text =).")
                .render(&chunks[2], t);
        });
}
<|endoftext|>


<commit_before>extern crate cocoa;

use cocoa::base::{NSUInteger, selector, nil, YES, NO};
use cocoa::appkit::{NSApp, NSRect, NSPoint, NSSize,
					NSAutoreleasePool, NSProcessInfo,
					NSApplication, NSApplicationActivationPolicyRegular,
					NSWindow, NSTitledWindowMask, NSBackingStoreBuffered,
					NSString,
					NSMenu, NSMenuItem};

fn main() {
	unsafe {
		let _pool = NSAutoreleasePool::new(nil);

		let app = NSApp();
		app.setActivationPolicy_(NSApplicationActivationPolicyRegular);

		// create Menu Bar
		let menubar = NSMenu::new(nil).autorelease();
		let app_menu_item = NSMenuItem::new(nil).autorelease();
		menubar.addItem_(app_menu_item);
		app.setMainMenu_(menubar);

		// create Application menu
		let app_menu = NSMenu::new(nil).autorelease();
		let quit_prefix = NSString::alloc(nil).init_str("Quit \0");
		let quit_title = quit_prefix.stringByAppendingString_(
			NSProcessInfo::processInfo(nil).processName()
		);
		let quit_action = selector("terminate:");
		let quit_key = NSString::alloc(nil).init_str("q\0");
		let quit_item = NSMenuItem::alloc(nil).initWithTitle_action_keyEquivalent_(
			quit_title,
			quit_action,
			quit_key
		).autorelease();
		app_menu.addItem_(quit_item);
		app_menu_item.setSubmenu_(app_menu);

		// create Window
		let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
			NSRect::new(NSPoint::new(0., 0.), NSSize::new(200., 200.)),
			NSTitledWindowMask as NSUInteger,
			NSBackingStoreBuffered,
			NO
		).autorelease();
		window.cascadeTopLeftFromPoint_(NSPoint::new(20., 20.));
		window.center();
		let title = NSString::alloc(nil).init_str("Hello World!\0");
		window.setTitle_(title);
		window.makeKeyAndOrderFront_(nil);

		app.activateIgnoringOtherApps_(YES);
		app.run();
	}
}
<commit_msg>Fixed runtime error in example by removing unnecessary null terminator<commit_after>extern crate cocoa;

use cocoa::base::{NSUInteger, selector, nil, YES, NO};
use cocoa::appkit::{NSApp, NSRect, NSPoint, NSSize,
					NSAutoreleasePool, NSProcessInfo,
					NSApplication, NSApplicationActivationPolicyRegular,
					NSWindow, NSTitledWindowMask, NSBackingStoreBuffered,
					NSString,
					NSMenu, NSMenuItem};

fn main() {
	unsafe {
		let _pool = NSAutoreleasePool::new(nil);

		let app = NSApp();
		app.setActivationPolicy_(NSApplicationActivationPolicyRegular);

		// create Menu Bar
		let menubar = NSMenu::new(nil).autorelease();
		let app_menu_item = NSMenuItem::new(nil).autorelease();
		menubar.addItem_(app_menu_item);
		app.setMainMenu_(menubar);

		// create Application menu
		let app_menu = NSMenu::new(nil).autorelease();
		let quit_prefix = NSString::alloc(nil).init_str("Quit");
		let quit_title = quit_prefix.stringByAppendingString_(
			NSProcessInfo::processInfo(nil).processName()
		);
		let quit_action = selector("terminate:");
		let quit_key = NSString::alloc(nil).init_str("q");
		let quit_item = NSMenuItem::alloc(nil).initWithTitle_action_keyEquivalent_(
			quit_title,
			quit_action,
			quit_key
		).autorelease();
		app_menu.addItem_(quit_item);
		app_menu_item.setSubmenu_(app_menu);

		// create Window
		let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
			NSRect::new(NSPoint::new(0., 0.), NSSize::new(200., 200.)),
			NSTitledWindowMask as NSUInteger,
			NSBackingStoreBuffered,
			NO
		).autorelease();
		window.cascadeTopLeftFromPoint_(NSPoint::new(20., 20.));
		window.center();
		let title = NSString::alloc(nil).init_str("Hello World!");
		window.setTitle_(title);
		window.makeKeyAndOrderFront_(nil);

		app.activateIgnoringOtherApps_(YES);
		app.run();
	}
}
<|endoftext|>


<commit_before>// extern crate bindgen;
#[cfg(target_env = "msvc")]
extern crate cc;
extern crate pkg_config;
extern crate num_cpus;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

// Automatically write bindings to libsass
//#[allow(dead_code)]
//fn write_bindings() {
//    let bindings = bindgen::Builder::default()
//        .header("libsass/include/sass.h")
//        .clang_arg("-Ilibsass/include")
//        // To avoid a test failing
//        .blacklist_type("max_align_t")
//        // we do static linking so it should be fine
//        // https://github.com/rust-lang/rust/issues/36927
//        .rustified_enum(".*")
//        .generate()
//        .expect("Unable to generate bindings");
//
//    // Write the bindings to the $OUT_DIR/bindings.rs file.
//    let out_path = PathBuf::from("src");
//    bindings
//        .write_to_file(out_path.join("bindings.rs"))
//        .expect("Couldn't write bindings!");
//}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => panic!("\n{} failed with {}\n", stringify!($e), e),
    })
}

fn cp_r(dir: &Path, dest: &Path) {
    for entry in t!(fs::read_dir(dir)) {
        let entry = t!(entry);
        let path = entry.path();
        let dst = dest.join(path.file_name().unwrap());
        if t!(fs::metadata(&path)).is_file() {
            t!(fs::copy(path, dst));
        } else {
            t!(fs::create_dir_all(&dst));
            cp_r(&path, &dst);
        }
    }
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().unwrap().join("libsass")
}

// linux/unix
#[cfg(not(target_env = "msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);
    let is_bsd = target.contains("dragonfly")
        || target.contains("freebsd")
        || target.contains("netbsd")
        || target.contains("openbsd");
    let libprobe = | lib: &str | -> bool {
      Command::new("gcc")
        .arg("-xc++")
        .arg("-o/dev/null")
        .arg(format!("-l{}",lib))
        .arg("-shared")
        .stderr(Stdio::null())
        .status()
        .expect("")
        .success()
    };

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or(num_cpus::get().to_string());
    let r = Command::new(if is_bsd { "gmake" } else { "make" })
        .current_dir(&build)
        .args(&["--jobs", &jobs])
        .output()
        .expect("error running make");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=sass");

    if libprobe("c++_shared") {
        println!("cargo:rustc-link-lib=dylib=c++_shared");
    }
    else if libprobe("c++") {
        println!("cargo:rustc-link-lib=dylib=c++");
    }
    else if libprobe("stdc++") {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
    else {
        panic!("no c++ library found");
    }

}

// windows
#[cfg(target_env = "msvc")]
fn compile() {
    let src = get_libsass_folder();
    let target = env::var("TARGET").expect("TARGET not found in environment");
    let msvc_platform = if target.contains("x86_64") {
        "Win64"
    } else {
        "Win32"
    };
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);

    // Find an instance of devenv.exe from Visual Studio IDE in order to upgrade
    // libsass.sln to the current available IDE. Do nothing if no devenv.exe found
    let d = cc::windows_registry::find(target.as_str(), "devenv.exe");
    if let Some(mut d) = d {
        let d = d
            .args(&["/upgrade", "win\\libsass.sln"])
            .current_dir(&build)
            .output()
            .expect("error running devenv");
        if !d.status.success() {
            let err = String::from_utf8_lossy(&d.stderr);
            let out = String::from_utf8_lossy(&d.stdout);
            println!("Upgrade error:\nSTDERR:{}\nSTDOUT:{}", err, out);
        }
    }

    let r = cc::windows_registry::find(target.as_str(), "msbuild.exe")
        .expect("could not find msbuild")
        .args(&[
            "win\\libsass.sln",
            "/p:LIBSASS_STATIC_LIB=1",
            "/p:Configuration=Release",
            "/p:WholeProgramOptimization=false",
            format!("/p:Platform={}", msvc_platform).as_str(),
        ])
        .current_dir(&build)
        .output()
        .expect("error running msbuild");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("win").join("bin").display()
    );
    println!("cargo:rustc-link-lib=static=libsass");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if let Ok(_) = pkg_config::find_library("libsass") {
        return;
    }

    compile();
}
<commit_msg>changed from gcc to cc to be compatible to bsd<commit_after>// extern crate bindgen;
#[cfg(target_env = "msvc")]
extern crate cc;
extern crate pkg_config;
extern crate num_cpus;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

// Automatically write bindings to libsass
//#[allow(dead_code)]
//fn write_bindings() {
//    let bindings = bindgen::Builder::default()
//        .header("libsass/include/sass.h")
//        .clang_arg("-Ilibsass/include")
//        // To avoid a test failing
//        .blacklist_type("max_align_t")
//        // we do static linking so it should be fine
//        // https://github.com/rust-lang/rust/issues/36927
//        .rustified_enum(".*")
//        .generate()
//        .expect("Unable to generate bindings");
//
//    // Write the bindings to the $OUT_DIR/bindings.rs file.
//    let out_path = PathBuf::from("src");
//    bindings
//        .write_to_file(out_path.join("bindings.rs"))
//        .expect("Couldn't write bindings!");
//}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => panic!("\n{} failed with {}\n", stringify!($e), e),
    })
}

fn cp_r(dir: &Path, dest: &Path) {
    for entry in t!(fs::read_dir(dir)) {
        let entry = t!(entry);
        let path = entry.path();
        let dst = dest.join(path.file_name().unwrap());
        if t!(fs::metadata(&path)).is_file() {
            t!(fs::copy(path, dst));
        } else {
            t!(fs::create_dir_all(&dst));
            cp_r(&path, &dst);
        }
    }
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().unwrap().join("libsass")
}

// linux/unix
#[cfg(not(target_env = "msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);
    let is_bsd = target.contains("dragonfly")
        || target.contains("freebsd")
        || target.contains("netbsd")
        || target.contains("openbsd");
    let libprobe = | lib: &str | -> bool {
      Command::new("cc")
        .arg("-xc++")
        .arg("-o/dev/null")
        .arg(format!("-l{}",lib))
        .arg("-shared")
        .stderr(Stdio::null())
        .status()
        .expect("")
        .success()
    };

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or(num_cpus::get().to_string());
    let r = Command::new(if is_bsd { "gmake" } else { "make" })
        .current_dir(&build)
        .args(&["--jobs", &jobs])
        .output()
        .expect("error running make");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=sass");

    if libprobe("c++_shared") {
        println!("cargo:rustc-link-lib=dylib=c++_shared");
    }
    else if libprobe("c++") {
        println!("cargo:rustc-link-lib=dylib=c++");
    }
    else if libprobe("stdc++") {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
    else {
        panic!("no c++ library found");
    }

}

// windows
#[cfg(target_env = "msvc")]
fn compile() {
    let src = get_libsass_folder();
    let target = env::var("TARGET").expect("TARGET not found in environment");
    let msvc_platform = if target.contains("x86_64") {
        "Win64"
    } else {
        "Win32"
    };
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);

    // Find an instance of devenv.exe from Visual Studio IDE in order to upgrade
    // libsass.sln to the current available IDE. Do nothing if no devenv.exe found
    let d = cc::windows_registry::find(target.as_str(), "devenv.exe");
    if let Some(mut d) = d {
        let d = d
            .args(&["/upgrade", "win\\libsass.sln"])
            .current_dir(&build)
            .output()
            .expect("error running devenv");
        if !d.status.success() {
            let err = String::from_utf8_lossy(&d.stderr);
            let out = String::from_utf8_lossy(&d.stdout);
            println!("Upgrade error:\nSTDERR:{}\nSTDOUT:{}", err, out);
        }
    }

    let r = cc::windows_registry::find(target.as_str(), "msbuild.exe")
        .expect("could not find msbuild")
        .args(&[
            "win\\libsass.sln",
            "/p:LIBSASS_STATIC_LIB=1",
            "/p:Configuration=Release",
            "/p:WholeProgramOptimization=false",
            format!("/p:Platform={}", msvc_platform).as_str(),
        ])
        .current_dir(&build)
        .output()
        .expect("error running msbuild");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("win").join("bin").display()
    );
    println!("cargo:rustc-link-lib=static=libsass");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if let Ok(_) = pkg_config::find_library("libsass") {
        return;
    }

    compile();
}
<|endoftext|>


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

extern crate datafusion;
use datafusion::exec::*;

/// This example shows the steps to parse, plan, and execute simple SQL in the current process
fn main() {

    // create execution context
    let mut ctx = ExecutionContext::local("./test/data".to_string());

    // define an external table (csv file)
    ctx.sql("CREATE EXTERNAL TABLE uk_cities (\
        city VARCHAR(100), \
        lat DOUBLE, \
        lng DOUBLE)").unwrap();

    // define the SQL statement
    let sql = "SELECT ST_AsText(ST_Point(lat, lng)) FROM uk_cities WHERE lat < 53";

    // create a data frame
    let df1 = ctx.sql(&sql).unwrap();

    // write the results to a file
    ctx.write(df1,"_southern_cities.csv").unwrap();

}
<commit_msg>update example to avoid type coercion panic<commit_after>// Copyright 2018 Grove Enterprises LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate datafusion;
use datafusion::exec::*;

/// This example shows the steps to parse, plan, and execute simple SQL in the current process
fn main() {

    // create execution context
    let mut ctx = ExecutionContext::local("./test/data".to_string());

    // define an external table (csv file)
    ctx.sql("CREATE EXTERNAL TABLE uk_cities (\
        city VARCHAR(100), \
        lat DOUBLE, \
        lng DOUBLE)").unwrap();

    // define the SQL statement
    let sql = "SELECT ST_AsText(ST_Point(lat, lng)) FROM uk_cities WHERE lat < 53.0";

    // create a data frame
    let df1 = ctx.sql(&sql).unwrap();

    // write the results to a file
    ctx.write(df1,"_southern_cities.csv").unwrap();

}
<|endoftext|>


<commit_before>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate glfw;
extern crate image;

use glfw::{Action, Context, Key};
use image::DynamicImage;
use image::imageops;

fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    let (mut window, events) = glfw.create_window(600, 600, "Cursor Icon Testing", glfw::WindowMode::Windowed)
                                   .expect("Failed to create GLFW window.");

    window.set_key_polling(true);
    window.make_current();
    glfw.set_swap_interval(glfw::SwapInterval::Sync(1));

    //Place cursor variable here so it doesn't Drop until the program ends
    let cursor;

    if let DynamicImage::ImageRgba8(icon) = image::open("examples/icon.png").unwrap() {
        //Resize icon while preserving aspect ratio
        let resized_icon = imageops::resize(&icon, 32, icon.height() / icon.width() * 32, image::imageops::Lanczos3);

        cursor = glfw::Cursor::create(resized_icon, 0, 0);

        window.set_cursor(Some(&cursor));
    }

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }
    }
}

fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
    match event {
        glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
            window.set_should_close(true)
        }
        _ => {}
    }
}
<commit_msg>Update cursor_icon example.<commit_after>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate glfw;
extern crate image;

use glfw::{Action, Context, Key};
use image::DynamicImage;
use image::imageops;

fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    let (mut window, events) = glfw.create_window(600, 600, "Cursor Icon Testing", glfw::WindowMode::Windowed)
                                   .expect("Failed to create GLFW window.");

    window.set_key_polling(true);
    window.make_current();
    glfw.set_swap_interval(glfw::SwapInterval::Sync(1));

    if let DynamicImage::ImageRgba8(icon) = image::open("examples/icon.png").unwrap() {
        //Resize icon while preserving aspect ratio
        let resized_icon = imageops::resize(&icon, 32, icon.height() / icon.width() * 32, image::imageops::Lanczos3);

        let cursor = glfw::Cursor::create(resized_icon, 0, 0);

        window.set_cursor(Some(cursor));
    }

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }
    }
}

fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
    match event {
        glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
            window.set_should_close(true)
        }
        _ => {}
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Linus Färnstrand <faern@faern.net>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for sending and receiving data link layer packets on a fake network managed
//! by in memory FIFO queues. Useful for writing tests.

use datalink::{self, DataLinkChannelIterator, DataLinkReceiver,
               DataLinkSender, NetworkInterface};
use std::io;
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;
use std::time;
use util::MacAddr;

/// Configuration for the dummy datalink backend. Contains `std::sync::mpsc`
/// channels that are used to communicate with the fake network.
#[derive(Debug)]
pub struct Config {
    receiver: Receiver<io::Result<Box<[u8]>>>,
    inject_handle: Option<Sender<io::Result<Box<[u8]>>>>,

    sender: Sender<Box<[u8]>>,
    read_handle: Option<Receiver<Box<[u8]>>>,
}

impl Config {
    /// Creates a new `Config` with the given channels as the backing network.
    /// When using this constructor `inject_handle` and `read_handle` will return `None`.
    /// Those handles must be kept track of elsewhere.
    ///
    /// The `DataLinkChannelIterator` created by the dummy backend will read packets from
    /// `receiver`. Both network errors and data can be sent on this channel.
    /// When the `receiver` channel is closed (`Sender` is dropped)
    /// `DataLinkChannelIterator::next()` will sleep forever, simlating an idle network.
    ///
    /// The `DataLinkSender` created by the dummy backend will send all packets sent
    /// through `build_and_send()` and `send_to()` to the `sender` channel.
    pub fn new(receiver: Receiver<io::Result<Box<[u8]>>>, sender: Sender<Box<[u8]>>) -> Config {
        Config {
            receiver: receiver,
            inject_handle: None,
            sender: sender,
            read_handle: None,
        }
    }

    /// Get the `Sender` handle that can inject packets in the fake network.
    /// Only usable with `Config`s generated from `default()`
    pub fn inject_handle(&mut self) -> Option<Sender<io::Result<Box<[u8]>>>> {
        self.inject_handle.take()
    }

    /// Get the `Receiver` handle where packets sent to the fake network can be read.
    /// Only usable with `Config`s generated from `default()`
    pub fn read_handle(&mut self) -> Option<Receiver<Box<[u8]>>> {
        self.read_handle.take()
    }
}

impl<'a> From<&'a datalink::Config> for Config {
    /// Will not use the `datalink::Config`. This will simply call `dummy::Config::default()`.
    fn from(_config: &datalink::Config) -> Config {
        Config::default()
    }
}

impl Default for Config {
    /// Creates a default config with one input and one output channel. The handles used to inject
    /// to and read form the network can be fetched with `inject_handle()` and `read_handle()`
    fn default() -> Config {
        let (in_tx, in_rx) = mpsc::channel();
        let (out_tx, out_rx) = mpsc::channel();
        Config {
            receiver: in_rx,
            inject_handle: Some(in_tx),
            sender: out_tx,
            read_handle: Some(out_rx),
        }
    }
}

/// Create a data link channel backed by FIFO queues. Useful for debugging and testing.
/// See `Config` for how to inject and read packets on this fake network.
pub fn channel(_: &NetworkInterface, config: Config) -> io::Result<datalink::Channel> {
    let sender = Box::new(MockDataLinkSender { sender: config.sender });
    let receiver = Box::new(MockDataLinkReceiver { receiver: Some(config.receiver) });

    Ok(datalink::Channel::Ethernet(sender, receiver))
}

struct MockDataLinkSender {
    sender: Sender<Box<[u8]>>,
}

impl DataLinkSender for MockDataLinkSender {
    fn build_and_send(&mut self,
                      num_packets: usize,
                      packet_size: usize,
                      func: &mut FnMut(&mut [u8]))
        -> Option<io::Result<()>> {
        for _ in 0..num_packets {
            let mut buffer = vec![0; packet_size];
            func(&mut buffer);
            // Send the data to the queue. Don't care if it's closed
            self.sender.send(buffer.into_boxed_slice()).unwrap_or(());
        }
        Some(Ok(()))
    }

    fn send_to(&mut self,
               packet: &[u8],
               _dst: Option<NetworkInterface>)
        -> Option<io::Result<()>> {
        let buffer = packet.to_vec();
        self.sender.send(buffer.into_boxed_slice()).unwrap_or(());
        Some(Ok(()))
    }
}

struct MockDataLinkReceiver {
    receiver: Option<Receiver<io::Result<Box<[u8]>>>>,
}

impl DataLinkReceiver for MockDataLinkReceiver {
    fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a> {
        Box::new(MockDataLinkChannelIterator {
            receiver: self.receiver.take().expect("Only one receiver allowed"),
            used_packets: vec![],
        })
    }
}

struct MockDataLinkChannelIterator {
    receiver: Receiver<io::Result<Box<[u8]>>>,
    used_packets: Vec<Box<[u8]>>,
}

impl<'a> DataLinkChannelIterator<'a> for MockDataLinkChannelIterator {
    fn next(&mut self) -> io::Result<&[u8]> {
        match self.receiver.recv() {
            Ok(result) => {
                // A network event happened. Might be a packet or a simulated error
                match result {
                    Ok(buffer) => {
                        self.used_packets.push(buffer);
                        let buffer_ref = &*self.used_packets[self.used_packets.len() - 1];
                        Ok(buffer_ref)
                    }
                    Err(e) => Err(e),
                }
            }
            Err(_) => {
                // The channel supplying fake packets is broken. The user lost/destroyed their
                // inject_handle. This means there will never be any more packets sent to this
                // dummy network. To simulate an idle network we block and sleep forever here.
                loop {
                    thread::sleep(time::Duration::new(10, 0));
                }
            }
        }
    }
}

/// Get three fake interfaces generated with `dummy_interface(0..3)`.
pub fn interfaces() -> Vec<NetworkInterface> {
    (0..3).map(|i| dummy_interface(i)).collect()
}

/// Generates a fake `NetworkInterface`.
/// The name of the interface will be `ethX` where X is the integer `i`.
/// The index will be `i`.
/// The MAC will be `01:02:03:04:05:i`.
pub fn dummy_interface(i: u8) -> NetworkInterface {
    NetworkInterface {
        name: format!("eth{}", i),
        index: i as u32,
        mac: Some(MacAddr::new(1, 2, 3, 4, 5, i)),
        ips: Vec::new(),
        flags: 0,
    }
}

#[cfg(test)]
mod tests {
    use datalink::{DataLinkReceiver, DataLinkSender};
    use datalink::Channel::Ethernet;

    use std::io;
    use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
    use std::thread::{sleep, spawn};
    use std::time::Duration;

    #[test]
    fn send_nothing() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending zero packets yields zero packets
        let mut builder = |_: &mut [u8]| {
            panic!("Should not be called");
        };
        tx.build_and_send(0, 20, &mut builder).unwrap().unwrap();
        assert!(read_handle.try_recv().is_err());
    }

    #[test]
    fn send_one_packet() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending one packet yields one packet
        let mut builder = |pkg: &mut [u8]| {
            assert_eq!(pkg.len(), 20);
            pkg[0] = 9;
            pkg[19] = 201;
        };
        tx.build_and_send(1, 20, &mut builder).unwrap().unwrap();
        let pkg = read_handle.try_recv().expect("Expected one packet to be sent");
        assert!(read_handle.try_recv().is_err());
        assert_eq!(pkg.len(), 20);
        assert_eq!(pkg[0], 9);
        assert_eq!(pkg[19], 201);
    }

    #[test]
    fn send_multiple_packets() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending multiple packets does the correct thing
        let mut closure_counter = 0;
        let mut builder = |pkg: &mut [u8]| {
            pkg[0] = closure_counter;
            closure_counter += 1;
        };
        tx.build_and_send(3, 20, &mut builder).unwrap().unwrap();
        for i in 0..3 {
            let pkg = read_handle.try_recv().expect("Expected a packet");
            assert_eq!(pkg[0], i);
        }
        assert!(read_handle.try_recv().is_err());
    }

    #[test]
    fn send_to() {
        let (_, read_handle, mut tx, _) = create_net();
        let mut buffer = vec![0; 20];
        buffer[1] = 34;
        buffer[18] = 76;

        tx.send_to(&buffer, None).unwrap().unwrap();
        let pkg = read_handle.try_recv().expect("Expected one packet to be sent");
        assert!(read_handle.try_recv().is_err());
        assert_eq!(pkg.len(), 20);
        assert_eq!(pkg[1], 34);
        assert_eq!(pkg[18], 76);
    }

    #[test]
    fn read_nothing() {
        let (_, _, _, mut rx) = create_net();
        let (control_tx, control_rx) = mpsc::channel();
        spawn(move || {
            let mut rx_iter = rx.iter();
            rx_iter.next().expect("Should not happen 1");
            control_tx.send(()).expect("Should not happen 2");
        });
        sleep(Duration::new(0, 1_000_000));
        match control_rx.try_recv() {
            Ok(_) => panic!("Nothing should have arrived"),
            Err(TryRecvError::Disconnected) => panic!("Thread should not have quit"),
            Err(TryRecvError::Empty) => (),
        }
    }

    #[test]
    fn read_one_pkg() {
        let (inject_handle, _, _, mut rx) = create_net();

        let buffer = vec![0; 20];
        inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();

        let mut rx_iter = rx.iter();
        let pkg = rx_iter.next().expect("Expected a packet");
        assert_eq!(pkg.len(), 20);
    }

    #[test]
    fn read_multiple_pkgs() {
        let (inject_handle, _, _, mut rx) = create_net();

        for i in 0..3 {
            let buffer = vec![i; 20];
            inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();
        }

        let mut rx_iter = rx.iter();
        {
            let pkg1 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg1[0], 0);
        }
        {
            let pkg2 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg2[0], 1);
        }
        {
            let pkg3 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg3[0], 2);
        }
    }

    fn create_net()
        -> (Sender<io::Result<Box<[u8]>>>,
            Receiver<Box<[u8]>>,
            Box<DataLinkSender>,
            Box<DataLinkReceiver>) {
        let interface = super::dummy_interface(56);
        let mut config = super::Config::default();
        let inject_handle = config.inject_handle().unwrap();
        let read_handle = config.read_handle().unwrap();

        let channel = super::channel(&interface, config);
        let (tx, rx) = match channel {
            Ok(Ethernet(tx, rx)) => (tx, rx),
            _ => panic!("Not a valid channel returned"),
        };
        (inject_handle, read_handle, tx, rx)
    }
}
<commit_msg>Get rid of DataLinkChannelIterator in dummy<commit_after>// Copyright (c) 2016 Linus Färnstrand <faern@faern.net>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for sending and receiving data link layer packets on a fake network managed
//! by in memory FIFO queues. Useful for writing tests.

use datalink::{self, DataLinkReceiver, DataLinkSender, NetworkInterface};
use std::io;
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;
use std::time;
use util::MacAddr;

/// Configuration for the dummy datalink backend. Contains `std::sync::mpsc`
/// channels that are used to communicate with the fake network.
#[derive(Debug)]
pub struct Config {
    receiver: Receiver<io::Result<Box<[u8]>>>,
    inject_handle: Option<Sender<io::Result<Box<[u8]>>>>,

    sender: Sender<Box<[u8]>>,
    read_handle: Option<Receiver<Box<[u8]>>>,
}

impl Config {
    /// Creates a new `Config` with the given channels as the backing network.
    /// When using this constructor `inject_handle` and `read_handle` will return `None`.
    /// Those handles must be kept track of elsewhere.
    ///
    /// The `DataLinkReceiver` created by the dummy backend will read packets from
    /// `receiver`. Both network errors and data can be sent on this channel.
    /// When the `receiver` channel is closed (`Sender` is dropped)
    /// `DataLinkReceiver::next()` will sleep forever, simlating an idle network.
    ///
    /// The `DataLinkSender` created by the dummy backend will send all packets sent
    /// through `build_and_send()` and `send_to()` to the `sender` channel.
    pub fn new(receiver: Receiver<io::Result<Box<[u8]>>>, sender: Sender<Box<[u8]>>) -> Config {
        Config {
            receiver: receiver,
            inject_handle: None,
            sender: sender,
            read_handle: None,
        }
    }

    /// Get the `Sender` handle that can inject packets in the fake network.
    /// Only usable with `Config`s generated from `default()`
    pub fn inject_handle(&mut self) -> Option<Sender<io::Result<Box<[u8]>>>> {
        self.inject_handle.take()
    }

    /// Get the `Receiver` handle where packets sent to the fake network can be read.
    /// Only usable with `Config`s generated from `default()`
    pub fn read_handle(&mut self) -> Option<Receiver<Box<[u8]>>> {
        self.read_handle.take()
    }
}

impl<'a> From<&'a datalink::Config> for Config {
    /// Will not use the `datalink::Config`. This will simply call `dummy::Config::default()`.
    fn from(_config: &datalink::Config) -> Config {
        Config::default()
    }
}

impl Default for Config {
    /// Creates a default config with one input and one output channel. The handles used to inject
    /// to and read form the network can be fetched with `inject_handle()` and `read_handle()`
    fn default() -> Config {
        let (in_tx, in_rx) = mpsc::channel();
        let (out_tx, out_rx) = mpsc::channel();
        Config {
            receiver: in_rx,
            inject_handle: Some(in_tx),
            sender: out_tx,
            read_handle: Some(out_rx),
        }
    }
}

/// Create a data link channel backed by FIFO queues. Useful for debugging and testing.
/// See `Config` for how to inject and read packets on this fake network.
pub fn channel(_: &NetworkInterface, config: Config) -> io::Result<datalink::Channel> {
    let sender = Box::new(MockDataLinkSender { sender: config.sender });
    let receiver = Box::new(MockDataLinkReceiver {
        receiver: config.receiver,
        used_packets: Vec::new()
    });

    Ok(datalink::Channel::Ethernet(sender, receiver))
}

struct MockDataLinkSender {
    sender: Sender<Box<[u8]>>,
}

impl DataLinkSender for MockDataLinkSender {
    fn build_and_send(&mut self,
                      num_packets: usize,
                      packet_size: usize,
                      func: &mut FnMut(&mut [u8]))
        -> Option<io::Result<()>> {
        for _ in 0..num_packets {
            let mut buffer = vec![0; packet_size];
            func(&mut buffer);
            // Send the data to the queue. Don't care if it's closed
            self.sender.send(buffer.into_boxed_slice()).unwrap_or(());
        }
        Some(Ok(()))
    }

    fn send_to(&mut self,
               packet: &[u8],
               _dst: Option<NetworkInterface>)
        -> Option<io::Result<()>> {
        let buffer = packet.to_vec();
        self.sender.send(buffer.into_boxed_slice()).unwrap_or(());
        Some(Ok(()))
    }
}

struct MockDataLinkReceiver {
    receiver: Receiver<io::Result<Box<[u8]>>>,
    used_packets: Vec<Box<[u8]>>,
}

impl DataLinkReceiver for MockDataLinkReceiver {
    fn next(&mut self) -> io::Result<&[u8]> {
        match self.receiver.recv() {
            Ok(result) => {
                // A network event happened. Might be a packet or a simulated error
                match result {
                    Ok(buffer) => {
                        self.used_packets.push(buffer);
                        let buffer_ref = &*self.used_packets[self.used_packets.len() - 1];
                        Ok(buffer_ref)
                    }
                    Err(e) => Err(e),
                }
            }
            Err(_) => {
                // The channel supplying fake packets is broken. The user lost/destroyed their
                // inject_handle. This means there will never be any more packets sent to this
                // dummy network. To simulate an idle network we block and sleep forever here.
                loop {
                    thread::sleep(time::Duration::new(10, 0));
                }
            }
        }
    }
}

/// Get three fake interfaces generated with `dummy_interface(0..3)`.
pub fn interfaces() -> Vec<NetworkInterface> {
    (0..3).map(|i| dummy_interface(i)).collect()
}

/// Generates a fake `NetworkInterface`.
/// The name of the interface will be `ethX` where X is the integer `i`.
/// The index will be `i`.
/// The MAC will be `01:02:03:04:05:i`.
pub fn dummy_interface(i: u8) -> NetworkInterface {
    NetworkInterface {
        name: format!("eth{}", i),
        index: i as u32,
        mac: Some(MacAddr::new(1, 2, 3, 4, 5, i)),
        ips: Vec::new(),
        flags: 0,
    }
}

#[cfg(test)]
mod tests {
    use datalink::{DataLinkReceiver, DataLinkSender};
    use datalink::Channel::Ethernet;

    use std::io;
    use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
    use std::thread::{sleep, spawn};
    use std::time::Duration;

    #[test]
    fn send_nothing() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending zero packets yields zero packets
        let mut builder = |_: &mut [u8]| {
            panic!("Should not be called");
        };
        tx.build_and_send(0, 20, &mut builder).unwrap().unwrap();
        assert!(read_handle.try_recv().is_err());
    }

    #[test]
    fn send_one_packet() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending one packet yields one packet
        let mut builder = |pkg: &mut [u8]| {
            assert_eq!(pkg.len(), 20);
            pkg[0] = 9;
            pkg[19] = 201;
        };
        tx.build_and_send(1, 20, &mut builder).unwrap().unwrap();
        let pkg = read_handle.try_recv().expect("Expected one packet to be sent");
        assert!(read_handle.try_recv().is_err());
        assert_eq!(pkg.len(), 20);
        assert_eq!(pkg[0], 9);
        assert_eq!(pkg[19], 201);
    }

    #[test]
    fn send_multiple_packets() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending multiple packets does the correct thing
        let mut closure_counter = 0;
        let mut builder = |pkg: &mut [u8]| {
            pkg[0] = closure_counter;
            closure_counter += 1;
        };
        tx.build_and_send(3, 20, &mut builder).unwrap().unwrap();
        for i in 0..3 {
            let pkg = read_handle.try_recv().expect("Expected a packet");
            assert_eq!(pkg[0], i);
        }
        assert!(read_handle.try_recv().is_err());
    }

    #[test]
    fn send_to() {
        let (_, read_handle, mut tx, _) = create_net();
        let mut buffer = vec![0; 20];
        buffer[1] = 34;
        buffer[18] = 76;

        tx.send_to(&buffer, None).unwrap().unwrap();
        let pkg = read_handle.try_recv().expect("Expected one packet to be sent");
        assert!(read_handle.try_recv().is_err());
        assert_eq!(pkg.len(), 20);
        assert_eq!(pkg[1], 34);
        assert_eq!(pkg[18], 76);
    }

    #[test]
    fn read_nothing() {
        let (_, _, _, mut rx) = create_net();
        let (control_tx, control_rx) = mpsc::channel();
        spawn(move || {
            rx.next().expect("Should not happen 1");
            control_tx.send(()).expect("Should not happen 2");
        });
        sleep(Duration::new(0, 1_000_000));
        match control_rx.try_recv() {
            Ok(_) => panic!("Nothing should have arrived"),
            Err(TryRecvError::Disconnected) => panic!("Thread should not have quit"),
            Err(TryRecvError::Empty) => (),
        }
    }

    #[test]
    fn read_one_pkg() {
        let (inject_handle, _, _, mut rx) = create_net();

        let buffer = vec![0; 20];
        inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();

        let pkg = rx.next().expect("Expected a packet");
        assert_eq!(pkg.len(), 20);
    }

    #[test]
    fn read_multiple_pkgs() {
        let (inject_handle, _, _, mut rx) = create_net();

        for i in 0..3 {
            let buffer = vec![i; 20];
            inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();
        }

        {
            let pkg1 = rx.next().expect("Expected a packet");
            assert_eq!(pkg1[0], 0);
        }
        {
            let pkg2 = rx.next().expect("Expected a packet");
            assert_eq!(pkg2[0], 1);
        }
        {
            let pkg3 = rx.next().expect("Expected a packet");
            assert_eq!(pkg3[0], 2);
        }
    }

    fn create_net()
        -> (Sender<io::Result<Box<[u8]>>>,
            Receiver<Box<[u8]>>,
            Box<DataLinkSender>,
            Box<DataLinkReceiver>) {
        let interface = super::dummy_interface(56);
        let mut config = super::Config::default();
        let inject_handle = config.inject_handle().unwrap();
        let read_handle = config.read_handle().unwrap();

        let channel = super::channel(&interface, config);
        let (tx, rx) = match channel {
            Ok(Ethernet(tx, rx)) => (tx, rx),
            _ => panic!("Not a valid channel returned"),
        };
        (inject_handle, read_handle, tx, rx)
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix fmt.<commit_after><|endoftext|>