<commit_before>use hyper::{Body, Client, Method, Request};
#[allow(unused)]
use log::{error, info, warn};

use serde_json::json;
use std::fs;
use std::process::exit;

use librespot::core::authentication::Credentials;
use librespot::core::config::SessionConfig;
use librespot::core::keymaster;
use librespot::core::session::Session;
use librespot::core::spotify_id::SpotifyId;

use librespot::playback::audio_backend;
use librespot::playback::config::{AudioFormat, PlayerConfig};
use librespot::playback::player::{Player, PlayerEvent};

const VERSION: &'static str = concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION"));

const SCOPES: &str = "user-read-private,playlist-read-private,playlist-read-collaborative,playlist-modify-public,playlist-modify-private,user-follow-modify,user-follow-read,user-library-read,user-library-modify,user-top-read,user-read-recently-played";

#[cfg(debug_assertions)]
const DEBUGMODE: bool = true;
#[cfg(not(debug_assertions))]
const DEBUGMODE: bool = false;

pub fn check(version_info: String) {
    println!("ok {}", version_info.to_string());

    let capabilities = json!({
        "version": env!("CARGO_PKG_VERSION").to_string(),
        "autoplay": true,
        "lms-auth": true,
        "volume-normalisation": true,
        "debug": DEBUGMODE,
        "ogg-direct": true,
        "save-token": true,
        "podcasts": true,
        "zeroconf-port": true
    });

    println!("{}", capabilities.to_string());
    exit(0);
}

// inspired by examples/get_token.rs
pub async fn get_token(
    client_id: Option<String>,
    scopes: Option<String>,
    save_token: Option<String>,
    last_credentials: Option<Credentials>,
    session_config: SessionConfig,
) {
    match last_credentials {
        Some(last_credentials) => {
            if let Some(client_id) = client_id {
                let scopes = scopes.unwrap_or(SCOPES.to_string());

                match Session::connect(session_config, last_credentials, None).await {
                    Ok(session) => {
                        match keymaster::get_token(&session, &client_id, &scopes).await {
                            Ok(token) => {
                                let json_token = json!({
                                    "accessToken": token.access_token.to_string(),
                                    "expiresIn": token.expires_in,
                                });

                                if let Some(save_token) = save_token {
                                    fs::write(save_token.to_string(), format!("{}", json_token))
                                        .expect("Can't write token file");
                                } else {
                                    println!("{}", json_token);
                                }
                            }
                            Err(error) => {
                                error!("Failed to fetch token: {:?}", error);
                                println!("{{ \"error\": \"Failed to get token.\" }}");
                            }
                        }
                    }
                    Err(error) => {
                        error!("Failed to create session: {:?}", error);
                        println!("{{ \"error\": \"Failed to create session.\" }}");
                    }
                }
            } else {
                println!("Use --client-id to provide a CLIENT_ID");
            }
        }
        None => {
            println!("Missing credentials");
        }
    }
}

// inspired by examples/play.rs
pub async fn play_track(
    track_id: String,
    start_position: u32,
    last_credentials: Option<Credentials>,
    player_config: PlayerConfig,
    session_config: SessionConfig,
) {
    match last_credentials {
        Some(last_credentials) => {
            let backend = audio_backend::find(None).unwrap();
            let audio_format = AudioFormat::default();

            let track = SpotifyId::from_uri(
                track_id
                    .replace("spotty://", "spotify:track:")
                    .replace("://", ":")
                    .as_str(),
            );

            match track {
                Ok(track) => match Session::connect(session_config, last_credentials, None).await {
                    Ok(session) => {
                        let (mut player, _) =
                            Player::new(player_config, session, None, move || {
                                backend(None, audio_format)
                            });

                        player.load(track, true, start_position);
                        player.await_end_of_track().await;
                    }
                    Err(error) => {
                        error!("Failed to create session: {:?}", error);
                        return;
                    }
                },
                Err(error) => {
                    error!("Problem getting a Spotify ID for {}: {:?}", track_id, error);
                    return;
                }
            };
        }
        None => {
            println!("Missing credentials");
        }
    }
}

// Connect mode support

#[derive(Clone)]
pub struct LMS {
    base_url: Option<String>,
    player_mac: Option<String>,
    auth: Option<String>,
}

#[allow(unused)]
impl LMS {
    pub fn new(base_url: Option<String>, player_mac: Option<String>, auth: Option<String>) -> LMS {
        LMS {
            base_url: Some(format!(
                "http://{}/jsonrpc.js",
                base_url.unwrap_or("localhost:9000".to_string())
            )),
            player_mac: player_mac,
            auth: auth,
        }
    }

    pub fn is_configured(&self) -> bool {
        if self.base_url != None {
            if self.player_mac != None {
                return true;
            }
        }

        return false;
    }

    pub async fn signal_event(&self, event: PlayerEvent) {
        let mut command = r#"["spottyconnect","change"]"#.to_string();

        match event {
            PlayerEvent::Changed {
                old_track_id,
                new_track_id,
            } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: changed, old track: {}, new track: {}",
                    old_track_id.to_base62().unwrap_or_default(),
                    new_track_id.to_base62().unwrap_or_default()
                );
                command = format!(
                    r#"["spottyconnect","change","{}","{}"]"#,
                    new_track_id.to_base62().unwrap_or_default().to_string(),
                    old_track_id.to_base62().unwrap_or_default().to_string()
                );
            }
            PlayerEvent::Started { track_id, .. } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: started, track: {}",
                    track_id.to_base62().unwrap_or_default()
                );
                command = format!(
                    r#"["spottyconnect","start","{}"]"#,
                    track_id.to_base62().unwrap_or_default().to_string()
                );
            }
            PlayerEvent::Stopped { track_id, .. } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: stopped, track: {}",
                    track_id.to_base62().unwrap_or_default()
                );
                command = r#"["spottyconnect","stop"]"#.to_string();
            }
            PlayerEvent::Playing {
                track_id,
                duration_ms,
                position_ms,
                ..
            } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: playing, track: {}, duration: {}, position: {}",
                    track_id.to_base62().unwrap_or_default(),
                    duration_ms,
                    position_ms
                );
                // we're not implementing the seek event here, as it's going to read player state anyway
                // but signal a change if the new position has changed and is > 0
                if position_ms <= 0 {
                    return;
                }
                command = r#"["spottyconnect","change"]"#.to_string();
            }
            PlayerEvent::Paused {
                track_id,
                duration_ms,
                position_ms,
                ..
            } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: paused, track: {}, duration: {}, position: {}",
                    track_id.to_base62().unwrap_or_default(),
                    duration_ms,
                    position_ms
                );
                command = r#"["spottyconnect","stop"]"#.to_string();
            }
            PlayerEvent::VolumeSet { volume } => {
                let mut new_volume = volume as u32;
                if new_volume > 0 {
                    new_volume = new_volume * 100 / u32::pow(2, 16);
                }

                if new_volume > 100 {
                    new_volume = 100;
                };

                #[cfg(debug_assertions)]
                info!("event: volume: {}", volume);
                // we're not using the volume here, as LMS will read player state anyway
                command = format!(r#"["spottyconnect","volume",{}]"#, new_volume.to_string());
            }
            _ => return,
        }

        if !self.is_configured() {
            #[cfg(debug_assertions)]
            warn!("LMS connection is not configured");
            #[cfg(debug_assertions)]
            info!("{}", command);
            return;
        }

        if let Some(ref base_url) = self.base_url {
            #[cfg(debug_assertions)]
            info!("Base URL to talk to LMS: {}", base_url);

            if let Some(ref player_mac) = self.player_mac {
                #[cfg(debug_assertions)]
                info!("Player MAC address to control: {}", player_mac);

                #[cfg(debug_assertions)]
                info!("Command to send to player: {}", command);

                let json = format!(
                    r#"{{"id": 1,"method":"slim.request","params":["{}",{}]}}"#,
                    player_mac, command
                );

                let mut auth_header = "".to_string();
                if let Some(ref auth) = self.auth {
                    auth_header = auth.trim().to_string();
                }

                let req = Request::builder()
                    .method(Method::POST)
                    .uri(base_url.to_string())
                    .header("user-agent", format!("{}", VERSION))
                    .header("content-type", "application/json")
                    .header("authorization", format!("Basic {}", auth_header))
                    .header("x-scanner", "1")
                    .body(Body::from(json.clone()))
                    .unwrap();

                let client = Client::new();
                let resp = client.request(req).await;

                match resp {
                    Ok(resp) => {
                        #[cfg(debug_assertions)]
                        info!("Response: {}", resp.status());
                    }
                    Err(error) => {
                        warn!("Problem posting to {} / {}: {:?}", base_url, json, error);
                    }
                }
            }
        }
    }
}
<commit_msg>Report errors back to LMS, unify response handling.<commit_after>use hyper::{Body, Client, Method, Request};
#[allow(unused)]
use log::{error, info, warn};

use serde_json::{json, Value};
use std::fs;
use std::process::exit;

use librespot::core::authentication::Credentials;
use librespot::core::config::SessionConfig;
use librespot::core::keymaster;
use librespot::core::session::Session;
use librespot::core::spotify_id::SpotifyId;

use librespot::playback::audio_backend;
use librespot::playback::config::{AudioFormat, PlayerConfig};
use librespot::playback::player::{Player, PlayerEvent};

const VERSION: &'static str = concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION"));

const SCOPES: &str = "user-read-private,playlist-read-private,playlist-read-collaborative,playlist-modify-public,playlist-modify-private,user-follow-modify,user-follow-read,user-library-read,user-library-modify,user-top-read,user-read-recently-played";

#[cfg(debug_assertions)]
const DEBUGMODE: bool = true;
#[cfg(not(debug_assertions))]
const DEBUGMODE: bool = false;

pub fn check(version_info: String) {
    println!("ok {}", version_info.to_string());

    let capabilities = json!({
        "version": env!("CARGO_PKG_VERSION").to_string(),
        "autoplay": true,
        "lms-auth": true,
        "volume-normalisation": true,
        "debug": DEBUGMODE,
        "ogg-direct": true,
        "save-token": true,
        "podcasts": true,
        "zeroconf-port": true
    });

    println!("{}", capabilities.to_string());
    exit(0);
}

// inspired by examples/get_token.rs
pub async fn get_token(
    client_id: Option<String>,
    scopes: Option<String>,
    save_token: Option<String>,
    last_credentials: Option<Credentials>,
    session_config: SessionConfig,
) {
    match last_credentials {
        Some(last_credentials) => {
            if let Some(client_id) = client_id {
                let scopes = scopes.unwrap_or(SCOPES.to_string());

                match Session::connect(session_config, last_credentials, None).await {
                    Ok(session) => {
                        match keymaster::get_token(&session, &client_id, &scopes).await {
                            Ok(token) => {
                                write_response(
                                    json!({
                                        "accessToken": token.access_token.to_string(),
                                        "expiresIn": token.expires_in,
                                    }),
                                    save_token,
                                );
                            }
                            Err(error) => {
                                error!("Failed to fetch token: {:?}", error);
                                write_response(
                                    json!({
                                        "error": "Failed to get access token."
                                    }),
                                    save_token,
                                );
                            }
                        }
                    }
                    Err(error) => {
                        error!("Failed to create session: {:?}", error);
                        write_response(
                            json!({
                                "error": "Failed to create session or connect to servers."
                            }),
                            save_token,
                        );
                    }
                }
            } else {
                println!("Use --client-id to provide a CLIENT_ID");
            }
        }
        None => {
            println!("Missing credentials");
        }
    }
}

fn write_response(json_token: Value, save_token: Option<String>) {
    if let Some(save_token) = save_token {
        fs::write(save_token.to_string(), json_token.to_string()).expect("Can't write token file");
    } else {
        println!("{}", json_token);
    }
}

// inspired by examples/play.rs
pub async fn play_track(
    track_id: String,
    start_position: u32,
    last_credentials: Option<Credentials>,
    player_config: PlayerConfig,
    session_config: SessionConfig,
) {
    match last_credentials {
        Some(last_credentials) => {
            let backend = audio_backend::find(None).unwrap();
            let audio_format = AudioFormat::default();

            let track = SpotifyId::from_uri(
                track_id
                    .replace("spotty://", "spotify:track:")
                    .replace("://", ":")
                    .as_str(),
            );

            match track {
                Ok(track) => match Session::connect(session_config, last_credentials, None).await {
                    Ok(session) => {
                        let (mut player, _) =
                            Player::new(player_config, session, None, move || {
                                backend(None, audio_format)
                            });

                        player.load(track, true, start_position);
                        player.await_end_of_track().await;
                    }
                    Err(error) => {
                        error!("Failed to create session: {:?}", error);
                        return;
                    }
                },
                Err(error) => {
                    error!("Problem getting a Spotify ID for {}: {:?}", track_id, error);
                    return;
                }
            };
        }
        None => {
            println!("Missing credentials");
        }
    }
}

// Connect mode support

#[derive(Clone)]
pub struct LMS {
    base_url: Option<String>,
    player_mac: Option<String>,
    auth: Option<String>,
}

#[allow(unused)]
impl LMS {
    pub fn new(base_url: Option<String>, player_mac: Option<String>, auth: Option<String>) -> LMS {
        LMS {
            base_url: Some(format!(
                "http://{}/jsonrpc.js",
                base_url.unwrap_or("localhost:9000".to_string())
            )),
            player_mac: player_mac,
            auth: auth,
        }
    }

    pub fn is_configured(&self) -> bool {
        if self.base_url != None {
            if self.player_mac != None {
                return true;
            }
        }

        return false;
    }

    pub async fn signal_event(&self, event: PlayerEvent) {
        let mut command = r#"["spottyconnect","change"]"#.to_string();

        match event {
            PlayerEvent::Changed {
                old_track_id,
                new_track_id,
            } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: changed, old track: {}, new track: {}",
                    old_track_id.to_base62().unwrap_or_default(),
                    new_track_id.to_base62().unwrap_or_default()
                );
                command = format!(
                    r#"["spottyconnect","change","{}","{}"]"#,
                    new_track_id.to_base62().unwrap_or_default().to_string(),
                    old_track_id.to_base62().unwrap_or_default().to_string()
                );
            }
            PlayerEvent::Started { track_id, .. } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: started, track: {}",
                    track_id.to_base62().unwrap_or_default()
                );
                command = format!(
                    r#"["spottyconnect","start","{}"]"#,
                    track_id.to_base62().unwrap_or_default().to_string()
                );
            }
            PlayerEvent::Stopped { track_id, .. } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: stopped, track: {}",
                    track_id.to_base62().unwrap_or_default()
                );
                command = r#"["spottyconnect","stop"]"#.to_string();
            }
            PlayerEvent::Playing {
                track_id,
                duration_ms,
                position_ms,
                ..
            } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: playing, track: {}, duration: {}, position: {}",
                    track_id.to_base62().unwrap_or_default(),
                    duration_ms,
                    position_ms
                );
                // we're not implementing the seek event here, as it's going to read player state anyway
                // but signal a change if the new position has changed and is > 0
                if position_ms <= 0 {
                    return;
                }
                command = r#"["spottyconnect","change"]"#.to_string();
            }
            PlayerEvent::Paused {
                track_id,
                duration_ms,
                position_ms,
                ..
            } => {
                #[cfg(debug_assertions)]
                info!(
                    "event: paused, track: {}, duration: {}, position: {}",
                    track_id.to_base62().unwrap_or_default(),
                    duration_ms,
                    position_ms
                );
                command = r#"["spottyconnect","stop"]"#.to_string();
            }
            PlayerEvent::VolumeSet { volume } => {
                let mut new_volume = volume as u32;
                if new_volume > 0 {
                    new_volume = new_volume * 100 / u32::pow(2, 16);
                }

                if new_volume > 100 {
                    new_volume = 100;
                };

                #[cfg(debug_assertions)]
                info!("event: volume: {}", volume);
                // we're not using the volume here, as LMS will read player state anyway
                command = format!(r#"["spottyconnect","volume",{}]"#, new_volume.to_string());
            }
            _ => return,
        }

        if !self.is_configured() {
            #[cfg(debug_assertions)]
            warn!("LMS connection is not configured");
            #[cfg(debug_assertions)]
            info!("{}", command);
            return;
        }

        if let Some(ref base_url) = self.base_url {
            #[cfg(debug_assertions)]
            info!("Base URL to talk to LMS: {}", base_url);

            if let Some(ref player_mac) = self.player_mac {
                #[cfg(debug_assertions)]
                info!("Player MAC address to control: {}", player_mac);

                #[cfg(debug_assertions)]
                info!("Command to send to player: {}", command);

                let json = format!(
                    r#"{{"id": 1,"method":"slim.request","params":["{}",{}]}}"#,
                    player_mac, command
                );

                let mut auth_header = "".to_string();
                if let Some(ref auth) = self.auth {
                    auth_header = auth.trim().to_string();
                }

                let req = Request::builder()
                    .method(Method::POST)
                    .uri(base_url.to_string())
                    .header("user-agent", format!("{}", VERSION))
                    .header("content-type", "application/json")
                    .header("authorization", format!("Basic {}", auth_header))
                    .header("x-scanner", "1")
                    .body(Body::from(json.clone()))
                    .unwrap();

                let client = Client::new();
                let resp = client.request(req).await;

                match resp {
                    Ok(resp) => {
                        #[cfg(debug_assertions)]
                        info!("Response: {}", resp.status());
                    }
                    Err(error) => {
                        warn!("Problem posting to {} / {}: {:?}", base_url, json, error);
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>tink-aead: use TypedPrimitiveSet for safety<commit_after><|endoftext|>


<commit_before>
extern crate regex;

use std::collections::VecDeque;

use std::io;
use std::io::prelude::*;

use regex::Regex;

#[derive(Debug)]
struct Range((usize, usize), (usize, usize));

#[derive(Debug)]
enum OperationType {
    On,
    Off,
    Toggle,
}

#[derive(Debug)]
struct Operation {
    op_type: OperationType,
    range: Range,
}

fn main() {

    let mut oper_list = VecDeque::new();

    {
        let re = Regex::new("^(turn on|turn off|toggle) ([0-9]+),([0-9]+) through \
                             ([0-9]+),([0-9]+)$")
                     .unwrap();
        let stdin = io::stdin();

        for uline in stdin.lock().lines() {
            let line = &uline.unwrap();

            let capture = re.captures(line).unwrap();

            let start_point = (capture.at(2).unwrap().parse::<usize>().unwrap(),
                               capture.at(3).unwrap().parse::<usize>().unwrap());

            let end_point = (capture.at(4).unwrap().parse::<usize>().unwrap(),
                             capture.at(5).unwrap().parse::<usize>().unwrap());

            let op;
            let op_str = capture.at(1).unwrap();
            let op_range = Range(start_point, end_point);

            match op_str {
                "turn on" => {
                    op = Operation {
                        op_type: OperationType::On,
                        range: op_range,
                    }
                }
                "turn off" => {
                    op = Operation {
                        op_type: OperationType::Off,
                        range: op_range,
                    }
                }
                "toggle" => {
                    op = Operation {
                        op_type: OperationType::Toggle,
                        range: op_range,
                    }
                }
                _ => panic!("Unknown operation: {:?}", op_str),
            }

            oper_list.push_back(op);
        }
    }

    let mut light_matrix = [[false; 1000]; 1000];

    for oper in oper_list.iter() {
        // + 1 because the ranges are inclusive
        for x in ((oper.range.0).0)..((oper.range.1).0 + 1) {

            for y in ((oper.range.0).1)..((oper.range.1).1 + 1) {

                match oper.op_type {
                    OperationType::On => light_matrix[x][y] = true,
                    OperationType::Off => light_matrix[x][y] = false,
                    OperationType::Toggle => light_matrix[x][y] = !light_matrix[x][y],
                }
            }
        }
    }

    let sum = light_matrix.iter().fold(0, |total_acc, &row| {
        total_acc +
        row.iter().fold(0, |acc, &light_state| {
            if light_state {
                acc + 1
            } else {
                acc
            }
        })
    });

    println!("Number of light lit after all operations: {}", sum);

    let mut brt_matrix = [[0 as u32; 1000]; 1000];

    for oper in oper_list.iter() {
        // + 1 because the ranges are inclusive
        for x in ((oper.range.0).0)..((oper.range.1).0 + 1) {

            for y in ((oper.range.0).1)..((oper.range.1).1 + 1) {

                match oper.op_type {
                    OperationType::On => brt_matrix[x][y] += 1,
                    OperationType::Off => if brt_matrix[x][y] != 0 { brt_matrix[x][y] -= 1 },
                    OperationType::Toggle => brt_matrix[x][y] += 2,
                }
            }
        }
    }

    let brt_sum = brt_matrix.iter().fold(0, |total_acc, &row| {
        total_acc +
        row.iter().fold(0, |acc, &light_state| {
            acc + light_state
        })
    });

    println!("Total brightness after all operations: {}", brt_sum);
}
<commit_msg>Minor code formatting.<commit_after>
extern crate regex;

use std::collections::VecDeque;

use std::io;
use std::io::prelude::*;

use regex::Regex;

#[derive(Debug)]
struct Range((usize, usize), (usize, usize));

#[derive(Debug)]
enum OperationType {
    On,
    Off,
    Toggle,
}

#[derive(Debug)]
struct Operation {
    op_type: OperationType,
    range: Range,
}

fn main() {

    let mut oper_list = VecDeque::new();

    {
        let re = Regex::new("^(turn on|turn off|toggle) ([0-9]+),([0-9]+) through \
                             ([0-9]+),([0-9]+)$")
                     .unwrap();
        let stdin = io::stdin();

        for uline in stdin.lock().lines() {
            let line = &uline.unwrap();

            let capture = re.captures(line).unwrap();

            let start_point = (capture.at(2).unwrap().parse::<usize>().unwrap(),
                               capture.at(3).unwrap().parse::<usize>().unwrap());

            let end_point = (capture.at(4).unwrap().parse::<usize>().unwrap(),
                             capture.at(5).unwrap().parse::<usize>().unwrap());

            let op;
            let op_str = capture.at(1).unwrap();
            let op_range = Range(start_point, end_point);

            match op_str {
                "turn on" => {
                    op = Operation {
                        op_type: OperationType::On,
                        range: op_range,
                    }
                }
                "turn off" => {
                    op = Operation {
                        op_type: OperationType::Off,
                        range: op_range,
                    }
                }
                "toggle" => {
                    op = Operation {
                        op_type: OperationType::Toggle,
                        range: op_range,
                    }
                }
                _ => panic!("Unknown operation: {:?}", op_str),
            }

            oper_list.push_back(op);
        }
    }

    let mut light_matrix = [[false; 1000]; 1000];

    for oper in oper_list.iter() {
        // + 1 because the ranges are inclusive
        for x in ((oper.range.0).0)..((oper.range.1).0 + 1) {

            for y in ((oper.range.0).1)..((oper.range.1).1 + 1) {

                match oper.op_type {
                    OperationType::On => light_matrix[x][y] = true,
                    OperationType::Off => light_matrix[x][y] = false,
                    OperationType::Toggle => light_matrix[x][y] = !light_matrix[x][y],
                }
            }
        }
    }

    let sum = light_matrix.iter().fold(0, |total_acc, &row| {
        total_acc +
        row.iter().fold(0, |acc, &light_state| {
            if light_state {
                acc + 1
            } else {
                acc
            }
        })
    });

    println!("Number of light lit after all operations: {}", sum);

    let mut brt_matrix = [[0 as u32; 1000]; 1000];

    for oper in oper_list.iter() {
        // + 1 because the ranges are inclusive
        for x in ((oper.range.0).0)..((oper.range.1).0 + 1) {

            for y in ((oper.range.0).1)..((oper.range.1).1 + 1) {

                match oper.op_type {
                    OperationType::On => brt_matrix[x][y] += 1,
                    OperationType::Off => {
                        if brt_matrix[x][y] != 0 {
                            brt_matrix[x][y] -= 1
                        }
                    }
                    OperationType::Toggle => brt_matrix[x][y] += 2,
                }
            }
        }
    }

    let brt_sum = brt_matrix.iter().fold(0, |total_acc, &row| {
        total_acc + row.iter().fold(0, |acc, &light_state| acc + light_state)
    });

    println!("Total brightness after all operations: {}", brt_sum);
}
<|endoftext|>


<commit_before>use std::collections::{VecDeque};
use std::char;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        InvalidHexValue(c: u8)
        InvalidOctValue(c: u8)
        InvalidUnicodeChar(c: u32)
        UnexpectedEnd
    }
}

fn hex_to_digit(c: u8) -> Result<u8, Error> {
    Ok(match c {
        b'0' ... b'9' => c - b'0',
        b'a' ... b'f' => c - b'a' + 10,
        b'A' ... b'F' => c - b'A' + 10,
        _ => return Err(Error::InvalidHexValue(c)),
    })
}

fn oct_to_digit(c: u8) -> Result<u8, Error> {
    Ok(match c {
        b'0' ... b'7' => c - b'0',
        _ => return Err(Error::InvalidOctValue(c)),
    })
}

pub fn unescape(s: &[u8], unicode: bool) -> Result<Vec<u8>, Error> {
    let mut buf = Vec::with_capacity(s.len());
    let mut oct_buf = VecDeque::with_capacity(3);

    let mut i = 0;

    macro_rules! read {
        () => ({
            match s.get(i) {
                None => return Err(Error::UnexpectedEnd),
                Some(c) => {
                    i += 1;
                    *c
                }
            }
        })
    }

    macro_rules! peek {
        () => ({
            s.get(i).map(|c| *c)
        })
    }

    loop {
        if i >= s.len() {
            return Ok(buf)
        }

        let c = read!();

        if c != b'\\' {
            buf.push(c);
            continue
        }

        let marker = read!();

        match marker {
            b'\n' => (),
            b'\\' => buf.push(b'\\'),
            b'\'' => buf.push(b'\''),
            b'"' => buf.push(b'"'),
            b'a' => buf.push(b'\x07'),
            b'b' => buf.push(b'\x08'),
            b'f' => buf.push(b'\x0c'),
            b'n' => buf.push(b'\n'),
            b'r' => buf.push(b'\r'),
            b't' => buf.push(b'\t'),
            b'v' => buf.push(b'\x0b'),
            b'x' => {
                let first = try!(hex_to_digit(read!()));
                let second = try!(hex_to_digit(read!()));
                buf.push(first * 15 + second)
            }
            b'0' ... b'7' => {
                oct_buf.push_front(try!(oct_to_digit(marker)));
                peek!().and_then(|c| oct_to_digit(c).ok()).map(|s| {
                    oct_buf.push_front(s);
                    i += 1;

                    peek!().and_then(|c| oct_to_digit(c).ok()).map(|s| {
                        oct_buf.push_front(s);
                        i += 1;
                    });
                });
                let value = oct_buf.iter().enumerate().fold(0u16, |acc, (i, &v)| acc + v as u16 * (8u16.pow(i as u32)));
                oct_buf.clear();
                buf.push(if value > 255 {
                    255
                } else {
                    value as u8
                });
                continue
            },
            b'u' if unicode => {
                let bytes: Vec<u8> = try!((0..4).map(|_| Ok(read!())).collect());
                let digits: Vec<u8> = try!(bytes.into_iter().map(hex_to_digit).collect());
                let value = digits.iter().enumerate().fold(0u32, |acc, (i, &v)| acc + v as u32 * (15u32.pow(i as u32)));
                match char::from_u32(value) {
                    Some(c) => buf.extend_from_slice(&digits),
                    None => return Err(Error::InvalidUnicodeChar(value)),
                }
                ()
            },
            b'U' if unicode => {
                let bytes: Vec<u8> = try!((0..8).map(|_| Ok(read!())).collect());
                let digits: Vec<u8> = try!(bytes.into_iter().map(hex_to_digit).collect());
                let value = digits.iter().enumerate().fold(0u32, |acc, (i, &v)| acc + v as u32 * (15u32.pow(i as u32)));
                match char::from_u32(value) {
                    Some(c) => buf.extend_from_slice(&digits),
                    None => return Err(Error::InvalidUnicodeChar(value)),
                }
                ()
            },
            _ => {
                buf.push(b'\\');
                buf.push(marker);
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::{unescape};

    #[test]
    fn test_unescape() {
        assert_eq!(unescape(b"foo", false).unwrap(), b"foo");
        assert_eq!(unescape(b"f\\noo", false).unwrap(), b"f\noo");
        assert_eq!(unescape(b"f\\x01oo", false).unwrap(), b"f\x01oo");
        assert_eq!(unescape(b"f\\375oo", false).unwrap(), b"f\xfdoo");
        assert_eq!(unescape(b"f\\75oo", false).unwrap(), b"f\x3doo");
        assert_eq!(unescape(b"f\\5oo", false).unwrap(), b"f\x05oo");
        assert_eq!(unescape(b"f\\oo", false).unwrap(), b"f\\oo");
        assert_eq!(unescape(b"f\\coo", false).unwrap(), b"f\\coo");
    }
}<commit_msg>Remove unicode escaping support<commit_after>use std::collections::{VecDeque};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        InvalidHexValue(c: u8)
        InvalidOctValue(c: u8)
        UnexpectedEnd
    }
}

fn hex_to_digit(c: u8) -> Result<u8, Error> {
    Ok(match c {
        b'0' ... b'9' => c - b'0',
        b'a' ... b'f' => c - b'a' + 10,
        b'A' ... b'F' => c - b'A' + 10,
        _ => return Err(Error::InvalidHexValue(c)),
    })
}

fn oct_to_digit(c: u8) -> Result<u8, Error> {
    Ok(match c {
        b'0' ... b'7' => c - b'0',
        _ => return Err(Error::InvalidOctValue(c)),
    })
}

pub fn unescape(s: &[u8], unicode: bool) -> Result<Vec<u8>, Error> {
    let mut buf = Vec::with_capacity(s.len());
    let mut oct_buf = VecDeque::with_capacity(3);

    let mut i = 0;

    macro_rules! read {
        () => ({
            match s.get(i) {
                None => return Err(Error::UnexpectedEnd),
                Some(c) => {
                    i += 1;
                    *c
                }
            }
        })
    }

    macro_rules! peek {
        () => ({
            s.get(i).map(|c| *c)
        })
    }

    loop {
        if i >= s.len() {
            return Ok(buf)
        }

        let c = read!();

        if c != b'\\' {
            buf.push(c);
            continue
        }

        let marker = read!();

        match marker {
            b'\n' => (),
            b'\\' => buf.push(b'\\'),
            b'\'' => buf.push(b'\''),
            b'"' => buf.push(b'"'),
            b'a' => buf.push(b'\x07'),
            b'b' => buf.push(b'\x08'),
            b'f' => buf.push(b'\x0c'),
            b'n' => buf.push(b'\n'),
            b'r' => buf.push(b'\r'),
            b't' => buf.push(b'\t'),
            b'v' => buf.push(b'\x0b'),
            b'x' => {
                let first = try!(hex_to_digit(read!()));
                let second = try!(hex_to_digit(read!()));
                buf.push(first * 15 + second)
            }
            b'0' ... b'7' => {
                oct_buf.push_front(try!(oct_to_digit(marker)));
                peek!().and_then(|c| oct_to_digit(c).ok()).map(|s| {
                    oct_buf.push_front(s);
                    i += 1;

                    peek!().and_then(|c| oct_to_digit(c).ok()).map(|s| {
                        oct_buf.push_front(s);
                        i += 1;
                    });
                });
                let value = oct_buf.iter().enumerate().fold(0u16, |acc, (i, &v)| acc + v as u16 * (8u16.pow(i as u32)));
                oct_buf.clear();
                buf.push(if value > 255 {
                    255
                } else {
                    value as u8
                });
                continue
            },
            b'u' if unicode => unimplemented!(),
            b'U' if unicode => unimplemented!(),
            _ => {
                buf.push(b'\\');
                buf.push(marker);
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::{unescape};

    #[test]
    fn test_unescape() {
        assert_eq!(unescape(b"foo", false).unwrap(), b"foo");
        assert_eq!(unescape(b"f\\noo", false).unwrap(), b"f\noo");
        assert_eq!(unescape(b"f\\x01oo", false).unwrap(), b"f\x01oo");
        assert_eq!(unescape(b"f\\375oo", false).unwrap(), b"f\xfdoo");
        assert_eq!(unescape(b"f\\75oo", false).unwrap(), b"f\x3doo");
        assert_eq!(unescape(b"f\\5oo", false).unwrap(), b"f\x05oo");
        assert_eq!(unescape(b"f\\oo", false).unwrap(), b"f\\oo");
        assert_eq!(unescape(b"f\\coo", false).unwrap(), b"f\\coo");
    }
}<|endoftext|>


<commit_before>use serde::{Serialize, Deserialize};

pub trait Cell: Clone + Serialize + Deserialize {
    type Coord: Coord;

    fn step<'a, I>(&'a self, neighbors: I) -> Self where I: Iterator<Item = Option<&'a Self>>;

    fn with_coord<C: Coord>(C) -> Self;
    fn coord(&self) -> &Self::Coord;
    fn set_coord<C: Coord>(&mut self, &C);
}

pub trait Nhood {
    type Coord: Coord;

    fn neighbors(&self, &Self::Coord) -> Vec<Self::Coord>;

    fn neighbors_count(&self) -> usize;
}

pub trait Coord: Clone + Serialize + Deserialize {
    fn from_2d(x: i32, y: i32) -> Self;

    fn x(&self) -> i32;
    fn y(&self) -> i32;
    fn z(&self) -> i32 {
        0
    }
}

pub trait Grid {
    type Cell: Cell;
    type Coord: Coord;

    fn step(&mut self);

    fn cells(&self) -> &Vec<Self::Cell>;
    fn dimensions(&self) -> Self::Coord;

    fn set_cells(&mut self, Vec<Self::Cell>);
}

pub trait Consumer {
    type Cell: Cell;

    fn consume<G: Grid<Cell = Self::Cell>>(&mut self, repr: &mut G);
}

pub trait Engine {
    fn run_times(&mut self, times: i64);
}
<commit_msg>Dense trait methods.<commit_after>use serde::{Serialize, Deserialize};

pub trait Cell: Clone + Serialize + Deserialize {
    type Coord: Coord;

    fn step<'a, I>(&'a self, neighbors: I) -> Self where I: Iterator<Item = Option<&'a Self>>;

    fn with_coord<C: Coord>(C) -> Self;
    fn coord(&self) -> &Self::Coord;
    fn set_coord<C: Coord>(&mut self, &C);
}

pub trait Nhood {
    type Coord: Coord;

    fn neighbors(&self, &Self::Coord) -> Vec<Self::Coord>;
    fn neighbors_count(&self) -> usize;
}

pub trait Coord: Clone + Serialize + Deserialize {
    fn from_2d(x: i32, y: i32) -> Self;

    fn x(&self) -> i32;
    fn y(&self) -> i32;
    fn z(&self) -> i32 {
        0
    }
}

pub trait Grid {
    type Cell: Cell;
    type Coord: Coord;

    fn step(&mut self);

    fn cells(&self) -> &Vec<Self::Cell>;
    fn dimensions(&self) -> Self::Coord;

    fn set_cells(&mut self, Vec<Self::Cell>);
}

pub trait Consumer {
    type Cell: Cell;

    fn consume<G: Grid<Cell = Self::Cell>>(&mut self, &mut G);
}

pub trait Engine {
    fn run_times(&mut self, i64);
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use std::panic::{self, UnwindSafe};
use std::process;

pub fn catch_unwind<F, R>(label: &'static str, foreign_call: F) -> R
where
    F: FnOnce() -> R + UnwindSafe,
{
    match panic::catch_unwind(foreign_call) {
        Ok(ret) => ret,
        Err(_) => abort(label),
    }
}

#[cold]
fn abort(label: &'static str) -> ! {
    let mut stdout = io::stdout();
    let _ = writeln!(stdout, "Error: panic in ffi function {}, aborting.", label);
    process::abort();
}
<commit_msg>Accept non-UnwindSafe extern Rust types in extern Rust signatures<commit_after>use std::io::{self, Write};
use std::panic::{self, AssertUnwindSafe};
use std::process;

pub fn catch_unwind<F, R>(label: &'static str, foreign_call: F) -> R
where
    F: FnOnce() -> R,
{
    // Regarding the AssertUnwindSafe: we immediately abort on panic so it
    // doesn't matter whether the types involved are unwind-safe. The UnwindSafe
    // bound on catch_unwind is about ensuring nothing is in a broken state if
    // your program plans to continue after the panic.
    match panic::catch_unwind(AssertUnwindSafe(foreign_call)) {
        Ok(ret) => ret,
        Err(_) => abort(label),
    }
}

#[cold]
fn abort(label: &'static str) -> ! {
    let mut stdout = io::stdout();
    let _ = writeln!(stdout, "Error: panic in ffi function {}, aborting.", label);
    process::abort();
}
<|endoftext|>


<commit_before>use crate::util::clean;
use console::{style, Emoji};
use indicatif::ProgressBar;
use std::fs;
use std::process::Command;
use toml::Value;

pub fn verify(start_at: Option<&str>) -> Result<(), ()> {
    let toml: Value = fs::read_to_string("info.toml").unwrap().parse().unwrap();
    let tomlvec: &Vec<Value> = toml.get("exercises").unwrap().as_array().unwrap();
    let mut hit_start_at = false;

    for i in tomlvec {
        let path = i.get("path").unwrap().as_str().unwrap();

        if let Some(start_at) = start_at {
            if start_at.ends_with(path) {
                hit_start_at = true;
            } else if !hit_start_at {
                continue;
            }
        }

        match i.get("mode").unwrap().as_str().unwrap() {
            "test" => test(i.get("path").unwrap().as_str().unwrap())?,
            "compile" => compile_only(i.get("path").unwrap().as_str().unwrap())?,
            _ => (),
        }
    }
    Ok(())
}

fn compile_only(filename: &str) -> Result<(), ()> {
    let progress_bar = ProgressBar::new_spinner();
    progress_bar.set_message(format!("Compiling {}...", filename).as_str());
    progress_bar.enable_steady_tick(100);
    let compilecmd = Command::new("rustc")
        .args(&[filename, "-o", "temp", "--color", "always"])
        .output()
        .expect("fail");
    progress_bar.finish_and_clear();
    if compilecmd.status.success() {
        let formatstr = format!(
            "{} Successfully compiled {}!",
            Emoji("✅", "✓"),
            filename
        );
        println!("{}", style(formatstr).green());
        clean();
        Ok(())
    } else {
        let formatstr = format!(
            "{} Compilation of {} failed! Compiler error message:\n",
            Emoji("⚠ ", "!"),
            filename
        );
        println!("{}", style(formatstr).red());
        println!("{}", String::from_utf8_lossy(&compilecmd.stderr));
        clean();
        Err(())
    }
}

pub fn test(filename: &str) -> Result<(), ()> {
    let progress_bar = ProgressBar::new_spinner();
    progress_bar.set_message(format!("Testing {}...", filename).as_str());
    progress_bar.enable_steady_tick(100);
    let testcmd = Command::new("rustc")
        .args(&["--test", filename, "-o", "temp", "--color", "always"])
        .output()
        .expect("fail");
    if testcmd.status.success() {
        progress_bar.set_message(format!("Running {}...", filename).as_str());
        let runcmd = Command::new("./temp").output().expect("fail");
        progress_bar.finish_and_clear();

        if runcmd.status.success() {
            let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename);
            println!("{}", style(formatstr).green());
            clean();
            Ok(())
        } else {
            let formatstr = format!(
                "{} Testing of {} failed! Please try again. Here's the output:",
                Emoji("⚠ ", "!"),
                filename
            );
            println!("{}", style(formatstr).red());
            println!("{}", String::from_utf8_lossy(&runcmd.stdout));
            clean();
            Err(())
        }
    } else {
        progress_bar.finish_and_clear();
        let formatstr = format!(
            "{} Compiling of {} failed! Please try again. Here's the output:",
            Emoji("⚠ ", "!"),
            filename
        );
        println!("{}", style(formatstr).red());
        println!("{}", String::from_utf8_lossy(&testcmd.stderr));
        clean();
        Err(())
    }
}
<commit_msg>deduplicate<commit_after>use crate::util::clean;
use console::{style, Emoji};
use indicatif::ProgressBar;
use std::fs;
use std::process::Command;
use toml::Value;

pub fn verify(start_at: Option<&str>) -> Result<(), ()> {
    let toml: Value = fs::read_to_string("info.toml").unwrap().parse().unwrap();
    let tomlvec: &Vec<Value> = toml.get("exercises").unwrap().as_array().unwrap();
    let mut hit_start_at = false;

    for i in tomlvec {
        let path = i.get("path").unwrap().as_str().unwrap();

        if let Some(start_at) = start_at {
            if start_at.ends_with(path) {
                hit_start_at = true;
            } else if !hit_start_at {
                continue;
            }
        }

        match i.get("mode").unwrap().as_str().unwrap() {
            "test" => test(path)?,
            "compile" => compile_only(path)?,
            _ => (),
        }
    }
    Ok(())
}

fn compile_only(filename: &str) -> Result<(), ()> {
    let progress_bar = ProgressBar::new_spinner();
    progress_bar.set_message(format!("Compiling {}...", filename).as_str());
    progress_bar.enable_steady_tick(100);
    let compilecmd = Command::new("rustc")
        .args(&[filename, "-o", "temp", "--color", "always"])
        .output()
        .expect("fail");
    progress_bar.finish_and_clear();
    if compilecmd.status.success() {
        let formatstr = format!(
            "{} Successfully compiled {}!",
            Emoji("✅", "✓"),
            filename
        );
        println!("{}", style(formatstr).green());
        clean();
        Ok(())
    } else {
        let formatstr = format!(
            "{} Compilation of {} failed! Compiler error message:\n",
            Emoji("⚠ ", "!"),
            filename
        );
        println!("{}", style(formatstr).red());
        println!("{}", String::from_utf8_lossy(&compilecmd.stderr));
        clean();
        Err(())
    }
}

pub fn test(filename: &str) -> Result<(), ()> {
    let progress_bar = ProgressBar::new_spinner();
    progress_bar.set_message(format!("Testing {}...", filename).as_str());
    progress_bar.enable_steady_tick(100);
    let testcmd = Command::new("rustc")
        .args(&["--test", filename, "-o", "temp", "--color", "always"])
        .output()
        .expect("fail");
    if testcmd.status.success() {
        progress_bar.set_message(format!("Running {}...", filename).as_str());
        let runcmd = Command::new("./temp").output().expect("fail");
        progress_bar.finish_and_clear();

        if runcmd.status.success() {
            let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename);
            println!("{}", style(formatstr).green());
            clean();
            Ok(())
        } else {
            let formatstr = format!(
                "{} Testing of {} failed! Please try again. Here's the output:",
                Emoji("⚠ ", "!"),
                filename
            );
            println!("{}", style(formatstr).red());
            println!("{}", String::from_utf8_lossy(&runcmd.stdout));
            clean();
            Err(())
        }
    } else {
        progress_bar.finish_and_clear();
        let formatstr = format!(
            "{} Compiling of {} failed! Please try again. Here's the output:",
            Emoji("⚠ ", "!"),
            filename
        );
        println!("{}", style(formatstr).red());
        println!("{}", String::from_utf8_lossy(&testcmd.stderr));
        clean();
        Err(())
    }
}
<|endoftext|>


<commit_before>//! Test cases of the multirust command that do not depend on the
//! dist server, mostly derived from multirust/test-v2.sh

extern crate rustup_dist;
extern crate rustup_utils;
extern crate rustup_mock;
extern crate time;
use rustup_mock::clitools::{self, Config, Scenario,
                               expect_stdout_ok, expect_stderr_ok,
                               expect_ok, expect_err, run,
                               this_host_triple};
use rustup_utils::{raw, utils};

use time::Duration;
use std::ops::Sub;
use std::ops::Add;

macro_rules! for_host { ($s: expr) => (&format!($s, this_host_triple())) }

pub fn setup(f: &Fn(&Config)) {
    clitools::setup(Scenario::SimpleV2, f);
}

#[test]
fn smoke_test() {
    setup(&|config| {
        expect_ok(config, &["rustup", "--version"]);
    });
}

#[test]
fn no_colors_in_piped_error_output() {
    setup(&|config| {
        let out = run(config, "rustc", &[], &[]);
        assert!(!out.ok);
        assert!(!out.stderr.contains("\u{1b}"));
    });
}

#[test]
fn rustc_with_bad_multirust_toolchain_env_var() {
    setup(&|config| {
        let out = run(config, "rustc", &[], &[("RUSTUP_TOOLCHAIN", "bogus")]);
        assert!(!out.ok);
        assert!(out.stderr.contains("toolchain 'bogus' is not installed"));
    });
}

#[test]
fn custom_invalid_names() {
    setup(&|config| {
        expect_err(config, &["rustup", "toolchain", "link", "nightly",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'nightly-{0}'"));
        expect_err(config, &["rustup", "toolchain", "link", "beta",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'beta-{0}'"));
        expect_err(config, &["rustup", "toolchain", "link", "stable",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'stable-{0}'"));
    });
}

#[test]
fn custom_invalid_names_with_archive_dates() {
    setup(&|config| {
        expect_err(config, &["rustup", "toolchain", "link", "nightly-2015-01-01",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'nightly-2015-01-01-{0}'"));
        expect_err(config, &["rustup", "toolchain", "link", "beta-2015-01-01",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'beta-2015-01-01-{0}'"));
        expect_err(config, &["rustup", "toolchain", "link", "stable-2015-01-01",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'stable-2015-01-01-{0}'"));
    });
}

#[test]
fn running_with_v2_metadata() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);
        // Replace the metadata version
        rustup_utils::raw::write_file(&config.rustupdir.join("version"),
                               "2").unwrap();
        expect_err(config, &["rustup", "default", "nightly"],
                   "rustup's metadata is out of date. run `rustup self upgrade-data`");
        expect_err(config, &["rustc", "--version"],
                   "rustup's metadata is out of date. run `rustup self upgrade-data`");
    });
}

// The thing that changed in the version bump from 2 -> 12 was the
// toolchain format. Check that on the upgrade all the toolchains.
// are deleted.
#[test]
fn upgrade_v2_metadata_to_v12() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);
        // Replace the metadata version
        rustup_utils::raw::write_file(&config.rustupdir.join("version"),
                               "2").unwrap();
        expect_stderr_ok(config, &["rustup", "self", "upgrade-data"],
                         "warning: this upgrade will remove all existing toolchains. you will need to reinstall them");
        expect_err(config, &["rustc", "--version"],
                   for_host!("toolchain 'nightly-{0}' is not installed"));
        expect_ok(config, &["rustup", "update", "nightly"]);
        expect_stdout_ok(config, &["rustc", "--version"],
                         "hash-n-2");
    });
}

// Regression test for newline placement
#[test]
fn update_all_no_update_whitespace() {
    setup(&|config| {
        expect_stdout_ok(config, &["rustup", "update", "nightly"],
for_host!(r"
  nightly-{} installed - 1.3.0 (hash-n-2)

"));
    });
}

// Issue #145
#[test]
fn update_works_without_term() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["update", "nightly"]);
        clitools::env(config, &mut cmd);
        cmd.env_remove("TERM");

        let out = cmd.output().unwrap();
        assert!(out.status.success());
    });
}

// Issue #140
// Don't panic when `target`, `update` etc. are called without subcommands.
#[test]
fn subcommand_required_for_target() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["target"]);
        clitools::env(config, &mut cmd);
        let out = cmd.output().unwrap();
        assert!(!out.status.success());
        assert!(out.status.code().unwrap() != 101);
    });
}

// Issue #140
// Don't panic when `target`, `update` etc. are called without subcommands.
#[test]
fn subcommand_required_for_toolchain() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["toolchain"]);
        clitools::env(config, &mut cmd);
        let out = cmd.output().unwrap();
        assert!(!out.status.success());
        assert!(out.status.code().unwrap() != 101);
    });
}

// Issue #140
// Don't panic when `target`, `update` etc. are called without subcommands.
#[test]
fn subcommand_required_for_override() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["override"]);
        clitools::env(config, &mut cmd);
        let out = cmd.output().unwrap();
        assert!(!out.status.success());
        assert!(out.status.code().unwrap() != 101);
    });
}

// Issue #140
// Don't panic when `target`, `update` etc. are called without subcommands.
#[test]
fn subcommand_required_for_self() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["self"]);
        clitools::env(config, &mut cmd);
        let out = cmd.output().unwrap();
        assert!(!out.status.success());
        assert!(out.status.code().unwrap() != 101);
    });
}

#[test]
fn multi_host_smoke_test() {
    // FIXME: Unfortunately the list of supported hosts is hard-coded,
    // so we have to use the triple of a host we actually test on. That means
    // that when we're testing on that host we can't test 'multi-host'.
    let trip = this_host_triple();
    if trip == clitools::MULTI_ARCH1 {
        return;
    }

    clitools::setup(Scenario::MultiHost, &|config| {
        let ref toolchain = format!("nightly-{}", clitools::MULTI_ARCH1);
        expect_ok(config, &["rustup", "default", toolchain]);
        expect_stdout_ok(config, &["rustc", "--version"],
                         "xxxx-n-2"); // cross-host mocks have their own versions
    });
}

#[test]
fn custom_toolchain_cargo_fallback_proxy() {
    setup(&|config| {
        let path = config.customdir.join("custom-1");

        expect_ok(config, &["rustup", "toolchain", "link", "mytoolchain",
                            &path.to_string_lossy()]);
        expect_ok(config, &["rustup", "default", "mytoolchain"]);

        expect_ok(config, &["rustup", "update", "stable"]);
        expect_stdout_ok(config, &["cargo", "--version"],
                         "hash-s-2");

        expect_ok(config, &["rustup", "update", "beta"]);
        expect_stdout_ok(config, &["cargo", "--version"],
                         "hash-b-2");

        expect_ok(config, &["rustup", "update", "nightly"]);
        expect_stdout_ok(config, &["cargo", "--version"],
                         "hash-n-2");
    });
}

#[test]
fn custom_toolchain_cargo_fallback_run() {
    setup(&|config| {
        let path = config.customdir.join("custom-1");

        expect_ok(config, &["rustup", "toolchain", "link", "mytoolchain",
                            &path.to_string_lossy()]);
        expect_ok(config, &["rustup", "default", "mytoolchain"]);

        expect_ok(config, &["rustup", "update", "stable"]);
        expect_stdout_ok(config, &["rustup", "run", "mytoolchain",
                                   "cargo", "--version"],
                         "hash-s-2");

        expect_ok(config, &["rustup", "update", "beta"]);
        expect_stdout_ok(config, &["rustup", "run", "mytoolchain",
                                   "cargo", "--version"],
                         "hash-b-2");

        expect_ok(config, &["rustup", "update", "nightly"]);
        expect_stdout_ok(config, &["rustup", "run", "mytoolchain",
                                   "cargo", "--version"],
                         "hash-n-2");

    });
}

#[test]
fn multirust_env_compat() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["update", "nightly"]);
        clitools::env(config, &mut cmd);
        cmd.env_remove("RUSTUP_HOME");
        cmd.env("MULTIRUST_HOME", &config.rustupdir);
        let out = cmd.output().unwrap();
        assert!(out.status.success());
        let stderr = String::from_utf8(out.stderr).unwrap();
        assert!(stderr.contains("environment variable MULTIRUST_HOME is deprecated. Use RUSTUP_HOME"));
    });
}

#[test]
fn toolchains_are_resolved_early() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);

        let full_toolchain = format!("nightly-{}", this_host_triple());
        expect_stderr_ok(config, &["rustup", "default", &full_toolchain],
                         &format!("info: using existing install for '{}'", full_toolchain));
    });
}

// #190
#[test]
fn proxies_pass_empty_args() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);
        expect_ok(config, &["rustup", "run", "nightly", "rustc", "--empty-arg-test", ""]);
    });
}

#[test]
fn enabling_telemetry_and_compiling_creates_log() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "stable"]);
        expect_ok(config, &["rustup", "telemetry", "on"]);
        expect_ok(config, &["rustc", "--version"]);

        let telemetry_dir = config.rustupdir.join("telemetry");
        let _ = utils::assert_is_directory(telemetry_dir.as_path());

        let out = telemetry_dir.read_dir();
        assert!(out.is_ok());

        let contents = out.unwrap();
        assert!(contents.count() > 0);
    });
}

#[test]
fn telemetry_cleanup_removes_old_files() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "stable"]);
        expect_ok(config, &["rustup", "telemetry", "on"]);

        let telemetry_dir = config.rustupdir.join("telemetry");

        let mut d = time::now_utc().sub(Duration::days(120));
        let one_day = time::Duration::days(1);

        for x in 0..110 {
            let file_name = format!("log-{}-{:02}-{:02}.json", d.tm_year + 1900, d.tm_mon + 1, d.tm_mday);
            let _ = raw::write_file(&telemetry_dir.join(&file_name), "");
            d = d.add(one_day);
        }

        expect_ok(config, &["rustc", "--version"]);

        let out = telemetry_dir.read_dir();
        assert!(out.is_ok());

        let contents = out.unwrap();
        let count = contents.count();

        assert!(count == 100);
    });
}
<commit_msg>Unused variable<commit_after>//! Test cases of the multirust command that do not depend on the
//! dist server, mostly derived from multirust/test-v2.sh

extern crate rustup_dist;
extern crate rustup_utils;
extern crate rustup_mock;
extern crate time;
use rustup_mock::clitools::{self, Config, Scenario,
                               expect_stdout_ok, expect_stderr_ok,
                               expect_ok, expect_err, run,
                               this_host_triple};
use rustup_utils::{raw, utils};

use time::Duration;
use std::ops::Sub;
use std::ops::Add;

macro_rules! for_host { ($s: expr) => (&format!($s, this_host_triple())) }

pub fn setup(f: &Fn(&Config)) {
    clitools::setup(Scenario::SimpleV2, f);
}

#[test]
fn smoke_test() {
    setup(&|config| {
        expect_ok(config, &["rustup", "--version"]);
    });
}

#[test]
fn no_colors_in_piped_error_output() {
    setup(&|config| {
        let out = run(config, "rustc", &[], &[]);
        assert!(!out.ok);
        assert!(!out.stderr.contains("\u{1b}"));
    });
}

#[test]
fn rustc_with_bad_multirust_toolchain_env_var() {
    setup(&|config| {
        let out = run(config, "rustc", &[], &[("RUSTUP_TOOLCHAIN", "bogus")]);
        assert!(!out.ok);
        assert!(out.stderr.contains("toolchain 'bogus' is not installed"));
    });
}

#[test]
fn custom_invalid_names() {
    setup(&|config| {
        expect_err(config, &["rustup", "toolchain", "link", "nightly",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'nightly-{0}'"));
        expect_err(config, &["rustup", "toolchain", "link", "beta",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'beta-{0}'"));
        expect_err(config, &["rustup", "toolchain", "link", "stable",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'stable-{0}'"));
    });
}

#[test]
fn custom_invalid_names_with_archive_dates() {
    setup(&|config| {
        expect_err(config, &["rustup", "toolchain", "link", "nightly-2015-01-01",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'nightly-2015-01-01-{0}'"));
        expect_err(config, &["rustup", "toolchain", "link", "beta-2015-01-01",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'beta-2015-01-01-{0}'"));
        expect_err(config, &["rustup", "toolchain", "link", "stable-2015-01-01",
                             "foo"],
                   for_host!("invalid custom toolchain name: 'stable-2015-01-01-{0}'"));
    });
}

#[test]
fn running_with_v2_metadata() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);
        // Replace the metadata version
        rustup_utils::raw::write_file(&config.rustupdir.join("version"),
                               "2").unwrap();
        expect_err(config, &["rustup", "default", "nightly"],
                   "rustup's metadata is out of date. run `rustup self upgrade-data`");
        expect_err(config, &["rustc", "--version"],
                   "rustup's metadata is out of date. run `rustup self upgrade-data`");
    });
}

// The thing that changed in the version bump from 2 -> 12 was the
// toolchain format. Check that on the upgrade all the toolchains.
// are deleted.
#[test]
fn upgrade_v2_metadata_to_v12() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);
        // Replace the metadata version
        rustup_utils::raw::write_file(&config.rustupdir.join("version"),
                               "2").unwrap();
        expect_stderr_ok(config, &["rustup", "self", "upgrade-data"],
                         "warning: this upgrade will remove all existing toolchains. you will need to reinstall them");
        expect_err(config, &["rustc", "--version"],
                   for_host!("toolchain 'nightly-{0}' is not installed"));
        expect_ok(config, &["rustup", "update", "nightly"]);
        expect_stdout_ok(config, &["rustc", "--version"],
                         "hash-n-2");
    });
}

// Regression test for newline placement
#[test]
fn update_all_no_update_whitespace() {
    setup(&|config| {
        expect_stdout_ok(config, &["rustup", "update", "nightly"],
for_host!(r"
  nightly-{} installed - 1.3.0 (hash-n-2)

"));
    });
}

// Issue #145
#[test]
fn update_works_without_term() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["update", "nightly"]);
        clitools::env(config, &mut cmd);
        cmd.env_remove("TERM");

        let out = cmd.output().unwrap();
        assert!(out.status.success());
    });
}

// Issue #140
// Don't panic when `target`, `update` etc. are called without subcommands.
#[test]
fn subcommand_required_for_target() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["target"]);
        clitools::env(config, &mut cmd);
        let out = cmd.output().unwrap();
        assert!(!out.status.success());
        assert!(out.status.code().unwrap() != 101);
    });
}

// Issue #140
// Don't panic when `target`, `update` etc. are called without subcommands.
#[test]
fn subcommand_required_for_toolchain() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["toolchain"]);
        clitools::env(config, &mut cmd);
        let out = cmd.output().unwrap();
        assert!(!out.status.success());
        assert!(out.status.code().unwrap() != 101);
    });
}

// Issue #140
// Don't panic when `target`, `update` etc. are called without subcommands.
#[test]
fn subcommand_required_for_override() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["override"]);
        clitools::env(config, &mut cmd);
        let out = cmd.output().unwrap();
        assert!(!out.status.success());
        assert!(out.status.code().unwrap() != 101);
    });
}

// Issue #140
// Don't panic when `target`, `update` etc. are called without subcommands.
#[test]
fn subcommand_required_for_self() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["self"]);
        clitools::env(config, &mut cmd);
        let out = cmd.output().unwrap();
        assert!(!out.status.success());
        assert!(out.status.code().unwrap() != 101);
    });
}

#[test]
fn multi_host_smoke_test() {
    // FIXME: Unfortunately the list of supported hosts is hard-coded,
    // so we have to use the triple of a host we actually test on. That means
    // that when we're testing on that host we can't test 'multi-host'.
    let trip = this_host_triple();
    if trip == clitools::MULTI_ARCH1 {
        return;
    }

    clitools::setup(Scenario::MultiHost, &|config| {
        let ref toolchain = format!("nightly-{}", clitools::MULTI_ARCH1);
        expect_ok(config, &["rustup", "default", toolchain]);
        expect_stdout_ok(config, &["rustc", "--version"],
                         "xxxx-n-2"); // cross-host mocks have their own versions
    });
}

#[test]
fn custom_toolchain_cargo_fallback_proxy() {
    setup(&|config| {
        let path = config.customdir.join("custom-1");

        expect_ok(config, &["rustup", "toolchain", "link", "mytoolchain",
                            &path.to_string_lossy()]);
        expect_ok(config, &["rustup", "default", "mytoolchain"]);

        expect_ok(config, &["rustup", "update", "stable"]);
        expect_stdout_ok(config, &["cargo", "--version"],
                         "hash-s-2");

        expect_ok(config, &["rustup", "update", "beta"]);
        expect_stdout_ok(config, &["cargo", "--version"],
                         "hash-b-2");

        expect_ok(config, &["rustup", "update", "nightly"]);
        expect_stdout_ok(config, &["cargo", "--version"],
                         "hash-n-2");
    });
}

#[test]
fn custom_toolchain_cargo_fallback_run() {
    setup(&|config| {
        let path = config.customdir.join("custom-1");

        expect_ok(config, &["rustup", "toolchain", "link", "mytoolchain",
                            &path.to_string_lossy()]);
        expect_ok(config, &["rustup", "default", "mytoolchain"]);

        expect_ok(config, &["rustup", "update", "stable"]);
        expect_stdout_ok(config, &["rustup", "run", "mytoolchain",
                                   "cargo", "--version"],
                         "hash-s-2");

        expect_ok(config, &["rustup", "update", "beta"]);
        expect_stdout_ok(config, &["rustup", "run", "mytoolchain",
                                   "cargo", "--version"],
                         "hash-b-2");

        expect_ok(config, &["rustup", "update", "nightly"]);
        expect_stdout_ok(config, &["rustup", "run", "mytoolchain",
                                   "cargo", "--version"],
                         "hash-n-2");

    });
}

#[test]
fn multirust_env_compat() {
    setup(&|config| {
        let mut cmd = clitools::cmd(config, "rustup", &["update", "nightly"]);
        clitools::env(config, &mut cmd);
        cmd.env_remove("RUSTUP_HOME");
        cmd.env("MULTIRUST_HOME", &config.rustupdir);
        let out = cmd.output().unwrap();
        assert!(out.status.success());
        let stderr = String::from_utf8(out.stderr).unwrap();
        assert!(stderr.contains("environment variable MULTIRUST_HOME is deprecated. Use RUSTUP_HOME"));
    });
}

#[test]
fn toolchains_are_resolved_early() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);

        let full_toolchain = format!("nightly-{}", this_host_triple());
        expect_stderr_ok(config, &["rustup", "default", &full_toolchain],
                         &format!("info: using existing install for '{}'", full_toolchain));
    });
}

// #190
#[test]
fn proxies_pass_empty_args() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);
        expect_ok(config, &["rustup", "run", "nightly", "rustc", "--empty-arg-test", ""]);
    });
}

#[test]
fn enabling_telemetry_and_compiling_creates_log() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "stable"]);
        expect_ok(config, &["rustup", "telemetry", "on"]);
        expect_ok(config, &["rustc", "--version"]);

        let telemetry_dir = config.rustupdir.join("telemetry");
        let _ = utils::assert_is_directory(telemetry_dir.as_path());

        let out = telemetry_dir.read_dir();
        assert!(out.is_ok());

        let contents = out.unwrap();
        assert!(contents.count() > 0);
    });
}

#[test]
fn telemetry_cleanup_removes_old_files() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "stable"]);
        expect_ok(config, &["rustup", "telemetry", "on"]);

        let telemetry_dir = config.rustupdir.join("telemetry");

        let mut d = time::now_utc().sub(Duration::days(120));
        let one_day = time::Duration::days(1);

        for _ in 0..110 {
            let file_name = format!("log-{}-{:02}-{:02}.json", d.tm_year + 1900, d.tm_mon + 1, d.tm_mday);
            let _ = raw::write_file(&telemetry_dir.join(&file_name), "");
            d = d.add(one_day);
        }

        expect_ok(config, &["rustc", "--version"]);

        let out = telemetry_dir.read_dir();
        assert!(out.is_ok());

        let contents = out.unwrap();
        let count = contents.count();

        assert!(count == 100);
    });
}
<|endoftext|>


<commit_before>//! Utilities for working with source code and printing nicely formatted
//! diagnostic information like warnings and errors.

#[macro_use]
extern crate failure;
extern crate itertools;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

#[cfg(feature = "serialization")]
extern crate serde;
#[cfg(feature = "serialization")]
#[macro_use]
extern crate serde_derive;

mod codemap;
mod filemap;
mod index;
mod span;

pub use codemap::CodeMap;
pub use filemap::{FileMap, FileName};
pub use filemap::{ByteIndexError, LineIndexError, LocationError, SpanError};
pub use index::{Index, Offset};
pub use index::{ByteIndex, ByteOffset};
pub use index::{ColumnIndex, ColumnNumber, ColumnOffset};
pub use index::{LineIndex, LineNumber, LineOffset};
pub use index::{RawIndex, RawOffset};
pub use span::{ByteSpan, Span};
<commit_msg>Documented the optional features that are available<commit_after>//! Utilities for working with source code and printing nicely formatted
//! diagnostic information like warnings and errors.
//!
//! # Optional Features
//!
//! Extra functionality is accessible by enabling feature flags. The features
//! currently available are:
//!
//! - **serialization** - Adds `Serialize` and `Deserialize` implementations
//!   for use with `serde`

#[macro_use]
extern crate failure;
extern crate itertools;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

#[cfg(feature = "serialization")]
extern crate serde;
#[cfg(feature = "serialization")]
#[macro_use]
extern crate serde_derive;

mod codemap;
mod filemap;
mod index;
mod span;

pub use codemap::CodeMap;
pub use filemap::{FileMap, FileName};
pub use filemap::{ByteIndexError, LineIndexError, LocationError, SpanError};
pub use index::{Index, Offset};
pub use index::{ByteIndex, ByteOffset};
pub use index::{ColumnIndex, ColumnNumber, ColumnOffset};
pub use index::{LineIndex, LineNumber, LineOffset};
pub use index::{RawIndex, RawOffset};
pub use span::{ByteSpan, Span};
<|endoftext|>


<commit_before>use libc::{c_char, c_double, c_int, c_void, size_t};
use std::mem;

#[cfg(target_arch="x86_64")]
#[path="ucontext_x86_64.rs"]
mod ucontext;

// This almost certainly needs to be made specific to just x86 (and
// add cases for the other processors).
#[cfg(not(target_arch="x86_64"))]
#[path="ucontext_generic.rs"]
mod ucontext;

// These almost certainly need to be replaced with something that is
// target/platform specific.
mod sigset;
mod sigstack;

#[cfg(target_arch="x86_64")]
const UNW_TDEP_CURSOR_LEN: usize = 127;

#[cfg(target_arch="x86_64")]
type unw_word_t = usize;

#[repr(C)]
pub struct unw_cursor_t {
    opaque: [unw_word_t; UNW_TDEP_CURSOR_LEN],
}

type unw_context_t = ucontext::ucontext_t;
type unw_regnum_t = c_int;

#[cfg(target_arch="x86_64")]
type unw_fpreg_t = c_double;

#[cfg(target_arch="x86_64")]
#[repr(C)]
struct unw_tdep_proc_info_t {

}

#[repr(C)]
struct unw_proc_info_t {
    start_ip: unw_word_t,
    end_ip: unw_word_t,
    lsda: unw_word_t,
    handler: unw_word_t,
    gp: unw_word_t,
    flags: unw_word_t,
    format: c_int,
    unwind_info_size: c_int,
    unwind_info: *mut c_void,
    extra: unw_tdep_proc_info_t,
}

#[repr(C)]
enum unw_save_loc_type_t {
    UNW_SLT_NONE,
    UNW_SLT_MEMORY,
    UNW_SLT_REG,
}

#[repr(C)]
struct unw_save_loc_t {
    type_: unw_save_loc_type_t,
    u: unw_word_t, // should be union { unw_word_t, unw_regnum_t }
    extra: unw_tdep_save_loc_t,
}

#[cfg(target_arch="x86_64")]
#[repr(C)]
struct unw_tdep_save_loc_t {

}

#[link(name="unwind")]
#[link(name="unwind-x86_64")]
extern {
    fn unw_getcontext(ucp: *mut unw_context_t) -> c_int;
    fn unw_init_local(c: *mut unw_cursor_t, ctxt: *mut unw_context_t);
    fn unw_step(cp: *mut unw_cursor_t);
    fn unw_get_reg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_word_t);
    fn unw_get_fpreg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_fpreg_t);
    fn unw_resume(cp: *mut unw_cursor_t);

    // I think the methods below are solely used for "remote
    // unwinding", which is not immediately relevant to me, so I need
    // not worry about finding definition for `struct unw_addr_space`.

    // fn unw_init_remote(c: *mut unw_cursor_t, as: unw_addr_space_t, arg: *mut c_void);
    // fn unw_create_addr_space(ap: *mut unw_accessors_t, byteorder: c_int);
    // fn unw_destroy_addr_space(as: unw_addr_space_t);
    // fn unw_get_accessors(as: unw_addr_space_t) -> *mut unw_accessors_t;
    // fn unw_flush_cache(as: unw_addr_space, lo: unw_word_t, hi: unw_word_t);
    // fn unw_set_caching_policy(as: unw_addr_space, policy: unw_caching_policy_t) -> c_int;

    fn unw_regname(regnum: unw_regnum_t) -> *const c_char;
    fn unw_get_proc_info(cp: *mut unw_cursor_t, pip: *mut unw_proc_info_t);
    fn unw_get_save_loc(cp: *mut unw_cursor_t, _int: c_int, loc: *mut unw_save_loc_t);
    fn unw_is_fpreg(r: unw_regnum_t) -> c_int;
    fn unw_is_signal_frame(cp: *mut unw_cursor_t) -> c_int;
    fn unw_get_proc_name(cp: *mut unw_cursor_t, bufp: *mut c_char, len: size_t, offp: *mut unw_word_t) -> c_int;

    // fn _U_dyn_register(di: *mut unw_dyn_info_t);
    // fn _U_dyn_cancel(di: *mut unw_dyn_info_t);
}

pub struct UnwindContext {
    repr: unw_context_t,
}

impl UnwindContext {
    pub fn new() -> UnwindContext {
        unsafe {
            let mut c = UnwindContext { repr: mem::uninitialized() };
            if 0 != unw_getcontext(&mut c.repr as *mut _) {
                panic!("got error from unw_getcontext");
            }
            return c;
        }
    }
}

<commit_msg>figured out the name I have to link in for `unw_getcontext`.<commit_after>use libc::{c_char, c_double, c_int, c_void, size_t};
use std::mem;

#[cfg(target_arch="x86_64")]
#[path="ucontext_x86_64.rs"]
mod ucontext;

// This almost certainly needs to be made specific to just x86 (and
// add cases for the other processors).
#[cfg(not(target_arch="x86_64"))]
#[path="ucontext_generic.rs"]
mod ucontext;

// These almost certainly need to be replaced with something that is
// target/platform specific.
mod sigset;
mod sigstack;

#[cfg(target_arch="x86_64")]
const UNW_TDEP_CURSOR_LEN: usize = 127;

#[cfg(target_arch="x86_64")]
type unw_word_t = usize;

#[repr(C)]
pub struct unw_cursor_t {
    opaque: [unw_word_t; UNW_TDEP_CURSOR_LEN],
}

type unw_context_t = ucontext::ucontext_t;
type unw_regnum_t = c_int;

#[cfg(target_arch="x86_64")]
type unw_fpreg_t = c_double;

#[cfg(target_arch="x86_64")]
#[repr(C)]
struct unw_tdep_proc_info_t {

}

#[repr(C)]
struct unw_proc_info_t {
    start_ip: unw_word_t,
    end_ip: unw_word_t,
    lsda: unw_word_t,
    handler: unw_word_t,
    gp: unw_word_t,
    flags: unw_word_t,
    format: c_int,
    unwind_info_size: c_int,
    unwind_info: *mut c_void,
    extra: unw_tdep_proc_info_t,
}

#[repr(C)]
enum unw_save_loc_type_t {
    UNW_SLT_NONE,
    UNW_SLT_MEMORY,
    UNW_SLT_REG,
}

#[repr(C)]
struct unw_save_loc_t {
    type_: unw_save_loc_type_t,
    u: unw_word_t, // should be union { unw_word_t, unw_regnum_t }
    extra: unw_tdep_save_loc_t,
}

#[cfg(target_arch="x86_64")]
#[repr(C)]
struct unw_tdep_save_loc_t {

}

#[link(name="unwind")]
#[link(name="unwind-x86_64")]
extern {
    #[cfg(target_arch="x86_64")]
    #[link_name="_Ux86_64_getcontext"]
    fn unw_getcontext(ucp: *mut unw_context_t) -> c_int;
    fn unw_init_local(c: *mut unw_cursor_t, ctxt: *mut unw_context_t);
    fn unw_step(cp: *mut unw_cursor_t);
    fn unw_get_reg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_word_t);
    fn unw_get_fpreg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_fpreg_t);
    fn unw_resume(cp: *mut unw_cursor_t);

    // I think the methods (and global) below are solely used for "remote
    // unwinding", which is not immediately relevant to me, so I need
    // not worry about finding definition for `struct unw_addr_space`.

    // static unw_local_addr_space: unw_addr_space_t;
    // fn unw_init_remote(c: *mut unw_cursor_t, as: unw_addr_space_t, arg: *mut c_void);
    // fn unw_create_addr_space(ap: *mut unw_accessors_t, byteorder: c_int);
    // fn unw_destroy_addr_space(as: unw_addr_space_t);
    // fn unw_get_accessors(as: unw_addr_space_t) -> *mut unw_accessors_t;
    // fn unw_flush_cache(as: unw_addr_space, lo: unw_word_t, hi: unw_word_t);
    // fn unw_set_caching_policy(as: unw_addr_space, policy: unw_caching_policy_t) -> c_int;

    fn unw_regname(regnum: unw_regnum_t) -> *const c_char;
    fn unw_get_proc_info(cp: *mut unw_cursor_t, pip: *mut unw_proc_info_t);
    fn unw_get_save_loc(cp: *mut unw_cursor_t, _int: c_int, loc: *mut unw_save_loc_t);
    fn unw_is_fpreg(r: unw_regnum_t) -> c_int;
    fn unw_is_signal_frame(cp: *mut unw_cursor_t) -> c_int;
    fn unw_get_proc_name(cp: *mut unw_cursor_t, bufp: *mut c_char, len: size_t, offp: *mut unw_word_t) -> c_int;

    // fn _U_dyn_register(di: *mut unw_dyn_info_t);
    // fn _U_dyn_cancel(di: *mut unw_dyn_info_t);
}

pub struct UnwindContext {
    repr: unw_context_t,
}

impl UnwindContext {
    pub fn new() -> UnwindContext {
        unsafe {
            let mut c = UnwindContext { repr: mem::uninitialized() };
            if 0 != unw_getcontext(&mut c.repr as *mut _) {
                panic!("got error from unw_getcontext");
            }
            return c;
        }
    }
}

<|endoftext|>


<commit_before>use lapin::{
    message::DeliveryResult, options::*, publisher_confirm::Confirmation, types::FieldTable,
    BasicProperties, Connection, ConnectionProperties, ConsumerDelegate,
};
use log::info;
use std::{future::Future, pin::Pin};

#[derive(Clone, Debug)]
struct Subscriber;

impl ConsumerDelegate for Subscriber {
    fn on_new_delivery(
        &self,
        delivery: DeliveryResult,
    ) -> Pin<Box<dyn Future<Output = ()> + Send>> {
        Box::pin(async move {
            if let Ok(Some((channel, delivery))) = delivery {
                channel
                    .basic_ack(delivery.delivery_tag, BasicAckOptions::default())
                    .await
                    .expect("basic_ack");
            }
        })
    }
}

fn main() {
    if std::env::var("RUST_LOG").is_err() {
        std::env::set_var("RUST_LOG", "info");
    }

    env_logger::init();

    let addr = std::env::var("AMQP_ADDR").unwrap_or_else(|_| "amqp://127.0.0.1:5672/%2f".into());
    let conn = Connection::connect(&addr, ConnectionProperties::default())
        .wait()
        .expect("connection error");

    info!("CONNECTED");

    let channel_a = conn.create_channel().wait().expect("create_channel");
    let channel_b = conn.create_channel().wait().expect("create_channel");

    let queue = channel_a
        .queue_declare(
            "hello",
            QueueDeclareOptions::default(),
            FieldTable::default(),
        )
        .wait()
        .expect("queue_declare");

    info!("Declared queue {:?}", queue);

    info!("will consume");
    channel_b
        .basic_consume(
            "hello",
            "my_consumer",
            BasicConsumeOptions::default(),
            FieldTable::default(),
        )
        .wait()
        .expect("basic_consume")
        .set_delegate(Subscriber)
        .expect("set_delegate");

    let payload = b"Hello world!";

    loop {
        let confirm = channel_a
            .basic_publish(
                "",
                "hello",
                BasicPublishOptions::default(),
                payload.to_vec(),
                BasicProperties::default(),
            )
            .wait()
            .expect("basic_publish")
            .wait()
            .expect("publisher-confirms");
        assert_eq!(confirm, Confirmation::NotRequested);
    }
}
<commit_msg>drop nofutures example<commit_after><|endoftext|>


<commit_before>/* Copyright 2016 Torbjørn Birch Moltu
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Test that every method gives the correct result for valid values.
//! Except iterators, which are stateful.

use std::char;
use std::str::{self,FromStr};
use std::hash::Hash;
use std::collections::hash_map::DefaultHasher;
extern crate encode_unicode;
use encode_unicode::*;

#[test]
fn equal_defaults() {
    assert_eq!(Utf8Char::default().to_char(), char::default());
    assert_eq!(Utf16Char::default().to_char(), char::default());
}

#[test]
fn same_size_as_char() {
    use std::mem::size_of;
    assert_eq!(size_of::<Utf8Char>(), size_of::<char>());
    assert_eq!(size_of::<Utf16Char>(), size_of::<char>());
}

#[test]
#[cfg(feature="std")]
fn read_iterator() {
    use std::io::Read;
    use std::cmp::min;

    let uc = 'ä'.to_utf8();
    assert_eq!(uc.len(), 2);
    for chunk in 1..5 {
        let mut buf = [b'E'; 6];
        let mut iter = uc.into_iter();
        let mut written = 0;
        for _ in 0..4 {
            assert_eq!(iter.read(&mut buf[..0]).unwrap(), 0);
            let wrote = iter.read(&mut buf[written..written+chunk]).unwrap();
            assert_eq!(wrote, min(2-written, chunk));
            written += wrote;
            for &b in &buf[written..] {assert_eq!(b, b'E');}
            assert_eq!(buf[..written], AsRef::<[u8]>::as_ref(&uc)[..written]);
        }
        assert_eq!(written, 2);
    }
}

const EDGES_AND_BETWEEN: [u32;13] = [
    0x0,// min
    0x3b,// between
    0x7f,// max 1-byte UTF-8
    0x80,// min 2-byte UTF-8
    0x111,// between
    0x7ff,// max 2-byte UTF-8
    0x800,// min 3-byte UTF-8
    0xd7ff,// before reserved
    0xe000,// after reserved
    0xffff,// max UTF-16 single and 3-byte UTF-8
    0x10000,// min UTF-16 surrogate and 4-byte UTF-8
    0xabcde,// between
    0x10ffff,// max
];

fn eq_cmp_hash(c: char) -> (Utf8Char, Utf16Char) {
    let sh = &mut DefaultHasher::new();
    let u8c = c.to_utf8();
    assert_eq!(u8c.to_char(), c);
    assert_eq!(u8c.hash(sh), c.hash(sh));
    let u16c = c.to_utf16();
    assert_eq!(u16c.to_char(), c);
    assert_eq!(u16c.hash(sh), c.hash(sh));

    for other in &EDGES_AND_BETWEEN {
        let other = unsafe{ char::from_u32_unchecked(*other) };

        let u8other = other.to_utf8();
        assert_eq!(u8c == u8other,  c == other);
        assert_eq!(u8c.hash(sh)==other.hash(sh),  c.hash(sh)==u8other.hash(sh));
        assert_eq!(u8c.cmp(&u8other), c.cmp(&other));

        let u16other = other.to_utf16();
        assert_eq!(u16c == u16other,  c == other);
        assert_eq!(u16c.hash(sh)==other.hash(sh),  c.hash(sh)==u16other.hash(sh));
        assert_eq!(u16c.cmp(&u16other), c.cmp(&other));
    }
    (u8c, u16c)
}

fn iterators(c: char) {
    let mut iter = c.iter_utf8_bytes();
    let mut buf = [0; 4];
    let mut iter_ref = c.encode_utf8(&mut buf[..]).bytes();
    for _ in 0..6 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(iter.next(), iter_ref.next());
    }

    let mut iter = c.iter_utf16_units();
    let mut buf = [0; 2];
    let mut iter_ref = c.encode_utf16(&mut buf[..]).iter().cloned();
    for _ in 0..4 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(iter.next(), iter_ref.next());
    }
}

fn test(c: u32) {
    let c = char::from_u32(c).expect(&format!("{:x} is not a valid char", c));
    assert_eq!(char::from_u32_detailed(c as u32), Ok(c));
    let (u8c, u16c) = eq_cmp_hash(c);
    iterators(c);

    // UTF-8
    let mut buf = [0; 4];
    let reference = c.encode_utf8(&mut buf[..]).as_bytes();
    let len = reference.len(); // short name because it is used in many places.
    assert_eq!(reference[0].extra_utf8_bytes(), Ok(len-1));
    assert_eq!(reference[0].extra_utf8_bytes_unchecked(), len-1);

    for i in c.len_utf8()..5 {
        let mut test_dst = [b'F';4];
        assert_eq!(c.to_utf8_slice(&mut test_dst[..i]), len);
        for b in &mut test_dst[len..] {// Test that it doesn't write too much
            assert_eq!(*b, b'F', "c={:?}, i={}, utf8_len={}", c, i, len);
            *b = 0;
        }
        assert_eq!(&test_dst[..len], reference);
        assert_eq!(AsRef::<[u8]>::as_ref(&u8c), reference);
        assert_eq!(u8c.to_array(), (test_dst, len));
    }
    let (mut arr,arrlen) = u8c.to_array();
    assert_eq!(arrlen, len);
    assert_eq!(Utf8Char::from_array(arr), Ok(u8c));
    assert_eq!(c.to_utf8_array(),  (arr, len));

    let str_ = str::from_utf8(reference).unwrap();
    let ustr = Utf8Char::from_str(str_).unwrap();
    assert_eq!(ustr.to_array().0, arr);// bitwise equality
    assert_eq!(char::from_utf8_array(arr), Ok(c));
    assert_eq!(char::from_utf8_slice(reference), Ok((c,len)));
    for b in arr.iter_mut().skip(arrlen) {
        *b = b'F';// from_slice_start must not read these.
    }
    assert_eq!(Utf8Char::from_slice_start(&arr), Ok((u8c,len)));// Test that it doesn't read too much
    assert_eq!(Utf8Char::from_slice_start(reference), Ok((u8c,len)));

    // UTF-16
    let mut buf = [0; 2];
    let reference = c.encode_utf16(&mut buf[..]);
    let len = reference.len();
    for i in c.len_utf16()..3 {
        let mut test_dst = [0;2];
        assert_eq!(c.to_utf16_slice(&mut test_dst[..i]), len);
        assert_eq!(&test_dst[..len], reference);
        assert_eq!(u16c.to_slice(&mut test_dst[..i]), len);
    }
    assert_eq!(reference[0].utf16_needs_extra_unit(), Some(len==2));
    assert_eq!(reference[0].utf16_is_leading_surrogate(), len==2);
    assert_eq!(char::from_utf16_slice(&reference[..len]), Ok((c,len)));
    let tuple = c.to_utf16_tuple();
    assert_eq!(tuple, (reference[0],reference.get(1).cloned()));
    assert_eq!(char::from_utf16_tuple(tuple), Ok(c));
    assert_eq!(c.to_utf16().to_char(), c);
}

#[test]
fn edges_middle() {
    for c in &EDGES_AND_BETWEEN {
        test(*c);
    }
}

#[test]
#[ignore]
fn all() {
    for c in std::iter::Iterator::chain(0..0xd800, 0xe000..0x110000) {
        test(c);
    }
}
<commit_msg>Test the iterators Debug output<commit_after>/* Copyright 2016 Torbjørn Birch Moltu
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Test that every method gives the correct result for valid values.
//! Except iterators, which are stateful.

use std::char;
use std::str::{self,FromStr};
use std::hash::Hash;
use std::collections::hash_map::DefaultHasher;
extern crate encode_unicode;
use encode_unicode::*;

#[test]
fn equal_defaults() {
    assert_eq!(Utf8Char::default().to_char(), char::default());
    assert_eq!(Utf16Char::default().to_char(), char::default());
}

#[test]
fn same_size_as_char() {
    use std::mem::size_of;
    assert_eq!(size_of::<Utf8Char>(), size_of::<char>());
    assert_eq!(size_of::<Utf16Char>(), size_of::<char>());
}

#[test]
#[cfg(feature="std")]
fn read_iterator() {
    use std::io::Read;
    use std::cmp::min;

    let uc = 'ä'.to_utf8();
    assert_eq!(uc.len(), 2);
    for chunk in 1..5 {
        let mut buf = [b'E'; 6];
        let mut iter = uc.into_iter();
        let mut written = 0;
        for _ in 0..4 {
            assert_eq!(iter.read(&mut buf[..0]).unwrap(), 0);
            let wrote = iter.read(&mut buf[written..written+chunk]).unwrap();
            assert_eq!(wrote, min(2-written, chunk));
            written += wrote;
            for &b in &buf[written..] {assert_eq!(b, b'E');}
            assert_eq!(buf[..written], AsRef::<[u8]>::as_ref(&uc)[..written]);
        }
        assert_eq!(written, 2);
    }
}

const EDGES_AND_BETWEEN: [u32;13] = [
    0x0,// min
    0x3b,// between
    0x7f,// max 1-byte UTF-8
    0x80,// min 2-byte UTF-8
    0x111,// between
    0x7ff,// max 2-byte UTF-8
    0x800,// min 3-byte UTF-8
    0xd7ff,// before reserved
    0xe000,// after reserved
    0xffff,// max UTF-16 single and 3-byte UTF-8
    0x10000,// min UTF-16 surrogate and 4-byte UTF-8
    0xabcde,// between
    0x10ffff,// max
];

fn eq_cmp_hash(c: char) -> (Utf8Char, Utf16Char) {
    let sh = &mut DefaultHasher::new();
    let u8c = c.to_utf8();
    assert_eq!(u8c.to_char(), c);
    assert_eq!(u8c.hash(sh), c.hash(sh));
    let u16c = c.to_utf16();
    assert_eq!(u16c.to_char(), c);
    assert_eq!(u16c.hash(sh), c.hash(sh));

    for other in &EDGES_AND_BETWEEN {
        let other = unsafe{ char::from_u32_unchecked(*other) };

        let u8other = other.to_utf8();
        assert_eq!(u8c == u8other,  c == other);
        assert_eq!(u8c.hash(sh)==other.hash(sh),  c.hash(sh)==u8other.hash(sh));
        assert_eq!(u8c.cmp(&u8other), c.cmp(&other));

        let u16other = other.to_utf16();
        assert_eq!(u16c == u16other,  c == other);
        assert_eq!(u16c.hash(sh)==other.hash(sh),  c.hash(sh)==u16other.hash(sh));
        assert_eq!(u16c.cmp(&u16other), c.cmp(&other));
    }
    (u8c, u16c)
}

fn iterators(c: char) {
    let mut iter = c.iter_utf8_bytes();
    let mut buf = [0; 4];
    let mut iter_ref = c.encode_utf8(&mut buf[..]).as_bytes().iter();
    for _ in 0..6 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice()));
        assert_eq!(iter.next(), iter_ref.next().cloned());
    }

    let mut iter = c.iter_utf16_units();
    let mut buf = [0; 2];
    let mut iter_ref = c.encode_utf16(&mut buf[..]).iter();
    for _ in 0..4 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice()));
        assert_eq!(iter.next(), iter_ref.next().cloned());
    }
}

fn test(c: u32) {
    let c = char::from_u32(c).expect(&format!("{:x} is not a valid char", c));
    assert_eq!(char::from_u32_detailed(c as u32), Ok(c));
    let (u8c, u16c) = eq_cmp_hash(c);
    iterators(c);

    // UTF-8
    let mut buf = [0; 4];
    let reference = c.encode_utf8(&mut buf[..]).as_bytes();
    let len = reference.len(); // short name because it is used in many places.
    assert_eq!(reference[0].extra_utf8_bytes(), Ok(len-1));
    assert_eq!(reference[0].extra_utf8_bytes_unchecked(), len-1);

    for i in c.len_utf8()..5 {
        let mut test_dst = [b'F';4];
        assert_eq!(c.to_utf8_slice(&mut test_dst[..i]), len);
        for b in &mut test_dst[len..] {// Test that it doesn't write too much
            assert_eq!(*b, b'F', "c={:?}, i={}, utf8_len={}", c, i, len);
            *b = 0;
        }
        assert_eq!(&test_dst[..len], reference);
        assert_eq!(AsRef::<[u8]>::as_ref(&u8c), reference);
        assert_eq!(u8c.to_array(), (test_dst, len));
    }
    let (mut arr,arrlen) = u8c.to_array();
    assert_eq!(arrlen, len);
    assert_eq!(Utf8Char::from_array(arr), Ok(u8c));
    assert_eq!(c.to_utf8_array(),  (arr, len));

    let str_ = str::from_utf8(reference).unwrap();
    let ustr = Utf8Char::from_str(str_).unwrap();
    assert_eq!(ustr.to_array().0, arr);// bitwise equality
    assert_eq!(char::from_utf8_array(arr), Ok(c));
    assert_eq!(char::from_utf8_slice(reference), Ok((c,len)));
    for b in arr.iter_mut().skip(arrlen) {
        *b = b'F';// from_slice_start must not read these.
    }
    assert_eq!(Utf8Char::from_slice_start(&arr), Ok((u8c,len)));// Test that it doesn't read too much
    assert_eq!(Utf8Char::from_slice_start(reference), Ok((u8c,len)));

    // UTF-16
    let mut buf = [0; 2];
    let reference = c.encode_utf16(&mut buf[..]);
    let len = reference.len();
    for i in c.len_utf16()..3 {
        let mut test_dst = [0;2];
        assert_eq!(c.to_utf16_slice(&mut test_dst[..i]), len);
        assert_eq!(&test_dst[..len], reference);
        assert_eq!(u16c.to_slice(&mut test_dst[..i]), len);
    }
    assert_eq!(reference[0].utf16_needs_extra_unit(), Some(len==2));
    assert_eq!(reference[0].utf16_is_leading_surrogate(), len==2);
    assert_eq!(char::from_utf16_slice(&reference[..len]), Ok((c,len)));
    let tuple = c.to_utf16_tuple();
    assert_eq!(tuple, (reference[0],reference.get(1).cloned()));
    assert_eq!(char::from_utf16_tuple(tuple), Ok(c));
    assert_eq!(c.to_utf16().to_char(), c);
}

#[test]
fn edges_middle() {
    for c in &EDGES_AND_BETWEEN {
        test(*c);
    }
}

#[test]
#[ignore]
fn all() {
    for c in std::iter::Iterator::chain(0..0xd800, 0xe000..0x110000) {
        test(c);
    }
}
<|endoftext|>