<commit_before>use std::io::Read;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::mac::MacResult;
use crypto::sha1::Sha1;
use hex::FromHex;
use iron;
use serde_json;

use DB_POOL;
use builds;
use config::CONFIG;
use error::DashResult;
use github::models::{CommentFromJson, IssueFromJson, PullRequestFromJson};
use github::{handle_comment, handle_issue, handle_pr};

/// signature for request
/// see [this document](https://developer.github.com/webhooks/securing/) for more information
header! {(XHubSignature, "X-Hub-Signature") => [String]}

/// name of Github event
/// see [this document](https://developer.github.com/webhooks/#events) for available types
header! {(XGithubEvent, "X-Github-Event") => [String]}

/// unique id for each delivery
header! {(XGithubDelivery, "X-Github-Delivery") => [String]}

pub fn handler(req: &mut iron::Request) -> iron::IronResult<iron::Response> {
    match inner_handler(req) {
        Ok(()) => (),
        Err(why) => error!("Error processing webhook: {:?}", why),
    }

    Ok(iron::Response::with((iron::status::Ok, "ok")))
}

fn inner_handler(req: &mut iron::Request) -> DashResult<()> {
    if let (Some(&XGithubEvent(ref event_name)),
            Some(&XGithubDelivery(ref delivery_id)),
            Some(&XHubSignature(ref signature))) =
        (req.headers.get::<XGithubEvent>(),
         req.headers.get::<XGithubDelivery>(),
         req.headers.get::<XHubSignature>()) {

        // unfortunately we need to read untrusted input before authenticating
        // b/c we need to sha the request payload
        let mut body = String::new();
        req.body.read_to_string(&mut body)?;

        let mut authenticated = false;

        for secret in &CONFIG.github_webhook_secrets {
            if authenticate(secret, &body, signature) {
                // once we know it's from github, we'll parse it

                authenticated = true;

                let payload = parse_event(event_name, &body)?;

                let full_event = Event {
                    delivery_id: delivery_id.to_owned(),
                    event_name: event_name.to_owned(),
                    payload: payload,
                };

                info!("Received valid webhook ({} id {})",
                      full_event.event_name,
                      full_event.delivery_id);

                authenticated_handler(full_event)?;
                break;
            }
        }

        if !authenticated {
            warn!("Received invalid webhook: {:?}", req);
        }
    }

    Ok(())
}

fn authenticate(secret: &str, payload: &str, signature: &str) -> bool {
    // https://developer.github.com/webhooks/securing/#validating-payloads-from-github
    let sans_prefix = signature[5..].as_bytes();
    match Vec::from_hex(sans_prefix) {
        Ok(sigbytes) => {
            let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());
            mac.input(payload.as_bytes());
            // constant time comparison
            mac.result() == MacResult::new(&sigbytes)
        }
        Err(_) => false,
    }
}

fn parse_event(event_name: &str, body: &str) -> DashResult<Payload> {
    match event_name {
        "issue_comment" => Ok(Payload::IssueComment(serde_json::from_str(body)?)),
        "issues" => Ok(Payload::Issues(serde_json::from_str(body)?)),
        "pull_request" => Ok(Payload::PullRequest(serde_json::from_str(body)?)),
        "status" => Ok(Payload::Status(serde_json::from_str(body)?)),

        "commit_comment" |
        "create" |
        "delete" |
        "deployment" |
        "deployment_status" |
        "fork" |
        "gollum" |
        "label" |
        "member" |
        "membership" |
        "milestone" |
        "organization" |
        "page_build" |
        "public" |
        "pull_request_review_comment" |
        "pull_request_review" |
        "push" |
        "repository" |
        "release" |
        "team" |
        "team_add" |
        "watch" => {
            info!("Received {} event, ignoring...", event_name);
            Ok(Payload::Unsupported)
        }

        _ => {
            warn!("Received unrecognized event {}, check GitHub's API to see what's updated.",
                  event_name);
            Ok(Payload::Unsupported)
        }
    }
}

fn authenticated_handler(event: Event) -> DashResult<()> {
    let conn = &*DB_POOL.get()?;

    match event.payload {
        Payload::Issues(issue_event) => {
            handle_issue(conn, issue_event.issue, &issue_event.repository.full_name)?;
        }

        Payload::PullRequest(pr_event) => {
            handle_pr(conn, pr_event.pull_request, &pr_event.repository.full_name)?;
        }

        Payload::IssueComment(comment_event) => {
            // possible race conditions if we get a comment hook before the issue one (or we
            // missed the issue one), so make sure the issue exists first

            if comment_event.action != "deleted" {
                // TODO handle deleted comments properly
                handle_issue(conn, comment_event.issue, &comment_event.repository.full_name)?;
                handle_comment(conn, comment_event.comment, &comment_event.repository.full_name)?;
            }
        }

        Payload::Status(status_event) => {
            if status_event.state != "pending" &&
                status_event.commit.committer.login == "bors"
            {
                if let Some(url) = status_event.target_url {
                    builds::ingest_status_event(url)?
                }
            }
        },

        Payload::Unsupported => (),
    }

    Ok(())
}

#[derive(Debug)]
pub struct Event {
    delivery_id: String,
    event_name: String,
    payload: Payload,
}

#[derive(Debug)]
pub enum Payload {
    Issues(IssuesEvent),
    IssueComment(IssueCommentEvent),
    PullRequest(PullRequestEvent),
    Status(StatusEvent),

    Unsupported,
}

#[derive(Debug, Deserialize)]
pub struct IssuesEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
}

#[derive(Debug, Deserialize)]
pub struct IssueCommentEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
    comment: CommentFromJson,
}

#[derive(Debug, Deserialize)]
pub struct PullRequestEvent {
    action: String,
    repository: Repository,
    number: i32,
    pull_request: PullRequestFromJson,
}

#[derive(Debug, Deserialize)]
pub struct Repository {
    full_name: String,
}

#[derive(Debug, Deserialize)]
pub struct StatusEvent {
    commit: Commit,
    state: String,
    target_url: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct Commit {
    committer: Committer,
}

#[derive(Debug, Deserialize)]
pub struct Committer {
    login: String,
}
<commit_msg>Make webhook structs private<commit_after>use std::io::Read;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::mac::MacResult;
use crypto::sha1::Sha1;
use hex::FromHex;
use iron;
use serde_json;

use DB_POOL;
use builds;
use config::CONFIG;
use error::DashResult;
use github::models::{CommentFromJson, IssueFromJson, PullRequestFromJson};
use github::{handle_comment, handle_issue, handle_pr};

/// signature for request
/// see [this document](https://developer.github.com/webhooks/securing/) for more information
header! {(XHubSignature, "X-Hub-Signature") => [String]}

/// name of Github event
/// see [this document](https://developer.github.com/webhooks/#events) for available types
header! {(XGithubEvent, "X-Github-Event") => [String]}

/// unique id for each delivery
header! {(XGithubDelivery, "X-Github-Delivery") => [String]}

pub fn handler(req: &mut iron::Request) -> iron::IronResult<iron::Response> {
    match inner_handler(req) {
        Ok(()) => (),
        Err(why) => error!("Error processing webhook: {:?}", why),
    }

    Ok(iron::Response::with((iron::status::Ok, "ok")))
}

fn inner_handler(req: &mut iron::Request) -> DashResult<()> {
    if let (Some(&XGithubEvent(ref event_name)),
            Some(&XGithubDelivery(ref delivery_id)),
            Some(&XHubSignature(ref signature))) =
        (req.headers.get::<XGithubEvent>(),
         req.headers.get::<XGithubDelivery>(),
         req.headers.get::<XHubSignature>()) {

        // unfortunately we need to read untrusted input before authenticating
        // b/c we need to sha the request payload
        let mut body = String::new();
        req.body.read_to_string(&mut body)?;

        let mut authenticated = false;

        for secret in &CONFIG.github_webhook_secrets {
            if authenticate(secret, &body, signature) {
                // once we know it's from github, we'll parse it

                authenticated = true;

                let payload = parse_event(event_name, &body)?;

                let full_event = Event {
                    delivery_id: delivery_id.to_owned(),
                    event_name: event_name.to_owned(),
                    payload: payload,
                };

                info!("Received valid webhook ({} id {})",
                      full_event.event_name,
                      full_event.delivery_id);

                authenticated_handler(full_event)?;
                break;
            }
        }

        if !authenticated {
            warn!("Received invalid webhook: {:?}", req);
        }
    }

    Ok(())
}

fn authenticate(secret: &str, payload: &str, signature: &str) -> bool {
    // https://developer.github.com/webhooks/securing/#validating-payloads-from-github
    let sans_prefix = signature[5..].as_bytes();
    match Vec::from_hex(sans_prefix) {
        Ok(sigbytes) => {
            let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());
            mac.input(payload.as_bytes());
            // constant time comparison
            mac.result() == MacResult::new(&sigbytes)
        }
        Err(_) => false,
    }
}

fn parse_event(event_name: &str, body: &str) -> DashResult<Payload> {
    match event_name {
        "issue_comment" => Ok(Payload::IssueComment(serde_json::from_str(body)?)),
        "issues" => Ok(Payload::Issues(serde_json::from_str(body)?)),
        "pull_request" => Ok(Payload::PullRequest(serde_json::from_str(body)?)),
        "status" => Ok(Payload::Status(serde_json::from_str(body)?)),

        "commit_comment" |
        "create" |
        "delete" |
        "deployment" |
        "deployment_status" |
        "fork" |
        "gollum" |
        "label" |
        "member" |
        "membership" |
        "milestone" |
        "organization" |
        "page_build" |
        "public" |
        "pull_request_review_comment" |
        "pull_request_review" |
        "push" |
        "repository" |
        "release" |
        "team" |
        "team_add" |
        "watch" => {
            info!("Received {} event, ignoring...", event_name);
            Ok(Payload::Unsupported)
        }

        _ => {
            warn!("Received unrecognized event {}, check GitHub's API to see what's updated.",
                  event_name);
            Ok(Payload::Unsupported)
        }
    }
}

fn authenticated_handler(event: Event) -> DashResult<()> {
    let conn = &*DB_POOL.get()?;

    match event.payload {
        Payload::Issues(issue_event) => {
            handle_issue(conn, issue_event.issue, &issue_event.repository.full_name)?;
        }

        Payload::PullRequest(pr_event) => {
            handle_pr(conn, pr_event.pull_request, &pr_event.repository.full_name)?;
        }

        Payload::IssueComment(comment_event) => {
            // possible race conditions if we get a comment hook before the issue one (or we
            // missed the issue one), so make sure the issue exists first

            if comment_event.action != "deleted" {
                // TODO handle deleted comments properly
                handle_issue(conn, comment_event.issue, &comment_event.repository.full_name)?;
                handle_comment(conn, comment_event.comment, &comment_event.repository.full_name)?;
            }
        }

        Payload::Status(status_event) => {
            if status_event.state != "pending" &&
                status_event.commit.committer.login == "bors"
            {
                if let Some(url) = status_event.target_url {
                    builds::ingest_status_event(url)?
                }
            }
        },

        Payload::Unsupported => (),
    }

    Ok(())
}

#[derive(Debug)]
struct Event {
    delivery_id: String,
    event_name: String,
    payload: Payload,
}

#[derive(Debug)]
enum Payload {
    Issues(IssuesEvent),
    IssueComment(IssueCommentEvent),
    PullRequest(PullRequestEvent),
    Status(StatusEvent),

    Unsupported,
}

#[derive(Debug, Deserialize)]
struct IssuesEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
}

#[derive(Debug, Deserialize)]
struct IssueCommentEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
    comment: CommentFromJson,
}

#[derive(Debug, Deserialize)]
struct PullRequestEvent {
    action: String,
    repository: Repository,
    number: i32,
    pull_request: PullRequestFromJson,
}

#[derive(Debug, Deserialize)]
struct Repository {
    full_name: String,
}

#[derive(Debug, Deserialize)]
struct StatusEvent {
    commit: Commit,
    state: String,
    target_url: Option<String>,
}

#[derive(Debug, Deserialize)]
struct Commit {
    committer: Committer,
}

#[derive(Debug, Deserialize)]
struct Committer {
    login: String,
}
<|endoftext|>


<commit_before><commit_msg>Help and version options parsed and implemented.<commit_after><|endoftext|>


<commit_before><commit_msg>Support for "riff file1 file2" to diff two files<commit_after><|endoftext|>


<commit_before><commit_msg>rustfmt pass<commit_after><|endoftext|>


<commit_before>extern crate rand;
use rand::Rng;

fn main() {
    // FUTURE: can get width, height, population density, and num_generations from user:
    // width and height hould be greater than 0 and less than 100
    let width:           usize        = 20;
    let height:          usize        = 20;
    let num_generations: u8           = 100;
    let mut board:       Vec<Vec<u8>> = vec![vec![0; height]; width];
    populate_board_random(&mut board, 20);
    print_board(&board);
}

/// Prints the given board
/// Assumes board has dimensions greater than [0][0] and smaller than [100][100]
fn print_board(board: &Vec<Vec<u8>>) {
    for cell_num in 0..(board[0].len() + 1) {
        print!("{:3}", cell_num);
    }
    println!("");
    let mut row_num: u8 = 1;
    for row in board {
        print!("{:3}", row_num);
        row_num = row_num + 1;
        for cell in row {
            if *cell == 0 {
                print!("   ");
            } else {
                print!("  +");
            }
        }
        println!("");
    }
}

/// Populates the given board with a generation containing
/// percent_alive percent of live cells
fn populate_board_random(board: &mut Vec<Vec<u8>>, percent_alive: u8) {
    for row in board {
        for cell in row {
            let die_value: u8 = rand::thread_rng().gen_range(1, 101);
            if percent_alive >= die_value {
                *cell = 1;
            }
        }
    }
}
<commit_msg>Implement Game of Life logic<commit_after>extern crate rand;
use rand::Rng;

fn main() {
    // FUTURE: can get width, height, population density, and num_generations from user:
    // width and height hould be greater than 0 and less than 100
    let width:           usize        = 15;
    let height:          usize        = 15;
    let num_generations: u8           = 10;
    // board: the canonical Vec representing the state of our cells
    let mut board:       Vec<Vec<u8>> = vec![vec![0; height]; width];
    // tmp_board: Temporary board used to calculate intermediate states before
    // writing them to board.
    let mut tmp_board:   Vec<Vec<u8>> = vec![vec![0; height]; width];

    populate_board_random(&mut board, 20);
    hacky_and_bad_screen_clear();

    print_board(&board);
    println!("Cur Gen: 0 (Initial State)");
    std::thread::sleep(std::time::Duration::new(1, 0));

    for cur_generation in 1..(num_generations + 1) {
        advance_generation(&mut board, &mut tmp_board);
        std::thread::sleep(std::time::Duration::new(1, 0));
        hacky_and_bad_screen_clear();
        print_board(&board);
        println!("Cur Gen: {}", cur_generation);
    }
}

/// Populates the given board with a generation containing
/// percent_alive percent of live cells
fn populate_board_random(board: &mut Vec<Vec<u8>>, percent_alive: u8) {
    for row in board {
        for cell in row {
            let die_value: u8 = rand::thread_rng().gen_range(1, 101);
            if percent_alive >= die_value {
                *cell = 1;
            }
        }
    }
}

/// Advances the given board by one generation of the Game of Life
/// Assumes board has dimensions greater than [0][0] and smaller than [100][100]
fn advance_generation(board: &mut Vec<Vec<u8>>, tmp_board: &mut Vec<Vec<u8>>) {
    for row_num in 0..board.len() {
        for cell_num in 0..board[0].len() {
            tmp_board[row_num][cell_num] = calculate_next_state(&board, row_num, cell_num);
        }
    }
    for row_num in 0..board.len() {
        for cell_num in 0..board[0].len() {
            board[row_num][cell_num] = tmp_board[row_num][cell_num];
        }
    }
}

/// Given a board and the coordinates of the cell, returns the value this cell will hold
/// in the next generation
fn calculate_next_state(board: &Vec<Vec<u8>>, row_num: usize, cell_num: usize) -> u8 {
    let mut num_neighbors_alive: u8 = 0;

    // check top left:
    num_neighbors_alive += {
        if row_num != 0 && cell_num != 0 {
            board[row_num - 1][cell_num - 1]
        } else {
            0
        }
    };
    // check top middle:
    num_neighbors_alive += {
        if row_num != 0 {
            board[row_num - 1][cell_num]
        } else {
            0
        }
    };
    // check top right:
    num_neighbors_alive += {
        if row_num != 0 && cell_num != (board[0].len() - 1) {
            board[row_num - 1][cell_num + 1]
        } else {
            0
        }
    };
    // check left:
    num_neighbors_alive += {
        if cell_num != 0 {
            board[row_num][cell_num - 1]
        } else {
            0
        }
    };
    // check right:
    num_neighbors_alive += {
        if cell_num != (board[0].len() - 1) {
            board[row_num][cell_num + 1]
        } else {
            0
        }
    };
    // check bottom left:
    num_neighbors_alive += {
        if row_num != (board.len() - 1) && cell_num != 0 {
            board[row_num + 1][cell_num - 1]
        } else {
            0
        }
    };
    // check bottom right
    num_neighbors_alive += {
        if row_num != (board.len() - 1) && cell_num != (board[0].len() - 1) {
            board[row_num + 1][cell_num + 1]
        } else {
            0
        }
    };
    // check bottom middle
    num_neighbors_alive += {
        if row_num != (board.len() - 1) {
            board[row_num + 1][cell_num]
        } else {
            0
        }
    };

    if num_neighbors_alive < 2 || num_neighbors_alive > 3 {
        0
    } else if num_neighbors_alive == 2 {
        board[row_num][cell_num]
    } else {
        1
    }
}

/// Prints the given board
/// Assumes board has dimensions greater than [0][0] and smaller than [100][100]
fn print_board(board: &Vec<Vec<u8>>) {
    for cell_num in 0..(board[0].len() + 1) {
        print!("{:3}", cell_num);
    }
    println!("");
    let mut row_num: u8 = 1;
    for row in board {
        print!("{:3}", row_num);
        row_num = row_num + 1;
        for cell in row {
            if *cell == 0 {
                print!("   ");
            } else {
                print!("  +");
            }
        }
        println!("");
    }
}

fn hacky_and_bad_screen_clear()
{
    if !std::process::Command::new("clear").status().unwrap().success() {
        assert!(false);
    }
}
<|endoftext|>


<commit_before><commit_msg>Adjust error message<commit_after><|endoftext|>


<commit_before><commit_msg>Remove stray file<commit_after><|endoftext|>


<commit_before>use gtk::{idle_add, TextBufferExt, TextTag, TextTagExt, TextTagTableExt, TextView, TextViewExt};
use log::{self, Level, LevelFilter, Log, Metadata, Record};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
use std::sync::mpsc::{sync_channel, TryRecvError, TrySendError};
use std::sync::Mutex;

use app::AppContextPointer;
use errors::SondeError;

const LOG_LEVEL: Level = Level::Trace;

const TEXT_AREA_ID: &str = "console_log";

pub fn set_up_console_log(acp: &AppContextPointer) -> Result<(), SondeError> {
    if let Ok(text_area) = acp.fetch_widget::<TextView>(TEXT_AREA_ID) {
        if let Some(buf) = text_area.get_buffer() {
            if let Some(tag_table) = buf.get_tag_table() {
                let tag = TextTag::new("default");

                tag.set_property_font(Some("courier bold 9"));

                let success = tag_table.add(&tag);
                debug_assert!(success, "Failed to add tag to text tag table");
            }
        }
    }

    let (tx, rx) = sync_channel::<String>(256);

    let logger = Box::new(AppLogger::new(tx));
    let acp2 = Rc::clone(acp);

    idle_add(move || {
        loop {
            match rx.try_recv() {
                Ok(ref msg) => log_msg(&acp2, msg),
                Err(TryRecvError::Disconnected) => log_msg(&acp2, "\n\nLOGGER DISCONNECTED\n\n"),
                Err(TryRecvError::Empty) => {
                    break;
                }
            }
        }

        ::glib::source::Continue(true)
    });

    log::set_boxed_logger(logger).map_err(|_| SondeError::LogError("Error setting logger"))?;
    log::set_max_level(LevelFilter::max());

    Ok(())
}

struct AppLogger {
    tx: ::std::sync::mpsc::SyncSender<String>,
    overflow: Mutex<RefCell<VecDeque<String>>>,
}

impl AppLogger {
    fn new(tx: ::std::sync::mpsc::SyncSender<String>) -> Self {
        AppLogger {
            tx,
            overflow: Mutex::new(RefCell::new(VecDeque::new())),
        }
    }
}

impl Log for AppLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= LOG_LEVEL
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            // put it on the overflow, and then try to empty
            let overflow = self.overflow.lock().unwrap();
            let mut overflow = overflow.borrow_mut();
            overflow.push_back(format!("{} - {}\n", record.level(), record.args()));

            // empty the overflow
            while let Some(msg) = overflow.pop_front() {
                match self.tx.try_send(msg) {
                    Ok(_) => {}
                    Err(TrySendError::Full(msg_back)) => {
                        overflow.push_front(msg_back);
                        break;
                    }
                    Err(TrySendError::Disconnected(_)) => {}
                }
            }
        }
    }

    fn flush(&self) {}
}

fn log_msg(acp: &AppContextPointer, msg: &str) {
    if let Ok(text_area) = acp.fetch_widget::<TextView>(TEXT_AREA_ID) {
        if let Some(buf) = text_area.get_buffer() {
            let end = &mut buf.get_end_iter();
            buf.insert(end, msg);

            let start = &buf.get_start_iter();
            buf.apply_tag_by_name("default", start, end);
        }
    }

    let acp2 = Rc::clone(acp);
    idle_add(move || {
        if let Ok(ta) = acp2.fetch_widget::<TextView>(TEXT_AREA_ID) {
            if let Some(buf) = ta.get_buffer() {
                let end = &mut buf.get_end_iter();
                ta.scroll_to_iter(end, 0.0, false, 1.0, 1.0);
            }
        }

        ::glib::source::Continue(false)
    });
}
<commit_msg>Fixed 100% processor running all the time.<commit_after>use gtk::{timeout_add_seconds, idle_add, TextBufferExt, TextTag, TextTagExt, TextTagTableExt, TextView, TextViewExt};
use log::{self, Level, LevelFilter, Log, Metadata, Record};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
use std::sync::mpsc::{sync_channel, TryRecvError, TrySendError};
use std::sync::Mutex;

use app::AppContextPointer;
use errors::SondeError;

const LOG_LEVEL: Level = Level::Trace;

const TEXT_AREA_ID: &str = "console_log";

pub fn set_up_console_log(acp: &AppContextPointer) -> Result<(), SondeError> {
    if let Ok(text_area) = acp.fetch_widget::<TextView>(TEXT_AREA_ID) {
        if let Some(buf) = text_area.get_buffer() {
            if let Some(tag_table) = buf.get_tag_table() {
                let tag = TextTag::new("default");

                tag.set_property_font(Some("courier bold 9"));

                let success = tag_table.add(&tag);
                debug_assert!(success, "Failed to add tag to text tag table");
            }
        }
    }

    let (tx, rx) = sync_channel::<String>(256);

    let logger = Box::new(AppLogger::new(tx));
    let acp2 = Rc::clone(acp);

    timeout_add_seconds(1, move || {
        loop {
            match rx.try_recv() {
                Ok(ref msg) => log_msg(&acp2, msg),
                Err(TryRecvError::Disconnected) => log_msg(&acp2, "\n\nLOGGER DISCONNECTED\n\n"),
                Err(TryRecvError::Empty) => {
                    break;
                }
            }
        }

        ::glib::source::Continue(true)
    });

    log::set_boxed_logger(logger).map_err(|_| SondeError::LogError("Error setting logger"))?;
    log::set_max_level(LevelFilter::max());

    Ok(())
}

struct AppLogger {
    tx: ::std::sync::mpsc::SyncSender<String>,
    overflow: Mutex<RefCell<VecDeque<String>>>,
}

impl AppLogger {
    fn new(tx: ::std::sync::mpsc::SyncSender<String>) -> Self {
        AppLogger {
            tx,
            overflow: Mutex::new(RefCell::new(VecDeque::new())),
        }
    }
}

impl Log for AppLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= LOG_LEVEL
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            // put it on the overflow, and then try to empty
            let overflow = self.overflow.lock().unwrap();
            let mut overflow = overflow.borrow_mut();
            overflow.push_back(format!("{} - {}\n", record.level(), record.args()));

            // empty the overflow
            while let Some(msg) = overflow.pop_front() {
                match self.tx.try_send(msg) {
                    Ok(_) => {}
                    Err(TrySendError::Full(msg_back)) => {
                        overflow.push_front(msg_back);
                        break;
                    }
                    Err(TrySendError::Disconnected(_)) => {}
                }
            }
        }
    }

    fn flush(&self) {}
}

fn log_msg(acp: &AppContextPointer, msg: &str) {
    if let Ok(text_area) = acp.fetch_widget::<TextView>(TEXT_AREA_ID) {
        if let Some(buf) = text_area.get_buffer() {
            let end = &mut buf.get_end_iter();
            buf.insert(end, msg);

            let start = &buf.get_start_iter();
            buf.apply_tag_by_name("default", start, end);
        }
    }

    let acp2 = Rc::clone(acp);
    idle_add(move || {
        if let Ok(ta) = acp2.fetch_widget::<TextView>(TEXT_AREA_ID) {
            if let Some(buf) = ta.get_buffer() {
                let end = &mut buf.get_end_iter();
                ta.scroll_to_iter(end, 0.0, false, 1.0, 1.0);
            }
        }

        ::glib::source::Continue(false)
    });
}
<|endoftext|>


<commit_before><commit_msg>Simplify an overflow check<commit_after><|endoftext|>


<commit_before><commit_msg>use mut patterns in *many smart constructors<commit_after><|endoftext|>


<commit_before>//! Unix-specific types for signal handling.
//!
//! This module is only defined on Unix platforms and contains the primary
//! `Signal` type for receiving notifications of signals.

#![cfg(unix)]

pub extern crate libc;
extern crate mio;
extern crate mio_uds;

use std::cell::UnsafeCell;
use std::collections::HashSet;
use std::io::prelude::*;
use std::io;
use std::mem;
use std::os::unix::prelude::*;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::sync::{Mutex, Once, ONCE_INIT};

use futures::future;
use futures::sync::mpsc::{Receiver, Sender, channel};
use futures::{Async, AsyncSink, Future};
use futures::{Sink, Stream, Poll};
use self::libc::c_int;
use self::mio::Poll as MioPoll;
use self::mio::unix::EventedFd;
use self::mio::{Evented, Token, Ready, PollOpt};
use self::mio_uds::UnixStream;
use tokio_core::io::IoFuture;
use tokio_core::reactor::{Handle, CoreId, PollEvented};

pub use self::libc::{SIGINT, SIGTERM, SIGUSR1, SIGUSR2};
pub use self::libc::{SIGHUP, SIGQUIT, SIGPIPE, SIGALRM, SIGTRAP};

// Number of different unix signals
const SIGNUM: usize = 32;

struct SignalInfo {
    pending: AtomicBool,
    // The ones interested in this signal
    recipients: Mutex<Vec<(usize, Sender<c_int>)>>,

	init: Once,
    initialized: UnsafeCell<bool>,
    prev: UnsafeCell<libc::sigaction>,
}

struct Globals {
    sender: UnixStream,
    receiver: UnixStream,
    signals: [SignalInfo; SIGNUM],
    drivers: Mutex<HashSet<CoreId>>,
}

impl Default for SignalInfo {
    fn default() -> SignalInfo {
        SignalInfo {
            pending: AtomicBool::new(false),
            init: ONCE_INIT,
            initialized: UnsafeCell::new(false),
            recipients: Mutex::new(Vec::new()),
            prev: UnsafeCell::new(unsafe { mem::zeroed() }),
        }
    }
}

static mut GLOBALS: *mut Globals = 0 as *mut Globals;

fn globals() -> &'static Globals {
    static INIT: Once = ONCE_INIT;

    unsafe {
        INIT.call_once(|| {
            let (receiver, sender) = UnixStream::pair().unwrap();
            let globals = Globals {
                sender: sender,
                receiver: receiver,
                signals: Default::default(),
                drivers: Mutex::new(HashSet::new()),
            };
            GLOBALS = Box::into_raw(Box::new(globals));
        });
        &*GLOBALS
    }
}

/// Our global signal handler for all signals registered by this module.
///
/// The purpose of this signal handler is to primarily:
///
/// 1. Flag that our specific signal was received (e.g. store an atomic flag)
/// 2. Wake up driver tasks by writing a byte to a pipe
///
/// Those two operations shoudl both be async-signal safe. After that's done we
/// just try to call a previous signal handler, if any, to be "good denizens of
/// the internet"
extern fn handler(signum: c_int,
                  info: *mut libc::siginfo_t,
                  ptr: *mut libc::c_void) {
	type FnSigaction = extern fn(c_int, *mut libc::siginfo_t, *mut libc::c_void);
	type FnHandler = extern fn(c_int);
    unsafe {
        let slot = match (*GLOBALS).signals.get(signum as usize) {
            Some(slot) => slot,
            None => return,
        };
        slot.pending.store(true, Ordering::SeqCst);

        // Send a wakeup, ignore any errors (anything reasonably possible is
        // full pipe and then it will wake up anyway).
        drop((*GLOBALS).sender.write(&[1]));

        let fnptr = (*slot.prev.get()).sa_sigaction;
        if fnptr == 0 || fnptr == libc::SIG_DFL || fnptr == libc::SIG_IGN {
            return
        }
        if (*slot.prev.get()).sa_flags & libc::SA_SIGINFO == 0 {
            let action = mem::transmute::<usize, FnHandler>(fnptr);
            action(signum)
        } else {
            let action = mem::transmute::<usize, FnSigaction>(fnptr);
            action(signum, info, ptr)
        }
    }
}

/// Enable this module to receive signal notifications for the `signal`
/// provided.
///
/// This will register the signal handler if it hasn't already been registered,
/// returning any error along the way if that fails.
fn signal_enable(signal: c_int) -> io::Result<()> {
    let siginfo = match globals().signals.get(signal as usize) {
        Some(slot) => slot,
        None => {
            return Err(io::Error::new(io::ErrorKind::Other, "signal too large"))
        }
    };
	unsafe {
        let mut err = None;
        siginfo.init.call_once(|| {
            let mut new: libc::sigaction = mem::zeroed();
            new.sa_sigaction = handler as usize;
            new.sa_flags = libc::SA_RESTART |
                            libc::SA_SIGINFO |
                            libc::SA_NOCLDSTOP;
            if libc::sigaction(signal, &new, &mut *siginfo.prev.get()) != 0 {
                err = Some(io::Error::last_os_error());
            } else {
                *siginfo.initialized.get() = true;
            }
        });
        if let Some(err) = err {
            return Err(err)
        }
        if *siginfo.initialized.get() {
            Ok(())
        } else {
            Err(io::Error::new(io::ErrorKind::Other,
                               "failed to register signal handler"))
        }
	}
}

/// A helper struct to register our global receiving end of the signal pipe on
/// multiple event loops.
///
/// This structure represents registering the receiving end on all event loops,
/// and uses `EventedFd` in mio to do so. It's stored in each driver task and is
/// used to read data and register interest in new signals coming in.
struct EventedReceiver;

impl Evented for EventedReceiver {
    fn register(&self, poll: &MioPoll, token: Token, events: Ready, opts: PollOpt) -> io::Result<()> {
        let fd = globals().receiver.as_raw_fd();
        EventedFd(&fd).register(poll, token, events, opts)
    }
    fn reregister(&self, poll: &MioPoll, token: Token, events: Ready, opts: PollOpt) -> io::Result<()> {
        let fd = globals().receiver.as_raw_fd();
        EventedFd(&fd).reregister(poll, token, events, opts)
    }
    fn deregister(&self, poll: &MioPoll) -> io::Result<()> {
        let fd = globals().receiver.as_raw_fd();
        EventedFd(&fd).deregister(poll)
    }
}

impl Read for EventedReceiver {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (&globals().receiver).read(buf)
    }
}

struct Driver {
    id: CoreId,
    wakeup: PollEvented<EventedReceiver>,
}

impl Future for Driver {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        // Drain the data from the pipe and maintain interest in getting more
        let any_wakeup = self.drain();
        if any_wakeup {
            self.broadcast();
        }
        // This task just lives until the end of the event loop
        Ok(Async::NotReady)
    }
}

impl Drop for Driver {
    fn drop(&mut self) {
        let mut drivers = globals().drivers.lock().unwrap();
        drivers.remove(&self.id);
    }
}

impl Driver {
    fn new(handle: &Handle) -> io::Result<Driver> {
        Ok(Driver {
            id: handle.id(),
            wakeup: try!(PollEvented::new(EventedReceiver, handle)),
        })
    }

    /// Drain all data in the global receiver, returning whether data was to be
    /// had.
    ///
    /// If this function returns `true` then some signal has been received since
    /// we last checked, otherwise `false` indicates that no signal has been
    /// received.
    fn drain(&mut self) -> bool {
        let mut received = false;
        loop {
            match self.wakeup.read(&mut [0; 128]) {
                Ok(0) => panic!("EOF on self-pipe"),
                Ok(_) => received = true,
                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => break,
                Err(e) => panic!("Bad read on self-pipe: {}", e),
            }
        }
        received
    }

    /// Go through all the signals and broadcast everything.
    ///
    /// Driver tasks wake up for *any* signal and simply process all globally
    /// registered signal streams, so each task is sort of cooperatively working
    /// for all the rest as well.
    fn broadcast(&self) {
        for (sig, slot) in globals().signals.iter().enumerate() {
            // Any signal of this kind arrived since we checked last?
            if !slot.pending.swap(false, Ordering::SeqCst) {
                continue
            }

            let signum = sig as c_int;
            let mut recipients = slot.recipients.lock().unwrap();

            // Notify all waiters on this signal that the signal has been
            // received. If we can't push a message into the queue then we don't
            // worry about it as everything is coalesced anyway. If the channel
            // has gone away then we can remove that slot.
            for i in (0..recipients.len()).rev() {
                // TODO: This thing probably generates unnecessary wakups of
                //       this task. But let's optimise it later on, when we
                //       know this works.
                match recipients[i].1.start_send(signum) {
                    Ok(AsyncSink::Ready) => {}
                    Ok(AsyncSink::NotReady(_)) => {}
                    Err(_) => { recipients.swap_remove(i); }
                }
            }
        }
    }
}

/// An implementation of `Stream` for receiving a particular type of signal.
///
/// This structure implements the `Stream` trait and represents notifications
/// of the current process receiving a particular signal. The signal being
/// listened for is passed to `Signal::new`, and the same signal number is then
/// yielded as each element for the stream.
///
/// In general signal handling on Unix is a pretty tricky topic, and this
/// structure is no exception! There are some important limitations to keep in
/// mind when using `Signal` streams:
///
/// * Signals handling in Unix already necessitates coalescing signals
///   together sometimes. This `Signal` stream is also no exception here in
///   that it will also coalesce signals. That is, even if the signal handler
///   for this process runs multiple times, the `Signal` stream may only return
///   one signal notification. Specifically, before `poll` is called, all
///   signal notifications are coalesced into one item returned from `poll`.
///   Once `poll` has been called, however, a further signal is guaranteed to
///   be yielded as an item.
///
///   Put another way, any element pulled off the returned stream corresponds to
///   *at least one* signal, but possibly more.
///
/// * Signal handling in general is relatively inefficient. Although some
///   improvements are possible in this crate, it's recommended to not plan on
///   having millions of signal channels open.
///
/// * Currently the "driver task" to process incoming signals never exits. This
///   driver task runs in the background of the event loop provided, and
///   in general you shouldn't need to worry about it.
///
/// If you've got any questions about this feel free to open an issue on the
/// repo, though, as I'd love to chat about this! In other words, I'd love to
/// alleviate some of these limitations if possible!
pub struct Signal {
    signal: c_int,
    token: usize,
    rx: Receiver<c_int>,
}

impl Signal {
    /// Creates a new stream which will receive notifications when the current
    /// process receives the signal `signal`.
    ///
    /// This function will create a new stream which may be based on the
    /// event loop handle provided. This function returns a future which will
    /// then resolve to the signal stream, if successful.
    ///
    /// The `Signal` stream is an infinite stream which will receive
    /// notifications whenever a signal is received. More documentation can be
    /// found on `Signal` itself, but to reiterate:
    ///
    /// * Signals may be coalesced beyond what the kernel already does.
    /// * Once a signal handler is registered with the process the underlying
    ///   libc signal handler is never unregistered.
    ///
    /// A `Signal` stream can be created for a particular signal number
    /// multiple times. When a signal is received then all the associated
    /// channels will receive the signal notification.
    pub fn new(signal: c_int, handle: &Handle) -> IoFuture<Signal> {
        static TOKENS: AtomicUsize = ATOMIC_USIZE_INIT;

        let result = (|| {
            // Turn the signal delivery on once we are ready for it
            try!(signal_enable(signal));

            // Ensure there's a driver for our associated event loop processing
            // signals.
            let id = handle.id();
            let mut drivers = globals().drivers.lock().unwrap();
            if !drivers.contains(&id) {
                handle.spawn(try!(Driver::new(handle)));
                drivers.insert(id);
            }
            drop(drivers);

            // One wakeup in a queue is enough, no need for us to buffer up any
            // more.
            let (tx, rx) = channel(1);
            let token = TOKENS.fetch_add(1, Ordering::SeqCst);
            let idx = signal as usize;
            globals().signals[idx].recipients.lock().unwrap().push((token, tx));
            Ok(Signal {
                rx: rx,
                token: token,
                signal: signal,
            })
        })();

        future::result(result).boxed()
    }
}

impl Stream for Signal {
    type Item = c_int;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<c_int>, io::Error> {
        // receivers don't generate errors
        self.rx.poll().map_err(|_| panic!())
    }
}

impl Drop for Signal {
    fn drop(&mut self) {
        let idx = self.signal as usize;
        let mut list = globals().signals[idx].recipients.lock().unwrap();
        list.retain(|pair| pair.0 != self.token);
    }
}
<commit_msg>signal: Clarify a comment<commit_after>//! Unix-specific types for signal handling.
//!
//! This module is only defined on Unix platforms and contains the primary
//! `Signal` type for receiving notifications of signals.

#![cfg(unix)]

pub extern crate libc;
extern crate mio;
extern crate mio_uds;

use std::cell::UnsafeCell;
use std::collections::HashSet;
use std::io::prelude::*;
use std::io;
use std::mem;
use std::os::unix::prelude::*;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::sync::{Mutex, Once, ONCE_INIT};

use futures::future;
use futures::sync::mpsc::{Receiver, Sender, channel};
use futures::{Async, AsyncSink, Future};
use futures::{Sink, Stream, Poll};
use self::libc::c_int;
use self::mio::Poll as MioPoll;
use self::mio::unix::EventedFd;
use self::mio::{Evented, Token, Ready, PollOpt};
use self::mio_uds::UnixStream;
use tokio_core::io::IoFuture;
use tokio_core::reactor::{Handle, CoreId, PollEvented};

pub use self::libc::{SIGINT, SIGTERM, SIGUSR1, SIGUSR2};
pub use self::libc::{SIGHUP, SIGQUIT, SIGPIPE, SIGALRM, SIGTRAP};

// Number of different unix signals
const SIGNUM: usize = 32;

struct SignalInfo {
    pending: AtomicBool,
    // The ones interested in this signal
    recipients: Mutex<Vec<(usize, Sender<c_int>)>>,

	init: Once,
    initialized: UnsafeCell<bool>,
    prev: UnsafeCell<libc::sigaction>,
}

struct Globals {
    sender: UnixStream,
    receiver: UnixStream,
    signals: [SignalInfo; SIGNUM],
    drivers: Mutex<HashSet<CoreId>>,
}

impl Default for SignalInfo {
    fn default() -> SignalInfo {
        SignalInfo {
            pending: AtomicBool::new(false),
            init: ONCE_INIT,
            initialized: UnsafeCell::new(false),
            recipients: Mutex::new(Vec::new()),
            prev: UnsafeCell::new(unsafe { mem::zeroed() }),
        }
    }
}

static mut GLOBALS: *mut Globals = 0 as *mut Globals;

fn globals() -> &'static Globals {
    static INIT: Once = ONCE_INIT;

    unsafe {
        INIT.call_once(|| {
            let (receiver, sender) = UnixStream::pair().unwrap();
            let globals = Globals {
                sender: sender,
                receiver: receiver,
                signals: Default::default(),
                drivers: Mutex::new(HashSet::new()),
            };
            GLOBALS = Box::into_raw(Box::new(globals));
        });
        &*GLOBALS
    }
}

/// Our global signal handler for all signals registered by this module.
///
/// The purpose of this signal handler is to primarily:
///
/// 1. Flag that our specific signal was received (e.g. store an atomic flag)
/// 2. Wake up driver tasks by writing a byte to a pipe
///
/// Those two operations shoudl both be async-signal safe. After that's done we
/// just try to call a previous signal handler, if any, to be "good denizens of
/// the internet"
extern fn handler(signum: c_int,
                  info: *mut libc::siginfo_t,
                  ptr: *mut libc::c_void) {
	type FnSigaction = extern fn(c_int, *mut libc::siginfo_t, *mut libc::c_void);
	type FnHandler = extern fn(c_int);
    unsafe {
        let slot = match (*GLOBALS).signals.get(signum as usize) {
            Some(slot) => slot,
            None => return,
        };
        slot.pending.store(true, Ordering::SeqCst);

        // Send a wakeup, ignore any errors (anything reasonably possible is
        // full pipe and then it will wake up anyway).
        drop((*GLOBALS).sender.write(&[1]));

        let fnptr = (*slot.prev.get()).sa_sigaction;
        if fnptr == 0 || fnptr == libc::SIG_DFL || fnptr == libc::SIG_IGN {
            return
        }
        if (*slot.prev.get()).sa_flags & libc::SA_SIGINFO == 0 {
            let action = mem::transmute::<usize, FnHandler>(fnptr);
            action(signum)
        } else {
            let action = mem::transmute::<usize, FnSigaction>(fnptr);
            action(signum, info, ptr)
        }
    }
}

/// Enable this module to receive signal notifications for the `signal`
/// provided.
///
/// This will register the signal handler if it hasn't already been registered,
/// returning any error along the way if that fails.
fn signal_enable(signal: c_int) -> io::Result<()> {
    let siginfo = match globals().signals.get(signal as usize) {
        Some(slot) => slot,
        None => {
            return Err(io::Error::new(io::ErrorKind::Other, "signal too large"))
        }
    };
	unsafe {
        let mut err = None;
        siginfo.init.call_once(|| {
            let mut new: libc::sigaction = mem::zeroed();
            new.sa_sigaction = handler as usize;
            new.sa_flags = libc::SA_RESTART |
                            libc::SA_SIGINFO |
                            libc::SA_NOCLDSTOP;
            if libc::sigaction(signal, &new, &mut *siginfo.prev.get()) != 0 {
                err = Some(io::Error::last_os_error());
            } else {
                *siginfo.initialized.get() = true;
            }
        });
        if let Some(err) = err {
            return Err(err)
        }
        if *siginfo.initialized.get() {
            Ok(())
        } else {
            Err(io::Error::new(io::ErrorKind::Other,
                               "failed to register signal handler"))
        }
	}
}

/// A helper struct to register our global receiving end of the signal pipe on
/// multiple event loops.
///
/// This structure represents registering the receiving end on all event loops,
/// and uses `EventedFd` in mio to do so. It's stored in each driver task and is
/// used to read data and register interest in new signals coming in.
struct EventedReceiver;

impl Evented for EventedReceiver {
    fn register(&self, poll: &MioPoll, token: Token, events: Ready, opts: PollOpt) -> io::Result<()> {
        let fd = globals().receiver.as_raw_fd();
        EventedFd(&fd).register(poll, token, events, opts)
    }
    fn reregister(&self, poll: &MioPoll, token: Token, events: Ready, opts: PollOpt) -> io::Result<()> {
        let fd = globals().receiver.as_raw_fd();
        EventedFd(&fd).reregister(poll, token, events, opts)
    }
    fn deregister(&self, poll: &MioPoll) -> io::Result<()> {
        let fd = globals().receiver.as_raw_fd();
        EventedFd(&fd).deregister(poll)
    }
}

impl Read for EventedReceiver {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (&globals().receiver).read(buf)
    }
}

struct Driver {
    id: CoreId,
    wakeup: PollEvented<EventedReceiver>,
}

impl Future for Driver {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        // Drain the data from the pipe and maintain interest in getting more
        let any_wakeup = self.drain();
        if any_wakeup {
            self.broadcast();
        }
        // This task just lives until the end of the event loop
        Ok(Async::NotReady)
    }
}

impl Drop for Driver {
    fn drop(&mut self) {
        let mut drivers = globals().drivers.lock().unwrap();
        drivers.remove(&self.id);
    }
}

impl Driver {
    fn new(handle: &Handle) -> io::Result<Driver> {
        Ok(Driver {
            id: handle.id(),
            wakeup: try!(PollEvented::new(EventedReceiver, handle)),
        })
    }

    /// Drain all data in the global receiver, returning whether data was to be
    /// had.
    ///
    /// If this function returns `true` then some signal has been received since
    /// we last checked, otherwise `false` indicates that no signal has been
    /// received.
    fn drain(&mut self) -> bool {
        let mut received = false;
        loop {
            match self.wakeup.read(&mut [0; 128]) {
                Ok(0) => panic!("EOF on self-pipe"),
                Ok(_) => received = true,
                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => break,
                Err(e) => panic!("Bad read on self-pipe: {}", e),
            }
        }
        received
    }

    /// Go through all the signals and broadcast everything.
    ///
    /// Driver tasks wake up for *any* signal and simply process all globally
    /// registered signal streams, so each task is sort of cooperatively working
    /// for all the rest as well.
    fn broadcast(&self) {
        for (sig, slot) in globals().signals.iter().enumerate() {
            // Any signal of this kind arrived since we checked last?
            if !slot.pending.swap(false, Ordering::SeqCst) {
                continue
            }

            let signum = sig as c_int;
            let mut recipients = slot.recipients.lock().unwrap();

            // Notify all waiters on this signal that the signal has been
            // received. If we can't push a message into the queue then we don't
            // worry about it as everything is coalesced anyway. If the channel
            // has gone away then we can remove that slot.
            for i in (0..recipients.len()).rev() {
                // TODO: This thing probably generates unnecessary wakups of
                //       this task when `NotReady` is received because we don't
                //       actually want to get woken up to continue sending a
                //       message. Let's optimise it later on though, as we know
                //       this works.
                match recipients[i].1.start_send(signum) {
                    Ok(AsyncSink::Ready) => {}
                    Ok(AsyncSink::NotReady(_)) => {}
                    Err(_) => { recipients.swap_remove(i); }
                }
            }
        }
    }
}

/// An implementation of `Stream` for receiving a particular type of signal.
///
/// This structure implements the `Stream` trait and represents notifications
/// of the current process receiving a particular signal. The signal being
/// listened for is passed to `Signal::new`, and the same signal number is then
/// yielded as each element for the stream.
///
/// In general signal handling on Unix is a pretty tricky topic, and this
/// structure is no exception! There are some important limitations to keep in
/// mind when using `Signal` streams:
///
/// * Signals handling in Unix already necessitates coalescing signals
///   together sometimes. This `Signal` stream is also no exception here in
///   that it will also coalesce signals. That is, even if the signal handler
///   for this process runs multiple times, the `Signal` stream may only return
///   one signal notification. Specifically, before `poll` is called, all
///   signal notifications are coalesced into one item returned from `poll`.
///   Once `poll` has been called, however, a further signal is guaranteed to
///   be yielded as an item.
///
///   Put another way, any element pulled off the returned stream corresponds to
///   *at least one* signal, but possibly more.
///
/// * Signal handling in general is relatively inefficient. Although some
///   improvements are possible in this crate, it's recommended to not plan on
///   having millions of signal channels open.
///
/// * Currently the "driver task" to process incoming signals never exits. This
///   driver task runs in the background of the event loop provided, and
///   in general you shouldn't need to worry about it.
///
/// If you've got any questions about this feel free to open an issue on the
/// repo, though, as I'd love to chat about this! In other words, I'd love to
/// alleviate some of these limitations if possible!
pub struct Signal {
    signal: c_int,
    token: usize,
    rx: Receiver<c_int>,
}

impl Signal {
    /// Creates a new stream which will receive notifications when the current
    /// process receives the signal `signal`.
    ///
    /// This function will create a new stream which may be based on the
    /// event loop handle provided. This function returns a future which will
    /// then resolve to the signal stream, if successful.
    ///
    /// The `Signal` stream is an infinite stream which will receive
    /// notifications whenever a signal is received. More documentation can be
    /// found on `Signal` itself, but to reiterate:
    ///
    /// * Signals may be coalesced beyond what the kernel already does.
    /// * Once a signal handler is registered with the process the underlying
    ///   libc signal handler is never unregistered.
    ///
    /// A `Signal` stream can be created for a particular signal number
    /// multiple times. When a signal is received then all the associated
    /// channels will receive the signal notification.
    pub fn new(signal: c_int, handle: &Handle) -> IoFuture<Signal> {
        static TOKENS: AtomicUsize = ATOMIC_USIZE_INIT;

        let result = (|| {
            // Turn the signal delivery on once we are ready for it
            try!(signal_enable(signal));

            // Ensure there's a driver for our associated event loop processing
            // signals.
            let id = handle.id();
            let mut drivers = globals().drivers.lock().unwrap();
            if !drivers.contains(&id) {
                handle.spawn(try!(Driver::new(handle)));
                drivers.insert(id);
            }
            drop(drivers);

            // One wakeup in a queue is enough, no need for us to buffer up any
            // more.
            let (tx, rx) = channel(1);
            let token = TOKENS.fetch_add(1, Ordering::SeqCst);
            let idx = signal as usize;
            globals().signals[idx].recipients.lock().unwrap().push((token, tx));
            Ok(Signal {
                rx: rx,
                token: token,
                signal: signal,
            })
        })();

        future::result(result).boxed()
    }
}

impl Stream for Signal {
    type Item = c_int;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<c_int>, io::Error> {
        // receivers don't generate errors
        self.rx.poll().map_err(|_| panic!())
    }
}

impl Drop for Signal {
    fn drop(&mut self) {
        let idx = self.signal as usize;
        let mut list = globals().signals[idx].recipients.lock().unwrap();
        list.retain(|pair| pair.0 != self.token);
    }
}
<|endoftext|>


<commit_before>//#![feature(trace_macros)]

#[macro_use]
extern crate nom;

use nom::{digit, alphanumeric};

use std::str::{self, FromStr};
use std::collections::HashMap;

#[derive(Debug, PartialEq)]
pub enum JsonValue {
  Str(String),
  Num(f32),
  Array(Vec<JsonValue>),
  Object(HashMap<String, JsonValue>),
}

// FIXME: since we already parsed a serie of digits and dots,
// we know it is correct UTF-8. no need to use from_utf8 to
// verify it is correct
// FIXME: use alt_complete (implement ws for alt_complete)
named!(unsigned_float <f32>, map_res!(
  map_res!(
    recognize!(
      alt_complete!(
        delimited!(digit, tag!("."), opt!(complete!(digit))) |
        delimited!(opt!(digit), tag!("."), digit)            |
        digit
      )
    ),
    str::from_utf8
  ),
  FromStr::from_str
));
named!(float<f32>, map!(
  pair!(
    opt!(alt!(tag!("+") | tag!("-"))),
    unsigned_float
  ),
  |(sign, value): (Option<&[u8]>, f32)| {
    sign.and_then(|s| if s[0] == (b'-') { Some(-1f32) } else { None }).unwrap_or(1f32) * value
  }
));

//FIXME: verify how json strings are formatted
named!(string<&str>,
  delimited!(
    tag!("\""),
    map_res!(escaped!(call!(alphanumeric), '\\', is_a!("\"n\\")), str::from_utf8),
    tag!("\"")
  )
);

named!(array < Vec<JsonValue> >,
  ws!(
    delimited!(
      tag!("["),
      separated_list!(tag!(","), value),
      tag!("]")
    )
  )
);

named!(key_value<(&str,JsonValue)>,
  ws!(
    separated_pair!(
      string,
      tag!(":"),
      value
    )
  )
);

named!(hash< HashMap<String,JsonValue> >,
  ws!(
    map!(
      delimited!(
        tag!("{"),
        separated_list!(tag!(","), key_value),
        tag!("}")
        ),
      |tuple_vec| {
        let mut h: HashMap<String, JsonValue> = HashMap::new();
        for (k, v) in tuple_vec {
          h.insert(String::from(k), v);
        }
        h
      }
    )
  )
);

named!(value<JsonValue>,
  ws!(
    alt!(
      hash   => { |h|   JsonValue::Object(h)            } |
      array  => { |v|   JsonValue::Array(v)             } |
      string => { |s|   JsonValue::Str(String::from(s)) } |
      float  => { |num| JsonValue::Num(num)             }
    )
  )
);

#[test]
fn hash_test() {
  let test = &b"  { \"a\"\t: 42,
  \"b\": \"x\"
  }";

  //FIXME: top level value must be an object?
  println!("{:?}", value(&test[..]));
  //assert!(false);
}

#[test]
fn parse_example_test() {
  let test = &b"  { \"a\"\t: 42,
  \"b\": [ \"x\", \"y\", 12 ] ,
  \"c\": { \"hello\" : \"world\"
  }
  }";

  //FIXME: top level value must be an object?
  println!("{:?}", value(&test[..]));
  //assert!(false);
}
<commit_msg>more accurate json test<commit_after>//#![feature(trace_macros)]

#[macro_use]
extern crate nom;

use nom::{digit, is_alphanumeric, alphanumeric, space, recognize_float};

use std::str::{self, FromStr};
use std::collections::HashMap;

#[derive(Debug, PartialEq)]
pub enum JsonValue {
  Str(String),
  Num(f32),
  Array(Vec<JsonValue>),
  Object(HashMap<String, JsonValue>),
}

named!(float<f32>,
  flat_map!(recognize_float, parse_to!(f32))
);

//FIXME: verify how json strings are formatted
named!(string<&str>,
  delimited!(
    tag!("\""),
    //map_res!(escaped!(call!(alphanumeric), '\\', is_a!("\"n\\")), str::from_utf8),
    map_res!(escaped!(take_while1!(is_alphanumeric), '\\', one_of!("\"n\\")), str::from_utf8),
    tag!("\"")
  )
);

named!(array < Vec<JsonValue> >,
  ws!(
    delimited!(
      tag!("["),
      separated_list!(tag!(","), value),
      tag!("]")
    )
  )
);

named!(key_value<(&str,JsonValue)>,
  ws!(
    separated_pair!(
      string,
      tag!(":"),
      value
    )
  )
);

named!(hash< HashMap<String,JsonValue> >,
  ws!(
    map!(
      delimited!(
        tag!("{"),
        separated_list!(tag!(","), key_value),
        tag!("}")
        ),
      |tuple_vec| {
        let mut h: HashMap<String, JsonValue> = HashMap::new();
        for (k, v) in tuple_vec {
          h.insert(String::from(k), v);
        }
        h
      }
    )
  )
);

named!(value<JsonValue>,
  ws!(
    alt!(
      dbg_dmp!(hash)   => { |h|   JsonValue::Object(h)            } |
      dbg_dmp!(array)  => { |v|   JsonValue::Array(v)             } |
      dbg_dmp!(string) => { |s|   JsonValue::Str(String::from(s)) } |
      dbg_dmp!(float)  => { |num| JsonValue::Num(num)             }
    )
  )
);

#[test]
fn hash_test() {
  let test = &b"  { \"a\"\t: 42,
  \"b\": \"x\"
  }\0";

  //FIXME: top level value must be an object?
  println!("{:?}", value(&test[..]).unwrap());
  //assert!(false);
}

#[test]
fn parse_example_test() {
  let test = &b"  { \"a\"\t: 42,
  \"b\": [ \"x\", \"y\", 12 ] ,
  \"c\": { \"hello\" : \"world\"
  }
  }\0";

  //FIXME: top level value must be an object?
  println!("{:?}", value(&test[..]).unwrap());
  //assert!(false);
}
<|endoftext|>


<commit_before>extern crate funzzy;
mod cli;

fn new_args() -> funzzy::cli::Args {
    funzzy::cli::Args {
        cmd_init: false,
        cmd_watch: false,
        arg_command: vec![String::new()],
        flag_c: false,
        flag_h: false,
        flag_v: false,
    }
}

#[test]
fn it_returns_some_command() {
   let mut args = new_args();
   args.cmd_init = true;
   assert!(funzzy::cli::command(&args).is_some())
}

#[test]
fn it_as_default_returns_watch_command() {
   let args = new_args();
   assert!(funzzy::cli::command(&args).is_some());
}

#[test]
fn it_returns_watch_command() {
   let mut args = new_args();
   args.cmd_watch = true;
   assert!(funzzy::cli::command(&args).is_some())
}

#[test]
fn it_returns_watch_command_with_arbitrary_command() {
   let mut args = new_args();
   args.cmd_watch = true;
   args.flag_c = true;
   args.arg_command = vec![String::from("cargo build")];
   assert!(funzzy::cli::command(&args).is_some())
}
<commit_msg>tests: adding new verbose arg<commit_after>extern crate funzzy;
mod cli;

fn new_args() -> funzzy::cli::Args {
    funzzy::cli::Args {
        cmd_init: false,
        cmd_watch: false,
        arg_command: vec![String::new()],
        flag_c: false,
        flag_h: false,
        flag_v: false,
        flag_vb: false,
    }
}

#[test]
fn it_returns_some_command() {
   let mut args = new_args();
   args.cmd_init = true;
   assert!(funzzy::cli::command(&args).is_some())
}

#[test]
fn it_as_default_returns_watch_command() {
   let args = new_args();
   assert!(funzzy::cli::command(&args).is_some());
}

#[test]
fn it_returns_watch_command() {
   let mut args = new_args();
   args.cmd_watch = true;
   assert!(funzzy::cli::command(&args).is_some())
}

#[test]
fn it_returns_watch_command_with_arbitrary_command() {
   let mut args = new_args();
   args.cmd_watch = true;
   args.flag_c = true;
   args.arg_command = vec![String::from("cargo build")];
   assert!(funzzy::cli::command(&args).is_some())
}
<|endoftext|>


<commit_before>use std::cell::{Cell, RefCell};
use std::io::{Read, Seek, SeekFrom, ErrorKind, Result, Error};
use std::fs::File;
use std::str;

extern crate positioned_io;
extern crate byteorder;
use self::byteorder::LittleEndian;

use positioned_io::{ReadAt, WriteAt, Size, Cursor, SizeCursor, ByteIo, Slice};

#[test]
fn test_read_at() {
    let file = File::open("Cargo.toml").unwrap();
    let mut buf = [0; 4];
    file.read_exact_at(10, buf.as_mut()).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!(s, "name");
}

// A ReadAt that has weird behavior.
struct ReadCustom<I: ReadAt, F: Fn() -> Result<usize>> {
    i: I,
    fail: Cell<bool>,
    onfail: F,
}
impl<I: ReadAt, F: Fn() -> Result<usize>> ReadCustom<I, F> {
    fn new(i: I, f: F) -> Self {
        ReadCustom {
            i: i,
            fail: Cell::new(true),
            onfail: f,
        }
    }
}
impl<I: ReadAt, F: Fn() -> Result<usize>> ReadAt for ReadCustom<I, F> {
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> Result<usize> {
        let fail = self.fail.get();
        self.fail.set(!fail);
        if fail {
            (self.onfail)()
        } else {
            self.i.read_at(pos, buf)
        }
    }
}

#[test]
fn test_read_fails() {
    // Test interrupts.
    let file = File::open("Cargo.toml").unwrap();
    let mut buf = [0; 4];
    {
        let interrupt = ReadCustom::new(&file,
                                    || Err(Error::new(ErrorKind::Interrupted, "interrupt!")));
        interrupt.read_exact_at(10, buf.as_mut()).unwrap();
        let s = str::from_utf8(buf.as_ref()).unwrap();
        assert_eq!(s, "name");
    }

    // Test errors.
    {
        let fail = ReadCustom::new(&file, || Err(Error::new(ErrorKind::Other, "random fail")));
        assert!(fail.read_exact_at(10, buf.as_mut()).is_err());
    }

    // Test EOF.
    assert!(file.read_exact_at(10000, buf.as_mut()).is_err());
}

#[test]
fn test_size() {
    let file = File::open("Cargo.toml").unwrap();
    let size = file.size().unwrap().unwrap();
    assert!(size > 0);
}

#[test]
fn test_cursor() {
    let file = File::open("Cargo.toml").unwrap();
    let mut curs = Cursor::new_pos(file, 10);
    let mut buf = [0; 4];
    {
        curs.read_exact(&mut buf).unwrap();
        let s = str::from_utf8(buf.as_ref()).unwrap();
        assert_eq!("name", s);
    }
    curs.seek(SeekFrom::Current(4)).unwrap();
    curs.read_exact(&mut buf).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!("posi", s);
}

#[test]
fn test_size_cursor() {
    let file = File::open("Cargo.toml").unwrap();
    let mut curs = SizeCursor::new_pos(file, 10);
    let mut buf = [0; 4];
    curs.seek(SeekFrom::End(-2)).unwrap();
    assert_eq!(2, curs.read(&mut buf).unwrap());
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert!(s.contains("\n"));
}

#[test]
fn test_byteio() {
    let file = File::open("Cargo.toml").unwrap();
    let io: ByteIo<_, LittleEndian> = ByteIo::new(file);
    let r = io.read_i32_at(3).unwrap();
    assert_eq!(0x67616b63, r);
}

#[test]
fn test_vector() {
    // Write past the end.
    let mut v = vec![0, 1, 2, 3];
    let buf = [4, 5, 6, 7];
    (&mut v).write_all_at(2, &buf).unwrap();
    assert_eq!(vec![0, 1, 4, 5, 6, 7], v);
}

#[test]
fn test_slice() {
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        // Read too much, limited by size.
        let mut buf = [9; 4];
        let slice = Slice::new(&mut v, 2, Some(3));
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 1);
        assert_eq!(buf, [4, 9, 9, 9]);

        // Read too much, limited by buf
        let mut buf = [9; 2];
        let bytes = slice.read_at(1, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [3, 4]);
    }

    {
        // Read too much, limited by original vec.
        let slice = Slice::new(&mut v, 2, Some(5));
        let mut buf = [9; 6];
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [4, 5, 9, 9, 9, 9]);
    }

    {
        // Read too much of unsized slice.
        let slice = Slice::new(&mut v, 2, None);
        let mut buf = [9; 6];
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [4, 5, 9, 9, 9, 9]);
    }

    // Interleaved read/write to same slice.
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        let mut slice = Slice::new(&mut v, 2, Some(3));
        let mut buf = [9; 3];
        {
            let bytes = slice.write_at(2, &buf).unwrap();
            assert_eq!(bytes, 1);
        }
        {
            let bytes = slice.read_at(1, &mut buf).unwrap();
            assert_eq!(bytes, 2);
        }
        assert_eq!(buf, [3, 9, 9]);
        {
            let bytes = slice.write_at(0, &buf[..1]).unwrap();
            assert_eq!(bytes, 1);
        }
    }
    assert_eq!(v, vec![0, 1, 3, 3, 9, 5]);

    // Write past end.
    let mut v = vec![0, 1, 2, 3];
    let buf = [9; 6];
    // Limited by size.
    {
        let mut slice = Slice::new(&mut v, 2, Some(5));
        let bytes = slice.write_at(1, &buf).unwrap();
        assert_eq!(bytes, 4);
    }
    assert_eq!(v, vec![0, 1, 2, 9, 9, 9, 9]);
    // No size.
    {
        let mut slice = Slice::new(&mut v, 2, None);
        let bytes = slice.write_at(1, &buf).unwrap();
        assert_eq!(bytes, 6);
    }
    assert_eq!(v, vec![0, 1, 2, 9, 9, 9, 9, 9, 9]);

    // Automatic-size constructor.
    let mut v = vec![0, 1, 2, 3];
    {
        let mut slice = Slice::new_to_end(&mut v, 1).unwrap();
        assert_eq!(slice.size().unwrap().unwrap(), 3);
        let bytes = slice.write_at(0, &buf).unwrap();
        assert_eq!(bytes, 3);
    }
    assert_eq!(v, vec![0, 9, 9, 9]);

    // Slice of slice.
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        let mut slice1 = Slice::new(&mut v, 1, Some(4));
        let mut slice2 = Slice::new(&mut slice1, 1, Some(2));
        let bytes = slice2.write_at(0, &buf).unwrap();
        assert_eq!(bytes, 2);
    }
    assert_eq!(v, vec![0, 1, 9, 9, 4, 5]);
}

#[test]
fn test_refcell() {
    let mut buf = [0; 3];

    // Make sure we can instantiate a bunch of combinations.
    let mut a = [0, 1, 2, 3];
    a.as_ref().read_at(0, &mut buf).unwrap();
    a.as_mut().write_at(0, &buf).unwrap();

    let mut v = vec![0, 1, 2, 3];
    v.read_at(0, &mut buf).unwrap();
    v.write_at(0, &buf).unwrap();

    let mut ra = &RefCell::new(a.as_mut());
    ra.read_at(0, &mut buf).unwrap();
    ra.write_at(0, &buf).unwrap();

    let mut rv = &RefCell::new(&mut v);
    rv.read_at(0, &mut buf).unwrap();
    rv.write_at(0, &buf).unwrap();

    // Test writing but still being able to use, thanks to RefCell.
    let mut v = vec![0, 1, 2, 3];
    let mut rv = &RefCell::new(&mut v);
    let buf = [9; 4];
    rv.write_at(0, &buf).unwrap();
    assert_eq!(*rv.borrow(), &vec![9; 4]);
}
<commit_msg>test mixed positioned and moving read<commit_after>use std::cell::{Cell, RefCell};
use std::io::{Read, Seek, SeekFrom, ErrorKind, Result, Error};
use std::fs::File;
use std::str;

extern crate positioned_io;
extern crate byteorder;
use self::byteorder::LittleEndian;

use positioned_io::{ReadAt, WriteAt, Size, Cursor, SizeCursor, ByteIo, Slice};

#[test]
fn test_read_at() {
    let file = File::open("Cargo.toml").unwrap();
    let mut buf = [0; 4];
    file.read_exact_at(10, buf.as_mut()).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!(s, "name");
}

#[test]
fn test_read_position() {
    let mut file = File::open("tests/pi.txt").unwrap();
    let mut buf = [0; 4];
    file.read_exact(&mut buf[..]).unwrap();
    assert_eq!(&buf, b"3.14");
    file.read_exact_at(0, &mut buf[..]).unwrap();
    assert_eq!(&buf, b"3.14");
    file.read_exact(&mut buf[..]).unwrap();
    assert_eq!(&buf, b"1592");
}

// A ReadAt that has weird behavior.
struct ReadCustom<I: ReadAt, F: Fn() -> Result<usize>> {
    i: I,
    fail: Cell<bool>,
    onfail: F,
}
impl<I: ReadAt, F: Fn() -> Result<usize>> ReadCustom<I, F> {
    fn new(i: I, f: F) -> Self {
        ReadCustom {
            i: i,
            fail: Cell::new(true),
            onfail: f,
        }
    }
}
impl<I: ReadAt, F: Fn() -> Result<usize>> ReadAt for ReadCustom<I, F> {
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> Result<usize> {
        let fail = self.fail.get();
        self.fail.set(!fail);
        if fail {
            (self.onfail)()
        } else {
            self.i.read_at(pos, buf)
        }
    }
}

#[test]
fn test_read_fails() {
    // Test interrupts.
    let file = File::open("Cargo.toml").unwrap();
    let mut buf = [0; 4];
    {
        let interrupt = ReadCustom::new(&file,
                                    || Err(Error::new(ErrorKind::Interrupted, "interrupt!")));
        interrupt.read_exact_at(10, buf.as_mut()).unwrap();
        let s = str::from_utf8(buf.as_ref()).unwrap();
        assert_eq!(s, "name");
    }

    // Test errors.
    {
        let fail = ReadCustom::new(&file, || Err(Error::new(ErrorKind::Other, "random fail")));
        assert!(fail.read_exact_at(10, buf.as_mut()).is_err());
    }

    // Test EOF.
    assert!(file.read_exact_at(10000, buf.as_mut()).is_err());
}

#[test]
fn test_size() {
    let file = File::open("Cargo.toml").unwrap();
    let size = file.size().unwrap().unwrap();
    assert!(size > 0);
}

#[test]
fn test_cursor() {
    let file = File::open("Cargo.toml").unwrap();
    let mut curs = Cursor::new_pos(file, 10);
    let mut buf = [0; 4];
    {
        curs.read_exact(&mut buf).unwrap();
        let s = str::from_utf8(buf.as_ref()).unwrap();
        assert_eq!("name", s);
    }
    curs.seek(SeekFrom::Current(4)).unwrap();
    curs.read_exact(&mut buf).unwrap();
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert_eq!("posi", s);
}

#[test]
fn test_size_cursor() {
    let file = File::open("Cargo.toml").unwrap();
    let mut curs = SizeCursor::new_pos(file, 10);
    let mut buf = [0; 4];
    curs.seek(SeekFrom::End(-2)).unwrap();
    assert_eq!(2, curs.read(&mut buf).unwrap());
    let s = str::from_utf8(buf.as_ref()).unwrap();
    assert!(s.contains("\n"));
}

#[test]
fn test_byteio() {
    let file = File::open("Cargo.toml").unwrap();
    let io: ByteIo<_, LittleEndian> = ByteIo::new(file);
    let r = io.read_i32_at(3).unwrap();
    assert_eq!(0x67616b63, r);
}

#[test]
fn test_vector() {
    // Write past the end.
    let mut v = vec![0, 1, 2, 3];
    let buf = [4, 5, 6, 7];
    (&mut v).write_all_at(2, &buf).unwrap();
    assert_eq!(vec![0, 1, 4, 5, 6, 7], v);
}

#[test]
fn test_slice() {
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        // Read too much, limited by size.
        let mut buf = [9; 4];
        let slice = Slice::new(&mut v, 2, Some(3));
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 1);
        assert_eq!(buf, [4, 9, 9, 9]);

        // Read too much, limited by buf
        let mut buf = [9; 2];
        let bytes = slice.read_at(1, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [3, 4]);
    }

    {
        // Read too much, limited by original vec.
        let slice = Slice::new(&mut v, 2, Some(5));
        let mut buf = [9; 6];
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [4, 5, 9, 9, 9, 9]);
    }

    {
        // Read too much of unsized slice.
        let slice = Slice::new(&mut v, 2, None);
        let mut buf = [9; 6];
        let bytes = slice.read_at(2, &mut buf).unwrap();
        assert_eq!(bytes, 2);
        assert_eq!(buf, [4, 5, 9, 9, 9, 9]);
    }

    // Interleaved read/write to same slice.
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        let mut slice = Slice::new(&mut v, 2, Some(3));
        let mut buf = [9; 3];
        {
            let bytes = slice.write_at(2, &buf).unwrap();
            assert_eq!(bytes, 1);
        }
        {
            let bytes = slice.read_at(1, &mut buf).unwrap();
            assert_eq!(bytes, 2);
        }
        assert_eq!(buf, [3, 9, 9]);
        {
            let bytes = slice.write_at(0, &buf[..1]).unwrap();
            assert_eq!(bytes, 1);
        }
    }
    assert_eq!(v, vec![0, 1, 3, 3, 9, 5]);

    // Write past end.
    let mut v = vec![0, 1, 2, 3];
    let buf = [9; 6];
    // Limited by size.
    {
        let mut slice = Slice::new(&mut v, 2, Some(5));
        let bytes = slice.write_at(1, &buf).unwrap();
        assert_eq!(bytes, 4);
    }
    assert_eq!(v, vec![0, 1, 2, 9, 9, 9, 9]);
    // No size.
    {
        let mut slice = Slice::new(&mut v, 2, None);
        let bytes = slice.write_at(1, &buf).unwrap();
        assert_eq!(bytes, 6);
    }
    assert_eq!(v, vec![0, 1, 2, 9, 9, 9, 9, 9, 9]);

    // Automatic-size constructor.
    let mut v = vec![0, 1, 2, 3];
    {
        let mut slice = Slice::new_to_end(&mut v, 1).unwrap();
        assert_eq!(slice.size().unwrap().unwrap(), 3);
        let bytes = slice.write_at(0, &buf).unwrap();
        assert_eq!(bytes, 3);
    }
    assert_eq!(v, vec![0, 9, 9, 9]);

    // Slice of slice.
    let mut v = vec![0, 1, 2, 3, 4, 5];
    {
        let mut slice1 = Slice::new(&mut v, 1, Some(4));
        let mut slice2 = Slice::new(&mut slice1, 1, Some(2));
        let bytes = slice2.write_at(0, &buf).unwrap();
        assert_eq!(bytes, 2);
    }
    assert_eq!(v, vec![0, 1, 9, 9, 4, 5]);
}

#[test]
fn test_refcell() {
    let mut buf = [0; 3];

    // Make sure we can instantiate a bunch of combinations.
    let mut a = [0, 1, 2, 3];
    a.as_ref().read_at(0, &mut buf).unwrap();
    a.as_mut().write_at(0, &buf).unwrap();

    let mut v = vec![0, 1, 2, 3];
    v.read_at(0, &mut buf).unwrap();
    v.write_at(0, &buf).unwrap();

    let mut ra = &RefCell::new(a.as_mut());
    ra.read_at(0, &mut buf).unwrap();
    ra.write_at(0, &buf).unwrap();

    let mut rv = &RefCell::new(&mut v);
    rv.read_at(0, &mut buf).unwrap();
    rv.write_at(0, &buf).unwrap();

    // Test writing but still being able to use, thanks to RefCell.
    let mut v = vec![0, 1, 2, 3];
    let mut rv = &RefCell::new(&mut v);
    let buf = [9; 4];
    rv.write_at(0, &buf).unwrap();
    assert_eq!(*rv.borrow(), &vec![9; 4]);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;

lazy_static! {
    /// Documentation!
    pub static ref NUMBER: u32 = times_two(3);

    static ref ARRAY_BOXES: [Box<u32>; 3] = [Box::new(1), Box::new(2), Box::new(3)];

    /// More documentation!
    #[allow(unused_variables)]
    #[derive(Copy, Clone, Debug)]
    pub static ref STRING: String = "hello".to_string();

    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "abc");
        m.insert(1, "def");
        m.insert(2, "ghi");
        m
    };

    // This should not compile if the unsafe is removed.
    static ref UNSAFE: u32 = unsafe {
        std::mem::transmute::<i32, u32>(-1)
    };
}

lazy_static! {
    static ref S1: &'static str = "a";
    static ref S2: &'static str = "b";
}
lazy_static! {
    static ref S3: String = [*S1, *S2].join("");
}

#[test]
fn s3() {
    assert_eq!(&*S3, "ab");
}

fn times_two(n: u32) -> u32 {
    n * 2
}

#[test]
fn test_basic() {
    assert_eq!(&**STRING, "hello");
    assert_eq!(*NUMBER, 6);
    assert!(HASHMAP.get(&1).is_some());
    assert!(HASHMAP.get(&3).is_none());
    assert_eq!(&*ARRAY_BOXES, &[Box::new(1), Box::new(2), Box::new(3)]);
    assert_eq!(*UNSAFE, std::u32::MAX);
}

#[test]
fn test_repeat() {
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
}

#[test]
fn test_meta() {
    // this would not compile if STRING were not marked #[derive(Copy, Clone)]
    let copy_of_string = STRING;
    // just to make sure it was copied
    assert!(&STRING as *const _ != &copy_of_string as *const _);

    // this would not compile if STRING were not marked #[derive(Debug)]
    assert_eq!(
        format!("{:?}", STRING),
        "STRING { __private_field: () }".to_string()
    );
}

mod visibility {
    lazy_static! {
        pub static ref FOO: Box<u32> = Box::new(0);
        static ref BAR: Box<u32> = Box::new(98);
    }

    pub mod inner {
        lazy_static! {
            pub(in visibility) static ref BAZ: Box<u32> = Box::new(42);
            pub(crate) static ref BAG: Box<u32> = Box::new(37);
        }
    }

    #[test]
    fn sub_test() {
        assert_eq!(**FOO, 0);
        assert_eq!(**BAR, 98);
        assert_eq!(**inner::BAZ, 42);
        assert_eq!(**inner::BAG, 37);
    }
}

#[test]
fn test_visibility() {
    assert_eq!(*visibility::FOO, Box::new(0));
    assert_eq!(*visibility::inner::BAG, Box::new(37));
}

// This should not cause a warning about a missing Copy implementation
lazy_static! {
    pub static ref VAR: i32 = { 0 };
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct X;
struct Once(X);
const ONCE_INIT: Once = Once(X);
static DATA: X = X;
static ONCE: X = X;
fn require_sync() -> X {
    X
}
fn transmute() -> X {
    X
}
fn __static_ref_initialize() -> X {
    X
}
fn test(_: Vec<X>) -> X {
    X
}

// All these names should not be shadowed
lazy_static! {
    static ref ITEM_NAME_TEST: X = {
        test(vec![X, Once(X).0, ONCE_INIT.0, DATA, ONCE,
                  require_sync(), transmute(),
                  // Except this, which will sadly be shadowed by internals:
                  // __static_ref_initialize()
                  ])
    };
}

#[test]
fn item_name_shadowing() {
    assert_eq!(*ITEM_NAME_TEST, X);
}

use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::SeqCst;
#[allow(deprecated)]
use std::sync::atomic::ATOMIC_BOOL_INIT;

#[allow(deprecated)]
static PRE_INIT_FLAG: AtomicBool = ATOMIC_BOOL_INIT;

lazy_static! {
    static ref PRE_INIT: () = {
        PRE_INIT_FLAG.store(true, SeqCst);
        ()
    };
}

#[test]
fn pre_init() {
    assert_eq!(PRE_INIT_FLAG.load(SeqCst), false);
    lazy_static::initialize(&PRE_INIT);
    assert_eq!(PRE_INIT_FLAG.load(SeqCst), true);
}

lazy_static! {
    static ref LIFETIME_NAME: for<'a> fn(&'a u8) = {
        fn f(_: &u8) {}
        f
    };
}

#[test]
fn lifetime_name() {
    let _ = LIFETIME_NAME;
}
<commit_msg>test: VAR; remove unused braces<commit_after>#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;

lazy_static! {
    /// Documentation!
    pub static ref NUMBER: u32 = times_two(3);

    static ref ARRAY_BOXES: [Box<u32>; 3] = [Box::new(1), Box::new(2), Box::new(3)];

    /// More documentation!
    #[allow(unused_variables)]
    #[derive(Copy, Clone, Debug)]
    pub static ref STRING: String = "hello".to_string();

    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "abc");
        m.insert(1, "def");
        m.insert(2, "ghi");
        m
    };

    // This should not compile if the unsafe is removed.
    static ref UNSAFE: u32 = unsafe {
        std::mem::transmute::<i32, u32>(-1)
    };
}

lazy_static! {
    static ref S1: &'static str = "a";
    static ref S2: &'static str = "b";
}
lazy_static! {
    static ref S3: String = [*S1, *S2].join("");
}

#[test]
fn s3() {
    assert_eq!(&*S3, "ab");
}

fn times_two(n: u32) -> u32 {
    n * 2
}

#[test]
fn test_basic() {
    assert_eq!(&**STRING, "hello");
    assert_eq!(*NUMBER, 6);
    assert!(HASHMAP.get(&1).is_some());
    assert!(HASHMAP.get(&3).is_none());
    assert_eq!(&*ARRAY_BOXES, &[Box::new(1), Box::new(2), Box::new(3)]);
    assert_eq!(*UNSAFE, std::u32::MAX);
}

#[test]
fn test_repeat() {
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
    assert_eq!(*NUMBER, 6);
}

#[test]
fn test_meta() {
    // this would not compile if STRING were not marked #[derive(Copy, Clone)]
    let copy_of_string = STRING;
    // just to make sure it was copied
    assert!(&STRING as *const _ != &copy_of_string as *const _);

    // this would not compile if STRING were not marked #[derive(Debug)]
    assert_eq!(
        format!("{:?}", STRING),
        "STRING { __private_field: () }".to_string()
    );
}

mod visibility {
    lazy_static! {
        pub static ref FOO: Box<u32> = Box::new(0);
        static ref BAR: Box<u32> = Box::new(98);
    }

    pub mod inner {
        lazy_static! {
            pub(in visibility) static ref BAZ: Box<u32> = Box::new(42);
            pub(crate) static ref BAG: Box<u32> = Box::new(37);
        }
    }

    #[test]
    fn sub_test() {
        assert_eq!(**FOO, 0);
        assert_eq!(**BAR, 98);
        assert_eq!(**inner::BAZ, 42);
        assert_eq!(**inner::BAG, 37);
    }
}

#[test]
fn test_visibility() {
    assert_eq!(*visibility::FOO, Box::new(0));
    assert_eq!(*visibility::inner::BAG, Box::new(37));
}

// This should not cause a warning about a missing Copy implementation
lazy_static! {
    pub static ref VAR: i32 = 0;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct X;
struct Once(X);
const ONCE_INIT: Once = Once(X);
static DATA: X = X;
static ONCE: X = X;
fn require_sync() -> X {
    X
}
fn transmute() -> X {
    X
}
fn __static_ref_initialize() -> X {
    X
}
fn test(_: Vec<X>) -> X {
    X
}

// All these names should not be shadowed
lazy_static! {
    static ref ITEM_NAME_TEST: X = {
        test(vec![X, Once(X).0, ONCE_INIT.0, DATA, ONCE,
                  require_sync(), transmute(),
                  // Except this, which will sadly be shadowed by internals:
                  // __static_ref_initialize()
                  ])
    };
}

#[test]
fn item_name_shadowing() {
    assert_eq!(*ITEM_NAME_TEST, X);
}

use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::SeqCst;
#[allow(deprecated)]
use std::sync::atomic::ATOMIC_BOOL_INIT;

#[allow(deprecated)]
static PRE_INIT_FLAG: AtomicBool = ATOMIC_BOOL_INIT;

lazy_static! {
    static ref PRE_INIT: () = {
        PRE_INIT_FLAG.store(true, SeqCst);
        ()
    };
}

#[test]
fn pre_init() {
    assert_eq!(PRE_INIT_FLAG.load(SeqCst), false);
    lazy_static::initialize(&PRE_INIT);
    assert_eq!(PRE_INIT_FLAG.load(SeqCst), true);
}

lazy_static! {
    static ref LIFETIME_NAME: for<'a> fn(&'a u8) = {
        fn f(_: &u8) {}
        f
    };
}

#[test]
fn lifetime_name() {
    let _ = LIFETIME_NAME;
}
<|endoftext|>


<commit_before>use std::{f32, f64};

#[macro_use]
extern crate quote;

struct X;

impl quote::ToTokens for X {
    fn to_tokens(&self, tokens: &mut quote::Tokens) {
        tokens.append("X");
    }
}

#[test]
fn test_quote_impl() {
    let tokens = quote!(
        impl<'a, T: ToTokens> ToTokens for &'a T {
            fn to_tokens(&self, tokens: &mut Tokens) {
                (**self).to_tokens(tokens)
            }
        }
    );

    let expected = concat!(
        "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
            "fn to_tokens ( & self , tokens : & mut Tokens ) { ",
                "( * * self ) . to_tokens ( tokens ) ",
            "} ",
        "} "
    );

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_substitution() {
    let x = X;
    let tokens = quote!(#x <#x> (#x) [#x] {#x});

    let expected = "X < X > ( X ) [ X ] { X } ";

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_iter() {
    let primes = &[X, X, X, X];

    assert_eq!("X X X X ", quote!(#(#primes)*).to_string());

    assert_eq!("X , X , X , X , ", quote!(#(#primes,)*).to_string());

    assert_eq!("X , X , X , X ", quote!(#(#primes),*).to_string());
}

#[test]
fn test_advanced() {
    let generics = quote!( <'a, T> );

    let where_clause = quote!( where T: Serialize );

    let field_ty = quote!( String );

    let item_ty = quote!( Cow<'a, str> );

    let path = quote!( SomeTrait::serialize_with );

    let value = quote!( self.x );

    let tokens = quote! {
        struct SerializeWith #generics #where_clause {
            value: &'a #field_ty,
            phantom: ::std::marker::PhantomData<#item_ty>,
        }

        impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
            fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
                where S: ::serde::Serializer
            {
                #path(self.value, s)
            }
        }

        SerializeWith {
            value: #value,
            phantom: ::std::marker::PhantomData::<#item_ty>,
        }
    };

    let expected = concat!(
        "struct SerializeWith < 'a , T >  where T : Serialize  { ",
            "value : & 'a String  , ",
            "phantom : :: std :: marker :: PhantomData < Cow < 'a , str >  > , ",
        "} ",
        "impl < 'a , T >  :: serde :: Serialize for SerializeWith < 'a , T >  where T : Serialize  { ",
            "fn serialize < S > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > ",
                "where S : :: serde :: Serializer ",
            "{ ",
                "SomeTrait :: serialize_with  ( self . value , s ) ",
            "} ",
        "} ",
        "SerializeWith { ",
            "value : self . x  , ",
            "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str >  > , ",
        "} "
    );

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_integer() {
    let ii8 = -1i8;
    let ii16 = -1i16;
    let ii32 = -1i32;
    let ii64 = -1i64;
    let iisize = -1isize;
    let uu8 = 1u8;
    let uu16 = 1u16;
    let uu32 = 1u32;
    let uu64 = 1u64;
    let uusize = 1usize;

    let tokens = quote! {
        #ii8 #ii16 #ii32 #ii64 #iisize
        #uu8 #uu16 #uu32 #uu64 #uusize
    };
    let expected = "-1i8 -1i16 -1i32 -1i64 -1isize 1u8 1u16 1u32 1u64 1usize ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_floating() {
    let e32 = 2.71828f32;
    let nan32 = f32::NAN;
    let inf32 = f32::INFINITY;
    let neginf32 = f32::NEG_INFINITY;

    let e64 = 2.71828f64;
    let nan64 = f64::NAN;
    let inf64 = f64::INFINITY;
    let neginf64 = f64::NEG_INFINITY;

    let tokens = quote! {
        #e32 @ #nan32 @ #inf32 @ #neginf32
        #e64 @ #nan64 @ #inf64 @ #neginf64
    };
    let expected = concat!(
        "2.71828f32 @ :: std :: f32 :: NAN @ :: std :: f32 :: INFINITY @ :: std :: f32 :: NEG_INFINITY ",
        "2.71828f64 @ :: std :: f64 :: NAN @ :: std :: f64 :: INFINITY @ :: std :: f64 :: NEG_INFINITY ",
    );
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_char() {
    let zero = '\x00';
    let pound = '#';
    let quote = '"';
    let apost = '\'';
    let newline = '\n';
    let heart = '\u{2764}';

    let tokens = quote! {
        #zero #pound #quote #apost #newline #heart
    };
    let expected = "'\\u{0}' '#' '\"' '\\'' '\\n' '\u{2764}' ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_str() {
    let s = "a 'b \" c";
    let tokens = quote!(#s);
    let expected = "\"a 'b \\\" c\" ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_string() {
    let s = "a 'b \" c".to_string();
    let tokens = quote!(#s);
    let expected = "\"a 'b \\\" c\" ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_fancy_repetition() {
    let foo = vec!["a", "b"];
    let bar = vec![true, false];

    let tokens = quote! {
        #(#foo: #bar),*
    };

    let expected = r#""a" : true , "b" : false "#;
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_nested_fancy_repetition() {
    let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']];

    let tokens = quote! {
        #(
            #(#nested)*
        ),*
    };

    let expected = "'a' 'b' 'c' , 'x' 'y' 'z' ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_empty_repetition() {
    let tokens = quote!(#(a b)* #(c d),*);
    assert_eq!("", tokens.to_string());
}
<commit_msg>Add test for duplicate token<commit_after>use std::{f32, f64};

#[macro_use]
extern crate quote;

struct X;

impl quote::ToTokens for X {
    fn to_tokens(&self, tokens: &mut quote::Tokens) {
        tokens.append("X");
    }
}

#[test]
fn test_quote_impl() {
    let tokens = quote!(
        impl<'a, T: ToTokens> ToTokens for &'a T {
            fn to_tokens(&self, tokens: &mut Tokens) {
                (**self).to_tokens(tokens)
            }
        }
    );

    let expected = concat!(
        "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
            "fn to_tokens ( & self , tokens : & mut Tokens ) { ",
                "( * * self ) . to_tokens ( tokens ) ",
            "} ",
        "} "
    );

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_substitution() {
    let x = X;
    let tokens = quote!(#x <#x> (#x) [#x] {#x});

    let expected = "X < X > ( X ) [ X ] { X } ";

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_iter() {
    let primes = &[X, X, X, X];

    assert_eq!("X X X X ", quote!(#(#primes)*).to_string());

    assert_eq!("X , X , X , X , ", quote!(#(#primes,)*).to_string());

    assert_eq!("X , X , X , X ", quote!(#(#primes),*).to_string());
}

#[test]
fn test_advanced() {
    let generics = quote!( <'a, T> );

    let where_clause = quote!( where T: Serialize );

    let field_ty = quote!( String );

    let item_ty = quote!( Cow<'a, str> );

    let path = quote!( SomeTrait::serialize_with );

    let value = quote!( self.x );

    let tokens = quote! {
        struct SerializeWith #generics #where_clause {
            value: &'a #field_ty,
            phantom: ::std::marker::PhantomData<#item_ty>,
        }

        impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
            fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
                where S: ::serde::Serializer
            {
                #path(self.value, s)
            }
        }

        SerializeWith {
            value: #value,
            phantom: ::std::marker::PhantomData::<#item_ty>,
        }
    };

    let expected = concat!(
        "struct SerializeWith < 'a , T >  where T : Serialize  { ",
            "value : & 'a String  , ",
            "phantom : :: std :: marker :: PhantomData < Cow < 'a , str >  > , ",
        "} ",
        "impl < 'a , T >  :: serde :: Serialize for SerializeWith < 'a , T >  where T : Serialize  { ",
            "fn serialize < S > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > ",
                "where S : :: serde :: Serializer ",
            "{ ",
                "SomeTrait :: serialize_with  ( self . value , s ) ",
            "} ",
        "} ",
        "SerializeWith { ",
            "value : self . x  , ",
            "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str >  > , ",
        "} "
    );

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_integer() {
    let ii8 = -1i8;
    let ii16 = -1i16;
    let ii32 = -1i32;
    let ii64 = -1i64;
    let iisize = -1isize;
    let uu8 = 1u8;
    let uu16 = 1u16;
    let uu32 = 1u32;
    let uu64 = 1u64;
    let uusize = 1usize;

    let tokens = quote! {
        #ii8 #ii16 #ii32 #ii64 #iisize
        #uu8 #uu16 #uu32 #uu64 #uusize
    };
    let expected = "-1i8 -1i16 -1i32 -1i64 -1isize 1u8 1u16 1u32 1u64 1usize ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_floating() {
    let e32 = 2.71828f32;
    let nan32 = f32::NAN;
    let inf32 = f32::INFINITY;
    let neginf32 = f32::NEG_INFINITY;

    let e64 = 2.71828f64;
    let nan64 = f64::NAN;
    let inf64 = f64::INFINITY;
    let neginf64 = f64::NEG_INFINITY;

    let tokens = quote! {
        #e32 @ #nan32 @ #inf32 @ #neginf32
        #e64 @ #nan64 @ #inf64 @ #neginf64
    };
    let expected = concat!(
        "2.71828f32 @ :: std :: f32 :: NAN @ :: std :: f32 :: INFINITY @ :: std :: f32 :: NEG_INFINITY ",
        "2.71828f64 @ :: std :: f64 :: NAN @ :: std :: f64 :: INFINITY @ :: std :: f64 :: NEG_INFINITY ",
    );
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_char() {
    let zero = '\x00';
    let pound = '#';
    let quote = '"';
    let apost = '\'';
    let newline = '\n';
    let heart = '\u{2764}';

    let tokens = quote! {
        #zero #pound #quote #apost #newline #heart
    };
    let expected = "'\\u{0}' '#' '\"' '\\'' '\\n' '\u{2764}' ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_str() {
    let s = "a 'b \" c";
    let tokens = quote!(#s);
    let expected = "\"a 'b \\\" c\" ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_string() {
    let s = "a 'b \" c".to_string();
    let tokens = quote!(#s);
    let expected = "\"a 'b \\\" c\" ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_duplicate() {
    let ch = 'x';

    let tokens = quote!(#ch #ch);

    let expected = "'x' 'x' ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_fancy_repetition() {
    let foo = vec!["a", "b"];
    let bar = vec![true, false];

    let tokens = quote! {
        #(#foo: #bar),*
    };

    let expected = r#""a" : true , "b" : false "#;
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_nested_fancy_repetition() {
    let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']];

    let tokens = quote! {
        #(
            #(#nested)*
        ),*
    };

    let expected = "'a' 'b' 'c' , 'x' 'y' 'z' ";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_empty_repetition() {
    let tokens = quote!(#(a b)* #(c d),*);
    assert_eq!("", tokens.to_string());
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::collections::VecDeque;

#[derive(Debug)]
struct NodeInfo<'a,T: 'a + Debug> {
    depth: u32,
    iter: &'a Tree<T>,
}

impl<'a,T: 'a + Debug> NodeInfo<'a,T> {
    fn new(t: u32, it: &'a Tree<T>) -> Self { NodeInfo { depth: t, iter: it, } }
}

#[derive(Debug)]
struct Tree<T:Debug> {
  data: T,
  children: Vec<Tree<T>>,
}

impl<T:Debug> Tree<T> {
  fn new(t: T, c: Vec<Tree<T>>) -> Self { Tree { data: t, children: c, } }
  fn leaf(t: T) -> Self { Tree { data: t, children: vec![], } }
}

// Note that path elements are listed backwards (right-to-left) because we pop
// them off the end.
fn seek_path<T:Debug>(t: &Tree<T>, mut path: Vec<usize>) -> &Tree<T> {
  if let Some(index) = path.pop() {
    seek_path(&t.children[index], path)
  } else {
    t
  }
}

fn print_tree<T:Debug>(t: &Tree<T>) {
    let mut q: VecDeque<NodeInfo<T>> = VecDeque::new();
    let mut depth_old: u32 = 0;

    q.push_back(NodeInfo::new(depth_old, t));

    while let Some(mut u) = q.pop_front() {
        if u.depth > depth_old {
            println!("{:?}", u.iter.data);
            print!(" ");
        }
        else {
            print!("{:?}", u.iter.data);
            print!(" ");
        }

        depth_old = u.depth;
        u.depth += 1;

        for kid in u.iter.children.iter() {
            q.push_back(NodeInfo::new(u.depth, kid));
        }
    }

    println!("");
}

fn main() {
    let t = Tree::new("a", vec![Tree::leaf("b"),
                                Tree::leaf("c"),
                                Tree::new("d", vec![Tree::leaf("e")])]);
    print_tree(&t);

    println!["{:?}", seek_path(&t, vec![0usize])];
    println!["{:?}", seek_path(&t, vec![2usize])];
    println!["{:?}", seek_path(&t, vec![0usize, 2usize])];
}
<commit_msg>fixed formatting<commit_after>use std::fmt::Debug;
use std::collections::VecDeque;

#[derive(Debug)]
struct NodeInfo<'a,T: 'a + Debug> {
    depth: u32,
    iter: &'a Tree<T>,
}

impl<'a,T: 'a + Debug> NodeInfo<'a,T> {
    fn new(t: u32, it: &'a Tree<T>) -> Self { NodeInfo { depth: t, iter: it, } }
}

#[derive(Debug)]
struct Tree<T:Debug> {
  data: T,
  children: Vec<Tree<T>>,
}

impl<T:Debug> Tree<T> {
  fn new(t: T, c: Vec<Tree<T>>) -> Self { Tree { data: t, children: c, } }
  fn leaf(t: T) -> Self { Tree { data: t, children: vec![], } }
}

// Note that path elements are listed backwards (right-to-left) because we pop
// them off the end.
fn seek_path<T:Debug>(t: &Tree<T>, mut path: Vec<usize>) -> &Tree<T> {
  if let Some(index) = path.pop() {
    seek_path(&t.children[index], path)
  } else {
    t
  }
}

fn print_tree<T:Debug>(t: &Tree<T>) {
    let mut q: VecDeque<NodeInfo<T>> = VecDeque::new();
    let mut depth_old: u32 = 0;

    q.push_back(NodeInfo::new(depth_old, t));

    while let Some(mut u) = q.pop_front() {
        if u.depth > depth_old {
            println!("");
            print!("{:?}", u.iter.data);
            print!(" ");
        }
        else {
            print!("{:?}", u.iter.data);
            print!(" ");
        }

        depth_old = u.depth;
        u.depth += 1;

        for kid in u.iter.children.iter() {
            q.push_back(NodeInfo::new(u.depth, kid));
        }
    }

    println!("");
}

fn main() {
    let t = Tree::new("a", vec![Tree::leaf("b"),
                                Tree::leaf("c"),
                                Tree::new("d", vec![Tree::leaf("e")])]);
    print_tree(&t);

    println!["{:?}", seek_path(&t, vec![0usize])];
    println!["{:?}", seek_path(&t, vec![2usize])];
    println!["{:?}", seek_path(&t, vec![0usize, 2usize])];
}
<|endoftext|>