<commit_before>// Copyright (c) 2016-2018 Fabian Schuiki

//! Utilities to implement diagnostics and error reporting facilities.

use source::Span;
use std::fmt;

/// Print debug information. Omitted in release builds.
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! debugln {
    ($($arg:tt)*) => { eprintln!("\x1B[34;1mdebug:\x1B[m {}", format!($($arg)*)); }
}

/// Print debug information. Omitted in release builds.
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! debugln {
    ($($arg:tt)*) => {}
}

/// A handler deals with errors.
#[derive(Debug)]
pub struct Handler {
}

pub static DUMMY_HANDLER: Handler = Handler{};

/// Used to emit structured error messages.
#[must_use]
#[derive(Clone, Debug)]
pub struct DiagnosticBuilder<'a> {
	pub handler: &'a Handler,
	pub message: String,
}

/// A diagnostic result type. Either carries the result `T` in the Ok variant,
/// or an assembled diagnostic in the Err variant.
pub type DiagResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;

/// Emits diagnostic messages.
pub trait DiagEmitter {
	/// Emit a diagnostic message.
	fn emit(&self, diag: DiagBuilder2);
}

#[must_use]
#[derive(Clone, Debug)]
pub struct DiagBuilder2 {
	pub severity: Severity,
	pub message: String,
	pub segments: Vec<DiagSegment>,
}

#[derive(Clone, Debug)]
pub enum DiagSegment {
	Span(Span),
	Note(String),
}

/// A diagnostic result type. Either carries the result `T` in the Ok variant,
/// or an assembled diagnostic in the Err variant.
pub type DiagResult2<T> = Result<T, DiagBuilder2>;

impl DiagBuilder2 {
	pub fn new<S: Into<String>>(severity: Severity, message: S) -> DiagBuilder2 {
		DiagBuilder2 {
			severity: severity,
			message: message.into(),
			segments: Vec::new(),
		}
	}

	pub fn bug<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Bug, message)
	}

	pub fn fatal<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Fatal, message)
	}

	pub fn error<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Error, message)
	}

	pub fn warning<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Warning, message)
	}

	pub fn note<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Note, message)
	}

	pub fn segment(self, segment: DiagSegment) -> DiagBuilder2 {
		let mut segments = self.segments;
		segments.push(segment);
		DiagBuilder2 {
			segments: segments,
			..self
		}
	}

	pub fn span<S: Into<Span>>(self, span: S) -> DiagBuilder2 {
		self.segment(DiagSegment::Span(span.into()))
	}

	pub fn add_note<S: Into<String>>(self, message: S) -> DiagBuilder2 {
		self.segment(DiagSegment::Note(message.into()))
	}

	pub fn get_severity(&self) -> Severity {
		self.severity
	}

	pub fn get_message(&self) -> &String {
		&self.message
	}

	pub fn get_segments(&self) -> &[DiagSegment] {
		&self.segments
	}
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum Severity {
	Note,
	Warning,
	Error,
	Fatal,
	Bug,
}

impl Severity {
	pub fn to_str(self) -> &'static str {
		match self {
			Severity::Fatal => "fatal",
			Severity::Error => "error",
			Severity::Warning => "warning",
			Severity::Note => "note",
			Severity::Bug => "compiler bug",
		}
	}
}

impl fmt::Display for Severity {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.to_str())
	}
}

impl fmt::Display for DiagBuilder2 {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		let mut colorcode = match self.get_severity() {
			Severity::Bug | Severity::Fatal | Severity::Error => "\x1B[31;1m",
			Severity::Warning => "\x1B[33;1m",
			Severity::Note => "\x1B[36;1m",
		};
		write!(f, "{}{}:\x1B[m\x1B[1m {}\x1B[m\n", colorcode, self.get_severity(), self.get_message())?;

		for segment in &self.segments {
			match *segment {
				DiagSegment::Span(sp) => {
					let c = sp.source.get_content();
					let mut iter = c.extract_iter(0, sp.begin);

					// Look for the start of the line.
					let mut col = 1;
					let mut line = 1;
					let mut line_offset = sp.begin;
					while let Some(c) = iter.next_back() {
						match c.1 {
							'\n' => { line += 1; break; },
							'\r' => continue,
							_ => {
								col += 1;
								line_offset = c.0;
							}
						}
					}

					// Count the number of lines.
					while let Some(c) = iter.next_back() {
						if c.1 == '\n' {
							line += 1;
						}
					}

					// Print the line in question.
					let text: String = c.iter_from(line_offset).map(|x| x.1).take_while(|c| *c != '\n' && *c != '\r').collect();
					write!(f, "  --> {}:{}:{}-{}:\n", sp.source.get_path(), line, col, col + sp.extract().len())?;
					write!(f, "   | \n")?;
					write!(f, "   | ")?;
					for (mut i,c) in text.char_indices() {
						i += line_offset;
						if sp.begin != sp.end {
							if i == sp.begin { write!(f, "{}", colorcode)?; }
							if i == sp.end { write!(f, "\x1B[m")?; }
						}
						match c {
							'\t' => write!(f, "    ")?,
							c => write!(f, "{}", c)?,
						}
					}
					write!(f, "\x1B[m\n")?;
					write!(f, "   | ")?;

					// Print the caret markers for the line in question.
					let mut pd = ' ';
					for (mut i,c) in text.char_indices() {
						i += line_offset;
						let d = if (i >= sp.begin && i < sp.end) || (i == sp.begin && sp.begin == sp.end) {
							'^'
						} else {
							' '
						};
						if d != pd {
							write!(f, "{}", if d == ' ' {"\x1B[m"} else {colorcode})?;
						}
						pd = d;
						match c {
							'\t' => write!(f, "{}{}{}{}", d, d, d, d)?,
							_ => write!(f, "{}", d)?,
						}
					}
					write!(f, "\x1B[m\n")?;
					colorcode = "\x1B[1m";
				}
				DiagSegment::Note(ref message) => write!(f, "\x1B[1mnote:\x1B[m {}\n", message)?,
			}
		}

		if self.get_severity() == Severity::Bug {
			write!(f, "\nYou have encountered a compiler bug. Sorry about that! We would appreciate if you open an issue [1] and describe how you triggered the bug, together with a minimal snippet of code to reproduce it. Thanks!\n")?;
			write!(f, "[1]: https://github.com/fabianschuiki/moore\n")?;
		}

		Ok(())
	}
}
<commit_msg>improve readability of diagnostic notes<commit_after>// Copyright (c) 2016-2018 Fabian Schuiki

//! Utilities to implement diagnostics and error reporting facilities.

use source::Span;
use std::fmt;

/// Print debug information. Omitted in release builds.
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! debugln {
    ($($arg:tt)*) => { eprintln!("\x1B[34;1mdebug:\x1B[m {}", format!($($arg)*)); }
}

/// Print debug information. Omitted in release builds.
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! debugln {
    ($($arg:tt)*) => {}
}

/// A handler deals with errors.
#[derive(Debug)]
pub struct Handler {
}

pub static DUMMY_HANDLER: Handler = Handler{};

/// Used to emit structured error messages.
#[must_use]
#[derive(Clone, Debug)]
pub struct DiagnosticBuilder<'a> {
	pub handler: &'a Handler,
	pub message: String,
}

/// A diagnostic result type. Either carries the result `T` in the Ok variant,
/// or an assembled diagnostic in the Err variant.
pub type DiagResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;

/// Emits diagnostic messages.
pub trait DiagEmitter {
	/// Emit a diagnostic message.
	fn emit(&self, diag: DiagBuilder2);
}

#[must_use]
#[derive(Clone, Debug)]
pub struct DiagBuilder2 {
	pub severity: Severity,
	pub message: String,
	pub segments: Vec<DiagSegment>,
}

#[derive(Clone, Debug)]
pub enum DiagSegment {
	Span(Span),
	Note(String),
}

/// A diagnostic result type. Either carries the result `T` in the Ok variant,
/// or an assembled diagnostic in the Err variant.
pub type DiagResult2<T> = Result<T, DiagBuilder2>;

impl DiagBuilder2 {
	pub fn new<S: Into<String>>(severity: Severity, message: S) -> DiagBuilder2 {
		DiagBuilder2 {
			severity: severity,
			message: message.into(),
			segments: Vec::new(),
		}
	}

	pub fn bug<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Bug, message)
	}

	pub fn fatal<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Fatal, message)
	}

	pub fn error<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Error, message)
	}

	pub fn warning<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Warning, message)
	}

	pub fn note<S: Into<String>>(message: S) -> DiagBuilder2 {
		DiagBuilder2::new(Severity::Note, message)
	}

	pub fn segment(self, segment: DiagSegment) -> DiagBuilder2 {
		let mut segments = self.segments;
		segments.push(segment);
		DiagBuilder2 {
			segments: segments,
			..self
		}
	}

	pub fn span<S: Into<Span>>(self, span: S) -> DiagBuilder2 {
		self.segment(DiagSegment::Span(span.into()))
	}

	pub fn add_note<S: Into<String>>(self, message: S) -> DiagBuilder2 {
		self.segment(DiagSegment::Note(message.into()))
	}

	pub fn get_severity(&self) -> Severity {
		self.severity
	}

	pub fn get_message(&self) -> &String {
		&self.message
	}

	pub fn get_segments(&self) -> &[DiagSegment] {
		&self.segments
	}
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum Severity {
	Note,
	Warning,
	Error,
	Fatal,
	Bug,
}

impl Severity {
	pub fn to_str(self) -> &'static str {
		match self {
			Severity::Fatal => "fatal",
			Severity::Error => "error",
			Severity::Warning => "warning",
			Severity::Note => "note",
			Severity::Bug => "compiler bug",
		}
	}
}

impl fmt::Display for Severity {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.to_str())
	}
}

impl fmt::Display for DiagBuilder2 {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		let mut colorcode = match self.get_severity() {
			Severity::Bug | Severity::Fatal | Severity::Error => "\x1B[31;1m",
			Severity::Warning => "\x1B[33;1m",
			Severity::Note => "\x1B[36;1m",
		};
		write!(f, "{}{}:\x1B[m\x1B[1m {}\x1B[m\n", colorcode, self.get_severity(), self.get_message())?;

		for segment in &self.segments {
			match *segment {
				DiagSegment::Span(sp) => {
					let c = sp.source.get_content();
					let mut iter = c.extract_iter(0, sp.begin);

					// Look for the start of the line.
					let mut col = 1;
					let mut line = 1;
					let mut line_offset = sp.begin;
					while let Some(c) = iter.next_back() {
						match c.1 {
							'\n' => { line += 1; break; },
							'\r' => continue,
							_ => {
								col += 1;
								line_offset = c.0;
							}
						}
					}

					// Count the number of lines.
					while let Some(c) = iter.next_back() {
						if c.1 == '\n' {
							line += 1;
						}
					}

					// Print the line in question.
					let text: String = c.iter_from(line_offset).map(|x| x.1).take_while(|c| *c != '\n' && *c != '\r').collect();
					write!(f, "  --> {}:{}:{}-{}:\n", sp.source.get_path(), line, col, col + sp.extract().len())?;
					write!(f, "   | \n")?;
					write!(f, "   | ")?;
					for (mut i,c) in text.char_indices() {
						i += line_offset;
						if sp.begin != sp.end {
							if i == sp.begin { write!(f, "{}", colorcode)?; }
							if i == sp.end { write!(f, "\x1B[m")?; }
						}
						match c {
							'\t' => write!(f, "    ")?,
							c => write!(f, "{}", c)?,
						}
					}
					write!(f, "\x1B[m\n")?;
					write!(f, "   | ")?;

					// Print the caret markers for the line in question.
					let mut pd = ' ';
					for (mut i,c) in text.char_indices() {
						i += line_offset;
						let d = if (i >= sp.begin && i < sp.end) || (i == sp.begin && sp.begin == sp.end) {
							'^'
						} else {
							' '
						};
						if d != pd {
							write!(f, "{}", if d == ' ' {"\x1B[m"} else {colorcode})?;
						}
						pd = d;
						match c {
							'\t' => write!(f, "{}{}{}{}", d, d, d, d)?,
							_ => write!(f, "{}", d)?,
						}
					}
					write!(f, "\x1B[m\n")?;
					colorcode = "\x1B[1m";
				}
				DiagSegment::Note(ref message) => write!(f, "   = \x1B[1mnote:\x1B[m {}\n", message)?,
			}
		}

		if self.get_severity() == Severity::Bug {
			write!(f, "\nYou have encountered a compiler bug. Sorry about that! We would appreciate if you open an issue [1] and describe how you triggered the bug, together with a minimal snippet of code to reproduce it. Thanks!\n")?;
			write!(f, "[1]: https://github.com/fabianschuiki/moore\n")?;
		}

		Ok(())
	}
}
<|endoftext|>


<commit_before>use std::io::{Read, Write};
use std::env;
use std::fs::{DirBuilder, OpenOptions, File};
use std::path::PathBuf;
use std::path::Path;
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
use rustc_serialize::json;
use rusthub::oauth_web;
use notify;

#[derive(Debug)]
struct GhNotifyConfig {
    token: String
}

impl Decodable for GhNotifyConfig {
    fn decode<D: Decoder>(d: &mut D) -> Result<GhNotifyConfig, D::Error> {
        d.read_struct("root", 1, |d| {
            Ok(GhNotifyConfig{
                token: try!(d.read_struct_field("token", 0, |d| Decodable::decode(d)))
            })
        })
    }
}

impl Encodable for GhNotifyConfig {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_struct("root",  1, |s| {
            try!(s.emit_struct_field("token", 0, |s| {
                s.emit_str(&self.token)
            }));
            Ok(())
        })
    }
}

fn retrieve_config_path() -> PathBuf {
    debug!("Retrieving configuration path...");
    let mut path = env::home_dir().expect("Can't find home directory!");
    path.push(".gh-notify");
    path.push("config");
    path
}

fn open_config() -> File {
    let path = retrieve_config_path();
    info!("Opening configuration file...");
    match path.is_file() {
        false => {
            info!("Configuration file doesn't exist. Creating directories...");
            let mut path = env::home_dir().expect("Impossible to get your home dir!");
            path.push(".gh-notify");
            DirBuilder::new()
                .recursive(true)
                .create(&path).unwrap();

            path.push("config");

            OpenOptions::new()
                .read(true)
                .write(true)
                .create(true)
                .open(&path)
                .unwrap()
        }
        true => OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap()
    }
}

fn build_new_token(timeout: i32) -> String {
    info!("Building new token...");
    let client_id = "f912851b98b2884f77de".to_string();
    let scope = vec!("notifications".to_string());
    let mut secret = String::new();

    debug!("Opening secret...");
    File::open(&Path::new("secret"))
        .expect("Could not open secret")
        .read_to_string(&mut secret)
        .unwrap();

    let url = oauth_web::create_authentication_link(client_id.clone(), scope, true);
    notify::notify_action(
        "Authorize gh-notify for GitHub Access",
        "gh-notify needs authorization in order to receive notifications. Click to open an authorization window.",
        "Open Browser",
        timeout,
        |action| {
            match action {
                "default" | "clicked" => {
                    notify::open_link(&url);
                },
                "__closed" => error!("the notification was closed before authentication could occur"),
                _ => ()
            }
        }
    );

    debug!("Capturing authorization from GitHub redirect. Blocking...");
    let token = oauth_web::capture_authorization(client_id, secret, timeout as u64)
        .expect("ERROR: Something went wrong when requesting token.");

    write_config(&GhNotifyConfig {token: token.clone()});
    token
}

fn write_config(config: &GhNotifyConfig) {
    info!("Writing configuration to disk...");
    let mut file = OpenOptions::new()
        .write(true)
        .truncate(true)
        .create(true)
        .open(&retrieve_config_path())
        .unwrap();

    file.write(json::encode(config).unwrap().as_bytes()).unwrap();
    file.flush().unwrap();
    debug!("Configuration saved.");
}

pub fn retrieve_token(timeout: i32) -> String {
    info!("Retrieving token...");
    let mut config = open_config();
    let mut json_str = String::new();
    match config.read_to_string(&mut json_str) {
        Ok(_) => {
            debug!("Config file read sucessfully. Parsing...");
            let token: String = match json::decode::<GhNotifyConfig>(&json_str) {
                Ok(config_struct) => config_struct.token,
                Err(_) => build_new_token(timeout)
            };
            token
        },
        Err(_) => build_new_token(timeout)
    }
}<commit_msg>most work done for notification caching. Need to catch rusthub up with this app<commit_after>use std::io::{Read, Write};
use std::error::Error;
use std::env;
use std::fs::{DirBuilder, OpenOptions, File};
use std::path::PathBuf;
use std::path::Path;
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
use rustc_serialize::json;
use rusthub::oauth_web;
use rusthub::notifications::{Notification, Notifications};
use notify;

#[derive(Debug)]
struct GhNotifyConfig {
    token: String
}

impl Decodable for GhNotifyConfig {
    fn decode<D: Decoder>(d: &mut D) -> Result<GhNotifyConfig, D::Error> {
        d.read_struct("root", 1, |d| {
            Ok(GhNotifyConfig{
                token: try!(d.read_struct_field("token", 0, |d| Decodable::decode(d)))
            })
        })
    }
}

impl Encodable for GhNotifyConfig {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_struct("root",  1, |s| {
            try!(s.emit_struct_field("token", 0, |s| {
                s.emit_str(&self.token)
            }));
            Ok(())
        })
    }
}

fn get_notifications_path() -> PathBuf {
    let mut path = get_notify_path();
    path.push("saved_notifications.json");
    path
}

fn get_config_path() -> PathBuf {
    let mut path = get_notify_path();
    path.push("config");
    path
}

fn get_notify_path() -> PathBuf {
    let mut path = env::home_dir().expect("Can't find home directory!");
    path.push(".gh-notify");
    path
}

fn open_file(path: &PathBuf) -> File {
    info!("Opening {}...", path.as_path().to_string_lossy());
    match path.is_file() {
        false => {
            info!("File doesn't exist. Creating directories...");
            let mut dir = env::home_dir().expect("Impossible to get your home dir!");
            dir.push(".gh-notify");
            DirBuilder::new()
                .recursive(true)
                .create(&dir).unwrap();

            OpenOptions::new()
                .read(true)
                .write(true)
                .create(true)
                .open(&path)
                .unwrap()
        }
        true => OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap()
    }
}

fn build_new_token(timeout: i32) -> String {
    info!("Building new token...");
    let client_id = "f912851b98b2884f77de".to_string();
    let scope = vec!("notifications".to_string());
    let mut secret = String::new();

    debug!("Opening secret...");
    File::open(&Path::new("secret"))
        .expect("Could not open secret")
        .read_to_string(&mut secret)
        .unwrap();

    let url = oauth_web::create_authentication_link(client_id.clone(), scope, true);
    notify::notify_action(
        "Authorize gh-notify for GitHub Access",
        "gh-notify needs authorization in order to receive notifications. Click to open an authorization window.",
        "Open Browser",
        timeout,
        |action| {
            match action {
                "default" | "clicked" => {
                    notify::open_link(&url);
                },
                "__closed" => error!("the notification was closed before authentication could occur"),
                _ => ()
            }
        }
    );

    debug!("Capturing authorization from GitHub redirect. Blocking...");
    let token = oauth_web::capture_authorization(client_id, secret, timeout as u64)
        .expect("ERROR: Something went wrong when requesting token.");

    write_config(&GhNotifyConfig {token: token.clone()});
    token
}

fn write_config(config: &GhNotifyConfig) {
    info!("Writing configuration to disk...");
    let mut file = OpenOptions::new()
        .write(true)
        .truncate(true)
        .create(true)
        .open(&get_config_path())
        .unwrap();

    file.write(json::encode(config).unwrap().as_bytes()).unwrap();
    file.flush().unwrap();
    debug!("Configuration saved.");
}

pub fn retrieve_token(timeout: i32) -> String {
    info!("Retrieving token...");
    let mut config = open_file(&get_config_path());
    let mut json_str = String::new();
    match config.read_to_string(&mut json_str) {
        Ok(_) => {
            debug!("Config file read sucessfully. Parsing...");
            let token: String = match json::decode::<GhNotifyConfig>(&json_str) {
                Ok(config_struct) => config_struct.token,
                Err(_) => build_new_token(timeout)
            };
            token
        },
        Err(_) => build_new_token(timeout)
    }
}

pub fn get_saved_notifications() -> Result<Notifications, String> {
    info!("Getting saved notifications...");
    let file: File = open_file(&get_notifications_path());
    let mut json_str = String::new();
    match file.read_to_string(&mut json_str) {
        Ok(_) => {
            debug!("Notifications file read sucessfully. Parsing...");
            match json::decode::<Notifications>(&json_str) {
                Ok(notifications) => Ok(notifications),
                Err(err) => Err(err.description().to_string())
            }
        },
        Err(err) => Err(err.description().to_string())
    }
}

pub fn write_notifications(w_notifications: &Notifications) -> Result<(), String> {
    let file: File = open_file(&get_notifications_path());
    let w_list: Vec<Notification> = match get_saved_notifications() {
        Ok(r_notifications) => {
            let mut list: Vec<Notification> = w_notifications.list.clone()
                .into_iter()
                .filter(|w_notif| r_notifications.list.iter().any(|r_notif| w_notif.id != r_notif.id))
                .collect();
            list.append(&mut r_notifications.list);
            list
        },
        Err(string) => {
            debug!("Error reading saved notifications. Writing to file without comparison...");
            w_notifications.list
        }
    };

    file.set_len(0); // Truncate to 0
    file.write(json::encode(&Notifications {list: w_list}).as_bytes());
    file.flush();
    info!("Notifications written to file.");
    Ok()
}<|endoftext|>


<commit_before>#![allow(unknown_lints)]
#![allow(clippy::identity_op)] // used for vertical alignment

use std::collections::BTreeMap;
use std::fs::File;
use std::io::prelude::*;
use std::io::Cursor;
use std::time::Instant;

use curl::easy::{Easy, List};
use failure::bail;
use http::status::StatusCode;
use serde::{Deserialize, Serialize};
use serde_json;
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
use url::Url;

pub type Result<T> = std::result::Result<T, failure::Error>;

pub struct Registry {
    /// The base URL for issuing API requests.
    host: String,
    /// Optional authorization token.
    /// If None, commands requiring authorization will fail.
    token: Option<String>,
    /// Curl handle for issuing requests.
    handle: Easy,
}

#[derive(PartialEq, Clone, Copy)]
pub enum Auth {
    Authorized,
    Unauthorized,
}

#[derive(Deserialize)]
pub struct Crate {
    pub name: String,
    pub description: Option<String>,
    pub max_version: String,
}

#[derive(Serialize)]
pub struct NewCrate {
    pub name: String,
    pub vers: String,
    pub deps: Vec<NewCrateDependency>,
    pub features: BTreeMap<String, Vec<String>>,
    pub authors: Vec<String>,
    pub description: Option<String>,
    pub documentation: Option<String>,
    pub homepage: Option<String>,
    pub readme: Option<String>,
    pub readme_file: Option<String>,
    pub keywords: Vec<String>,
    pub categories: Vec<String>,
    pub license: Option<String>,
    pub license_file: Option<String>,
    pub repository: Option<String>,
    pub badges: BTreeMap<String, BTreeMap<String, String>>,
    #[serde(default)]
    pub links: Option<String>,
}

#[derive(Serialize)]
pub struct NewCrateDependency {
    pub optional: bool,
    pub default_features: bool,
    pub name: String,
    pub features: Vec<String>,
    pub version_req: String,
    pub target: Option<String>,
    pub kind: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub registry: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub explicit_name_in_toml: Option<String>,
}

#[derive(Deserialize)]
pub struct User {
    pub id: u32,
    pub login: String,
    pub avatar: Option<String>,
    pub email: Option<String>,
    pub name: Option<String>,
}

pub struct Warnings {
    pub invalid_categories: Vec<String>,
    pub invalid_badges: Vec<String>,
    pub other: Vec<String>,
}

#[derive(Deserialize)]
struct R {
    ok: bool,
}
#[derive(Deserialize)]
struct OwnerResponse {
    ok: bool,
    msg: String,
}
#[derive(Deserialize)]
struct ApiErrorList {
    errors: Vec<ApiError>,
}
#[derive(Deserialize)]
struct ApiError {
    detail: String,
}
#[derive(Serialize)]
struct OwnersReq<'a> {
    users: &'a [&'a str],
}
#[derive(Deserialize)]
struct Users {
    users: Vec<User>,
}
#[derive(Deserialize)]
struct TotalCrates {
    total: u32,
}
#[derive(Deserialize)]
struct Crates {
    crates: Vec<Crate>,
    meta: TotalCrates,
}
impl Registry {
    pub fn new(host: String, token: Option<String>) -> Registry {
        Registry::new_handle(host, token, Easy::new())
    }

    pub fn new_handle(host: String, token: Option<String>, handle: Easy) -> Registry {
        Registry {
            host,
            token,
            handle,
        }
    }

    pub fn host(&self) -> &str {
        &self.host
    }

    pub fn host_is_crates_io(&self) -> bool {
        Url::parse(self.host())
            .map(|u| u.host_str() == Some("crates.io"))
            .unwrap_or(false)
    }

    pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<String> {
        let body = serde_json::to_string(&OwnersReq { users: owners })?;
        let body = self.put(&format!("/crates/{}/owners", krate), body.as_bytes())?;
        assert!(serde_json::from_str::<OwnerResponse>(&body)?.ok);
        Ok(serde_json::from_str::<OwnerResponse>(&body)?.msg)
    }

    pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
        let body = serde_json::to_string(&OwnersReq { users: owners })?;
        let body = self.delete(&format!("/crates/{}/owners", krate), Some(body.as_bytes()))?;
        assert!(serde_json::from_str::<OwnerResponse>(&body)?.ok);
        Ok(())
    }

    pub fn list_owners(&mut self, krate: &str) -> Result<Vec<User>> {
        let body = self.get(&format!("/crates/{}/owners", krate))?;
        Ok(serde_json::from_str::<Users>(&body)?.users)
    }

    pub fn publish(&mut self, krate: &NewCrate, tarball: &File) -> Result<Warnings> {
        let json = serde_json::to_string(krate)?;
        // Prepare the body. The format of the upload request is:
        //
        //      <le u32 of json>
        //      <json request> (metadata for the package)
        //      <le u32 of tarball>
        //      <source tarball>
        let stat = tarball.metadata()?;
        let header = {
            let mut w = Vec::new();
            w.extend(
                [
                    (json.len() >> 0) as u8,
                    (json.len() >> 8) as u8,
                    (json.len() >> 16) as u8,
                    (json.len() >> 24) as u8,
                ].iter().cloned(),
            );
            w.extend(json.as_bytes().iter().cloned());
            w.extend(
                [
                    (stat.len() >> 0) as u8,
                    (stat.len() >> 8) as u8,
                    (stat.len() >> 16) as u8,
                    (stat.len() >> 24) as u8,
                ].iter().cloned(),
            );
            w
        };
        let size = stat.len() as usize + header.len();
        let mut body = Cursor::new(header).chain(tarball);

        let url = format!("{}/api/v1/crates/new", self.host);

        let token = match self.token.as_ref() {
            Some(s) => s,
            None => bail!("no upload token found, please run `cargo login`"),
        };
        self.handle.put(true)?;
        self.handle.url(&url)?;
        self.handle.in_filesize(size as u64)?;
        let mut headers = List::new();
        headers.append("Accept: application/json")?;
        headers.append(&format!("Authorization: {}", token))?;
        self.handle.http_headers(headers)?;

        let body = self.handle(&mut |buf| body.read(buf).unwrap_or(0))?;

        let response = if body.is_empty() {
            "{}".parse()?
        } else {
            body.parse::<serde_json::Value>()?
        };

        let invalid_categories: Vec<String> = response
            .get("warnings")
            .and_then(|j| j.get("invalid_categories"))
            .and_then(|j| j.as_array())
            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())
            .unwrap_or_else(Vec::new);

        let invalid_badges: Vec<String> = response
            .get("warnings")
            .and_then(|j| j.get("invalid_badges"))
            .and_then(|j| j.as_array())
            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())
            .unwrap_or_else(Vec::new);

        let other: Vec<String> = response
            .get("warnings")
            .and_then(|j| j.get("other"))
            .and_then(|j| j.as_array())
            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())
            .unwrap_or_else(Vec::new);

        Ok(Warnings {
            invalid_categories,
            invalid_badges,
            other,
        })
    }

    pub fn search(&mut self, query: &str, limit: u32) -> Result<(Vec<Crate>, u32)> {
        let formatted_query = percent_encode(query.as_bytes(), QUERY_ENCODE_SET);
        let body = self.req(
            &format!("/crates?q={}&per_page={}", formatted_query, limit),
            None,
            Auth::Unauthorized,
        )?;

        let crates = serde_json::from_str::<Crates>(&body)?;
        Ok((crates.crates, crates.meta.total))
    }

    pub fn yank(&mut self, krate: &str, version: &str) -> Result<()> {
        let body = self.delete(&format!("/crates/{}/{}/yank", krate, version), None)?;
        assert!(serde_json::from_str::<R>(&body)?.ok);
        Ok(())
    }

    pub fn unyank(&mut self, krate: &str, version: &str) -> Result<()> {
        let body = self.put(&format!("/crates/{}/{}/unyank", krate, version), &[])?;
        assert!(serde_json::from_str::<R>(&body)?.ok);
        Ok(())
    }

    fn put(&mut self, path: &str, b: &[u8]) -> Result<String> {
        self.handle.put(true)?;
        self.req(path, Some(b), Auth::Authorized)
    }

    fn get(&mut self, path: &str) -> Result<String> {
        self.handle.get(true)?;
        self.req(path, None, Auth::Authorized)
    }

    fn delete(&mut self, path: &str, b: Option<&[u8]>) -> Result<String> {
        self.handle.custom_request("DELETE")?;
        self.req(path, b, Auth::Authorized)
    }

    fn req(&mut self, path: &str, body: Option<&[u8]>, authorized: Auth) -> Result<String> {
        self.handle.url(&format!("{}/api/v1{}", self.host, path))?;
        let mut headers = List::new();
        headers.append("Accept: application/json")?;
        headers.append("Content-Type: application/json")?;

        if authorized == Auth::Authorized {
            let token = match self.token.as_ref() {
                Some(s) => s,
                None => bail!("no upload token found, please run `cargo login`"),
            };
            headers.append(&format!("Authorization: {}", token))?;
        }
        self.handle.http_headers(headers)?;
        match body {
            Some(mut body) => {
                self.handle.upload(true)?;
                self.handle.in_filesize(body.len() as u64)?;
                self.handle(&mut |buf| body.read(buf).unwrap_or(0))
            }
            None => self.handle(&mut |_| 0),
        }
    }

    fn handle(&mut self, read: &mut dyn FnMut(&mut [u8]) -> usize) -> Result<String> {
        let mut headers = Vec::new();
        let mut body = Vec::new();
        let started;
        {
            let mut handle = self.handle.transfer();
            handle.read_function(|buf| Ok(read(buf)))?;
            handle.write_function(|data| {
                body.extend_from_slice(data);
                Ok(data.len())
            })?;
            handle.header_function(|data| {
                headers.push(String::from_utf8_lossy(data).into_owned());
                true
            })?;
            started = Instant::now();
            handle.perform()?;
        }

        let body = match String::from_utf8(body) {
            Ok(body) => body,
            Err(..) => bail!("response body was not valid utf-8"),
        };
        let errors = serde_json::from_str::<ApiErrorList>(&body).ok().map(|s| {
            s.errors.into_iter().map(|s| s.detail).collect::<Vec<_>>()
        });

        match (self.handle.response_code()?, errors) {
            (0, None) | (200, None) => {},
            (503, _) if started.elapsed().as_secs() >= 29 && self.host_is_crates_io() => {
                bail!("Request timed out after 30 seconds. If you're trying to \
                       upload a crate it may be too large. If the crate is under \
                       10MB in size, you can email help@crates.io for assistance.")
            }
            (code, Some(errors)) => {
                let code = StatusCode::from_u16(code as _)?;
                bail!("api errors (status {}): {}", code, errors.join(", "))
            }
            (code, None) => bail!(
                "failed to get a 200 OK response, got {}\n\
                 headers:\n\
                 \t{}\n\
                 body:\n\
                 {}",
                 code,
                 headers.join("\n\t"),
                 body,
            ),
        }

        Ok(body)
    }
}
<commit_msg>Don't display the timeout error if the API returned errors<commit_after>#![allow(unknown_lints)]
#![allow(clippy::identity_op)] // used for vertical alignment

use std::collections::BTreeMap;
use std::fs::File;
use std::io::prelude::*;
use std::io::Cursor;
use std::time::Instant;

use curl::easy::{Easy, List};
use failure::bail;
use http::status::StatusCode;
use serde::{Deserialize, Serialize};
use serde_json;
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
use url::Url;

pub type Result<T> = std::result::Result<T, failure::Error>;

pub struct Registry {
    /// The base URL for issuing API requests.
    host: String,
    /// Optional authorization token.
    /// If None, commands requiring authorization will fail.
    token: Option<String>,
    /// Curl handle for issuing requests.
    handle: Easy,
}

#[derive(PartialEq, Clone, Copy)]
pub enum Auth {
    Authorized,
    Unauthorized,
}

#[derive(Deserialize)]
pub struct Crate {
    pub name: String,
    pub description: Option<String>,
    pub max_version: String,
}

#[derive(Serialize)]
pub struct NewCrate {
    pub name: String,
    pub vers: String,
    pub deps: Vec<NewCrateDependency>,
    pub features: BTreeMap<String, Vec<String>>,
    pub authors: Vec<String>,
    pub description: Option<String>,
    pub documentation: Option<String>,
    pub homepage: Option<String>,
    pub readme: Option<String>,
    pub readme_file: Option<String>,
    pub keywords: Vec<String>,
    pub categories: Vec<String>,
    pub license: Option<String>,
    pub license_file: Option<String>,
    pub repository: Option<String>,
    pub badges: BTreeMap<String, BTreeMap<String, String>>,
    #[serde(default)]
    pub links: Option<String>,
}

#[derive(Serialize)]
pub struct NewCrateDependency {
    pub optional: bool,
    pub default_features: bool,
    pub name: String,
    pub features: Vec<String>,
    pub version_req: String,
    pub target: Option<String>,
    pub kind: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub registry: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub explicit_name_in_toml: Option<String>,
}

#[derive(Deserialize)]
pub struct User {
    pub id: u32,
    pub login: String,
    pub avatar: Option<String>,
    pub email: Option<String>,
    pub name: Option<String>,
}

pub struct Warnings {
    pub invalid_categories: Vec<String>,
    pub invalid_badges: Vec<String>,
    pub other: Vec<String>,
}

#[derive(Deserialize)]
struct R {
    ok: bool,
}
#[derive(Deserialize)]
struct OwnerResponse {
    ok: bool,
    msg: String,
}
#[derive(Deserialize)]
struct ApiErrorList {
    errors: Vec<ApiError>,
}
#[derive(Deserialize)]
struct ApiError {
    detail: String,
}
#[derive(Serialize)]
struct OwnersReq<'a> {
    users: &'a [&'a str],
}
#[derive(Deserialize)]
struct Users {
    users: Vec<User>,
}
#[derive(Deserialize)]
struct TotalCrates {
    total: u32,
}
#[derive(Deserialize)]
struct Crates {
    crates: Vec<Crate>,
    meta: TotalCrates,
}
impl Registry {
    pub fn new(host: String, token: Option<String>) -> Registry {
        Registry::new_handle(host, token, Easy::new())
    }

    pub fn new_handle(host: String, token: Option<String>, handle: Easy) -> Registry {
        Registry {
            host,
            token,
            handle,
        }
    }

    pub fn host(&self) -> &str {
        &self.host
    }

    pub fn host_is_crates_io(&self) -> bool {
        Url::parse(self.host())
            .map(|u| u.host_str() == Some("crates.io"))
            .unwrap_or(false)
    }

    pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<String> {
        let body = serde_json::to_string(&OwnersReq { users: owners })?;
        let body = self.put(&format!("/crates/{}/owners", krate), body.as_bytes())?;
        assert!(serde_json::from_str::<OwnerResponse>(&body)?.ok);
        Ok(serde_json::from_str::<OwnerResponse>(&body)?.msg)
    }

    pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
        let body = serde_json::to_string(&OwnersReq { users: owners })?;
        let body = self.delete(&format!("/crates/{}/owners", krate), Some(body.as_bytes()))?;
        assert!(serde_json::from_str::<OwnerResponse>(&body)?.ok);
        Ok(())
    }

    pub fn list_owners(&mut self, krate: &str) -> Result<Vec<User>> {
        let body = self.get(&format!("/crates/{}/owners", krate))?;
        Ok(serde_json::from_str::<Users>(&body)?.users)
    }

    pub fn publish(&mut self, krate: &NewCrate, tarball: &File) -> Result<Warnings> {
        let json = serde_json::to_string(krate)?;
        // Prepare the body. The format of the upload request is:
        //
        //      <le u32 of json>
        //      <json request> (metadata for the package)
        //      <le u32 of tarball>
        //      <source tarball>
        let stat = tarball.metadata()?;
        let header = {
            let mut w = Vec::new();
            w.extend(
                [
                    (json.len() >> 0) as u8,
                    (json.len() >> 8) as u8,
                    (json.len() >> 16) as u8,
                    (json.len() >> 24) as u8,
                ].iter().cloned(),
            );
            w.extend(json.as_bytes().iter().cloned());
            w.extend(
                [
                    (stat.len() >> 0) as u8,
                    (stat.len() >> 8) as u8,
                    (stat.len() >> 16) as u8,
                    (stat.len() >> 24) as u8,
                ].iter().cloned(),
            );
            w
        };
        let size = stat.len() as usize + header.len();
        let mut body = Cursor::new(header).chain(tarball);

        let url = format!("{}/api/v1/crates/new", self.host);

        let token = match self.token.as_ref() {
            Some(s) => s,
            None => bail!("no upload token found, please run `cargo login`"),
        };
        self.handle.put(true)?;
        self.handle.url(&url)?;
        self.handle.in_filesize(size as u64)?;
        let mut headers = List::new();
        headers.append("Accept: application/json")?;
        headers.append(&format!("Authorization: {}", token))?;
        self.handle.http_headers(headers)?;

        let body = self.handle(&mut |buf| body.read(buf).unwrap_or(0))?;

        let response = if body.is_empty() {
            "{}".parse()?
        } else {
            body.parse::<serde_json::Value>()?
        };

        let invalid_categories: Vec<String> = response
            .get("warnings")
            .and_then(|j| j.get("invalid_categories"))
            .and_then(|j| j.as_array())
            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())
            .unwrap_or_else(Vec::new);

        let invalid_badges: Vec<String> = response
            .get("warnings")
            .and_then(|j| j.get("invalid_badges"))
            .and_then(|j| j.as_array())
            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())
            .unwrap_or_else(Vec::new);

        let other: Vec<String> = response
            .get("warnings")
            .and_then(|j| j.get("other"))
            .and_then(|j| j.as_array())
            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())
            .unwrap_or_else(Vec::new);

        Ok(Warnings {
            invalid_categories,
            invalid_badges,
            other,
        })
    }

    pub fn search(&mut self, query: &str, limit: u32) -> Result<(Vec<Crate>, u32)> {
        let formatted_query = percent_encode(query.as_bytes(), QUERY_ENCODE_SET);
        let body = self.req(
            &format!("/crates?q={}&per_page={}", formatted_query, limit),
            None,
            Auth::Unauthorized,
        )?;

        let crates = serde_json::from_str::<Crates>(&body)?;
        Ok((crates.crates, crates.meta.total))
    }

    pub fn yank(&mut self, krate: &str, version: &str) -> Result<()> {
        let body = self.delete(&format!("/crates/{}/{}/yank", krate, version), None)?;
        assert!(serde_json::from_str::<R>(&body)?.ok);
        Ok(())
    }

    pub fn unyank(&mut self, krate: &str, version: &str) -> Result<()> {
        let body = self.put(&format!("/crates/{}/{}/unyank", krate, version), &[])?;
        assert!(serde_json::from_str::<R>(&body)?.ok);
        Ok(())
    }

    fn put(&mut self, path: &str, b: &[u8]) -> Result<String> {
        self.handle.put(true)?;
        self.req(path, Some(b), Auth::Authorized)
    }

    fn get(&mut self, path: &str) -> Result<String> {
        self.handle.get(true)?;
        self.req(path, None, Auth::Authorized)
    }

    fn delete(&mut self, path: &str, b: Option<&[u8]>) -> Result<String> {
        self.handle.custom_request("DELETE")?;
        self.req(path, b, Auth::Authorized)
    }

    fn req(&mut self, path: &str, body: Option<&[u8]>, authorized: Auth) -> Result<String> {
        self.handle.url(&format!("{}/api/v1{}", self.host, path))?;
        let mut headers = List::new();
        headers.append("Accept: application/json")?;
        headers.append("Content-Type: application/json")?;

        if authorized == Auth::Authorized {
            let token = match self.token.as_ref() {
                Some(s) => s,
                None => bail!("no upload token found, please run `cargo login`"),
            };
            headers.append(&format!("Authorization: {}", token))?;
        }
        self.handle.http_headers(headers)?;
        match body {
            Some(mut body) => {
                self.handle.upload(true)?;
                self.handle.in_filesize(body.len() as u64)?;
                self.handle(&mut |buf| body.read(buf).unwrap_or(0))
            }
            None => self.handle(&mut |_| 0),
        }
    }

    fn handle(&mut self, read: &mut dyn FnMut(&mut [u8]) -> usize) -> Result<String> {
        let mut headers = Vec::new();
        let mut body = Vec::new();
        let started;
        {
            let mut handle = self.handle.transfer();
            handle.read_function(|buf| Ok(read(buf)))?;
            handle.write_function(|data| {
                body.extend_from_slice(data);
                Ok(data.len())
            })?;
            handle.header_function(|data| {
                headers.push(String::from_utf8_lossy(data).into_owned());
                true
            })?;
            started = Instant::now();
            handle.perform()?;
        }

        let body = match String::from_utf8(body) {
            Ok(body) => body,
            Err(..) => bail!("response body was not valid utf-8"),
        };
        let errors = serde_json::from_str::<ApiErrorList>(&body).ok().map(|s| {
            s.errors.into_iter().map(|s| s.detail).collect::<Vec<_>>()
        });

        match (self.handle.response_code()?, errors) {
            (0, None) | (200, None) => {},
            (503, None) if started.elapsed().as_secs() >= 29 && self.host_is_crates_io() => {
                bail!("Request timed out after 30 seconds. If you're trying to \
                       upload a crate it may be too large. If the crate is under \
                       10MB in size, you can email help@crates.io for assistance.")
            }
            (code, Some(errors)) => {
                let code = StatusCode::from_u16(code as _)?;
                bail!("api errors (status {}): {}", code, errors.join(", "))
            }
            (code, None) => bail!(
                "failed to get a 200 OK response, got {}\n\
                 headers:\n\
                 \t{}\n\
                 body:\n\
                 {}",
                 code,
                 headers.join("\n\t"),
                 body,
            ),
        }

        Ok(body)
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::error::Error;

use dbus;
use dbus::arg::{ArgType, Iter, IterAppend, RefArg, Variant};
use dbus::stdintf::org_freedesktop_dbus::PropertiesPropertiesChanged;
use dbus::tree::{MTFn, MethodErr, PropInfo};
use dbus::Connection;
use dbus::SignalArgs;

use super::super::stratis::{ErrorEnum, StratisError};

use super::types::{DbusErrorEnum, TData};

pub const STRATIS_BASE_PATH: &str = "/org/storage/stratis1";
pub const STRATIS_BASE_SERVICE: &str = "org.storage.stratis1";

/// Convert a tuple as option to an Option type
pub fn tuple_to_option<T>(value: (bool, T)) -> Option<T> {
    if value.0 {
        Some(value.1)
    } else {
        None
    }
}

/// Get the next argument off the bus
pub fn get_next_arg<'a, T>(iter: &mut Iter<'a>, loc: u16) -> Result<T, MethodErr>
where
    T: dbus::arg::Get<'a> + dbus::arg::Arg,
{
    if iter.arg_type() == ArgType::Invalid {
        return Err(MethodErr::no_arg());
    };
    let value: T = iter.read::<T>().map_err(|_| MethodErr::invalid_arg(&loc))?;
    Ok(value)
}

/// Translates an engine error to the (errorcode, string) tuple that Stratis
/// D-Bus methods return.
pub fn engine_to_dbus_err_tuple(err: &StratisError) -> (u16, String) {
    let error = match *err {
        StratisError::Error(_) => DbusErrorEnum::INTERNAL_ERROR,
        StratisError::Engine(ref e, _) => match *e {
            ErrorEnum::Error => DbusErrorEnum::ERROR,
            ErrorEnum::AlreadyExists => DbusErrorEnum::ALREADY_EXISTS,
            ErrorEnum::Busy => DbusErrorEnum::BUSY,
            ErrorEnum::Invalid => DbusErrorEnum::ERROR,
            ErrorEnum::NotFound => DbusErrorEnum::NOTFOUND,
        },
        StratisError::Io(_) => DbusErrorEnum::IO_ERROR,
        StratisError::Nix(_) => DbusErrorEnum::NIX_ERROR,
        StratisError::Uuid(_)
        | StratisError::Utf8(_)
        | StratisError::Serde(_)
        | StratisError::DM(_)
        | StratisError::Dbus(_)
        | StratisError::Udev(_) => DbusErrorEnum::INTERNAL_ERROR,
    };
    (error.into(), err.description().to_owned())
}

/// Convenience function to get the error value for "OK"
pub fn msg_code_ok() -> u16 {
    DbusErrorEnum::OK.into()
}

/// Convenience function to get the error string for "OK"
pub fn msg_string_ok() -> String {
    DbusErrorEnum::OK.get_error_string().to_owned()
}

/// Get the UUID for an object path.
pub fn get_uuid(i: &mut IterAppend, p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    let object_path = p.path.get_name();
    let path = p.tree
        .get(object_path)
        .expect("implicit argument must be in tree");

    let data = path.get_data()
        .as_ref()
        .ok_or_else(|| MethodErr::failed(&format!("no data for object path {}", object_path)))?;

    i.append(format!("{}", data.uuid.simple()));
    Ok(())
}

/// Get the parent object path for an object path.
pub fn get_parent(i: &mut IterAppend, p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    let object_path = p.path.get_name();
    let path = p.tree
        .get(object_path)
        .expect("implicit argument must be in tree");

    let data = path.get_data()
        .as_ref()
        .ok_or_else(|| MethodErr::failed(&format!("no data for object path {}", object_path)))?;

    i.append(data.parent.clone());
    Ok(())
}

/// Place a property changed signal on the D-Bus.
pub fn prop_changed_dispatch<T: 'static>(
    conn: &Connection,
    prop_name: &str,
    new_value: T,
    path: &dbus::Path,
) -> Result<(), ()>
where
    T: RefArg,
{
    let mut prop_changed: PropertiesPropertiesChanged = Default::default();
    prop_changed
        .changed_properties
        .insert(prop_name.into(), Variant(Box::new(new_value)));

    conn.send(prop_changed.to_emit_message(path))?;

    Ok(())
}
<commit_msg>Use display rather than description for DmError::Core errors<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::error::Error;

use dbus;
use dbus::arg::{ArgType, Iter, IterAppend, RefArg, Variant};
use dbus::stdintf::org_freedesktop_dbus::PropertiesPropertiesChanged;
use dbus::tree::{MTFn, MethodErr, PropInfo};
use dbus::Connection;
use dbus::SignalArgs;

use devicemapper::DmError;

use super::super::stratis::{ErrorEnum, StratisError};

use super::types::{DbusErrorEnum, TData};

pub const STRATIS_BASE_PATH: &str = "/org/storage/stratis1";
pub const STRATIS_BASE_SERVICE: &str = "org.storage.stratis1";

/// Convert a tuple as option to an Option type
pub fn tuple_to_option<T>(value: (bool, T)) -> Option<T> {
    if value.0 {
        Some(value.1)
    } else {
        None
    }
}

/// Get the next argument off the bus
pub fn get_next_arg<'a, T>(iter: &mut Iter<'a>, loc: u16) -> Result<T, MethodErr>
where
    T: dbus::arg::Get<'a> + dbus::arg::Arg,
{
    if iter.arg_type() == ArgType::Invalid {
        return Err(MethodErr::no_arg());
    };
    let value: T = iter.read::<T>().map_err(|_| MethodErr::invalid_arg(&loc))?;
    Ok(value)
}

/// Translates an engine error to the (errorcode, string) tuple that Stratis
/// D-Bus methods return.
pub fn engine_to_dbus_err_tuple(err: &StratisError) -> (u16, String) {
    let error = match *err {
        StratisError::Error(_) => DbusErrorEnum::INTERNAL_ERROR,
        StratisError::Engine(ref e, _) => match *e {
            ErrorEnum::Error => DbusErrorEnum::ERROR,
            ErrorEnum::AlreadyExists => DbusErrorEnum::ALREADY_EXISTS,
            ErrorEnum::Busy => DbusErrorEnum::BUSY,
            ErrorEnum::Invalid => DbusErrorEnum::ERROR,
            ErrorEnum::NotFound => DbusErrorEnum::NOTFOUND,
        },
        StratisError::Io(_) => DbusErrorEnum::IO_ERROR,
        StratisError::Nix(_) => DbusErrorEnum::NIX_ERROR,
        StratisError::Uuid(_)
        | StratisError::Utf8(_)
        | StratisError::Serde(_)
        | StratisError::DM(_)
        | StratisError::Dbus(_)
        | StratisError::Udev(_) => DbusErrorEnum::INTERNAL_ERROR,
    };
    let description = match *err {
        StratisError::DM(DmError::Core(ref err)) => err.to_string(),
        ref err => err.description().to_owned(),
    };
    (error.into(), description)
}

/// Convenience function to get the error value for "OK"
pub fn msg_code_ok() -> u16 {
    DbusErrorEnum::OK.into()
}

/// Convenience function to get the error string for "OK"
pub fn msg_string_ok() -> String {
    DbusErrorEnum::OK.get_error_string().to_owned()
}

/// Get the UUID for an object path.
pub fn get_uuid(i: &mut IterAppend, p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    let object_path = p.path.get_name();
    let path = p.tree
        .get(object_path)
        .expect("implicit argument must be in tree");

    let data = path.get_data()
        .as_ref()
        .ok_or_else(|| MethodErr::failed(&format!("no data for object path {}", object_path)))?;

    i.append(format!("{}", data.uuid.simple()));
    Ok(())
}

/// Get the parent object path for an object path.
pub fn get_parent(i: &mut IterAppend, p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    let object_path = p.path.get_name();
    let path = p.tree
        .get(object_path)
        .expect("implicit argument must be in tree");

    let data = path.get_data()
        .as_ref()
        .ok_or_else(|| MethodErr::failed(&format!("no data for object path {}", object_path)))?;

    i.append(data.parent.clone());
    Ok(())
}

/// Place a property changed signal on the D-Bus.
pub fn prop_changed_dispatch<T: 'static>(
    conn: &Connection,
    prop_name: &str,
    new_value: T,
    path: &dbus::Path,
) -> Result<(), ()>
where
    T: RefArg,
{
    let mut prop_changed: PropertiesPropertiesChanged = Default::default();
    prop_changed
        .changed_properties
        .insert(prop_name.into(), Variant(Box::new(new_value)));

    conn.send(prop_changed.to_emit_message(path))?;

    Ok(())
}
<|endoftext|>


<commit_before>extern crate toml;
extern crate rustc_serialize;
extern crate walkdir;
extern crate rpf;

use toml::decode;
use error::YabsError;
use ext::*;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, json};
use walkdir::WalkDir;

use std::ffi::OsStr;
use std::path::PathBuf;

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone)]
pub struct Profile {
    name: String,
    proj_desc: Option<ProjDesc>,
    inst_desc: Option<InstallDesc>,
    doc_desc: Option<DocDesc>,
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable)]
pub struct BuildFile {
    profiles: Vec<Profile>,
}

impl BuildFile {
    pub fn from_file(file: &str) -> Result<BuildFile, Vec<YabsError>> {
        let mut build_file: BuildFile = Default::default();
        parse_toml_file(file)
            .and_then(|toml| {
                for (key, table) in toml {
                    let mut profile: Profile = Default::default();
                    profile.name = key.clone();
                    match table {
                        toml::Value::Table(inner_table) => {
                            for (key, table) in inner_table {
                                match key.as_ref() {
                                    "project" => {
                                        profile.proj_desc = ProjDesc::from_toml_table(table).ok()
                                    }
                                    "install" => {
                                        profile.inst_desc = InstallDesc::from_toml_table(table).ok()
                                    }
                                    "doc" => {
                                        profile.doc_desc = DocDesc::from_toml_table(table).ok()
                                    }
                                    _ => (),
                                }
                            }
                        }
                        _ => (),
                    };
                    build_file.profiles.push(profile);
                }
                Ok(build_file)
            })
            .map_err(|err| err)
    }

    pub fn print_as_json(&self) {
        for profile in &self.profiles {
            profile.print_json();
        }
    }

    pub fn print_profile_as_json(&self, name: String) {
        for profile in &self.profiles {
            if profile.name == name {
                println!("{}", profile.name);
            } else {
                return;
            }
        }
    }

    pub fn print_sources(&self) -> Result<(), YabsError> {
        for profile in &self.profiles {
            println!("{}", profile.name);
            if let Some(proj) = profile.proj_desc.as_ref() {
                let sources = try!(proj.gen_obj_list());
                for file in sources.files {
                    println!("{}", file.display());
                }
            }
        }
        Ok(())
    }
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct ProjDesc {
    name: Option<String>,
    target: Option<String>,
    lang: Option<String>,
    os: Option<String>,
    version: Option<String>,
    compiler: Option<String>,
    src: Option<Vec<String>>,
    libs: Option<Vec<String>>,
    lib_dir: Option<Vec<String>>,
    inc: Option<Vec<String>>,
    inc_dir: Option<Vec<String>>,
    cflags: Option<String>,
    lflags: Option<String>,
    ignore: Option<Vec<String>>,
    before_script: Option<Vec<String>>,
    after_script: Option<Vec<String>>,
    lib: Option<bool>,
    ar: Option<String>,
}

#[derive(Default,RustcDecodable,RustcEncodable)]
struct Sources {
    files: Vec<PathBuf>,
    objects: Vec<PathBuf>,
}

impl ProjDesc {
    fn gen_obj_list(&self) -> Result<Sources, YabsError> {
        let mut sources = Sources::new();
        for entry in WalkDir::new(".") {
            let entry = try!(entry);
            if entry.path().is_file() {
                let lang = &self.lang.clone().unwrap();
                let file_ext = entry.path().extension().unwrap_or(OsStr::new(""));
                if let Some(ext) = file_ext.to_str() {
                    if let Some(lang) = self.lang.clone() {
                        if ext == lang {
                            sources.files.push(PathBuf::from(entry.path()));
                        }
                    }
                }
            }
        }
        Ok(sources)
    }
}

// Descibe how to install this project
#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone)]
pub struct InstallDesc {
    prefix: Option<String>,
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone)]
pub struct DocDesc {
    doc: Option<String>,
}

// General trait for any descriptions
pub trait Desc<T> {
    fn new() -> T;
    fn from_file(file: &str, name: &str) -> Result<T, Vec<YabsError>>;
    fn from_toml_table(table: toml::Value) -> Result<T, YabsError>;
    fn print_json(&self);
}

impl<T: Decodable + Encodable + Default> Desc<T> for T {
    fn new() -> T {
        Default::default()
    }

    fn from_file(file: &str, name: &str) -> Result<T, Vec<YabsError>> {
        parse_toml_file(file).and_then(|toml| {
            toml.get(name)
                .ok_or(vec![YabsError::NoDesc(name.to_owned())])
                .and_then(|desc| {
                    Decodable::decode(&mut toml::Decoder::new(desc.clone()))
                        .map_err(|err| vec![YabsError::TomlDecode(err)])
                })
        })
    }

    fn from_toml_table(table: toml::Value) -> Result<T, YabsError> {
        Ok(try!(Decodable::decode(&mut toml::Decoder::new(table.clone()))))
    }

    fn print_json(&self) {
        println!("{}", json::as_pretty_json(&self));
    }
}
<commit_msg>build: fix specific profile printing<commit_after>extern crate toml;
extern crate rustc_serialize;
extern crate walkdir;
extern crate rpf;

use toml::decode;
use error::YabsError;
use ext::*;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, json};
use walkdir::WalkDir;

use std::ffi::OsStr;
use std::path::PathBuf;

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct Profile {
    name: String,
    proj_desc: Option<ProjDesc>,
    inst_desc: Option<InstallDesc>,
    doc_desc: Option<DocDesc>,
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable)]
pub struct BuildFile {
    profiles: Vec<Profile>,
}

impl BuildFile {
    pub fn from_file(file: &str) -> Result<BuildFile, Vec<YabsError>> {
        let mut build_file: BuildFile = Default::default();
        parse_toml_file(file)
            .and_then(|toml| {
                for (key, table) in toml {
                    let mut profile: Profile = Default::default();
                    profile.name = key.clone();
                    match table {
                        toml::Value::Table(inner_table) => {
                            for (key, table) in inner_table {
                                match key.as_ref() {
                                    "project" => {
                                        profile.proj_desc = ProjDesc::from_toml_table(table).ok()
                                    }
                                    "install" => {
                                        profile.inst_desc = InstallDesc::from_toml_table(table).ok()
                                    }
                                    "doc" => {
                                        profile.doc_desc = DocDesc::from_toml_table(table).ok()
                                    }
                                    _ => (),
                                }
                            }
                        }
                        _ => (),
                    };
                    build_file.profiles.push(profile);
                }
                Ok(build_file)
            })
            .map_err(|err| err)
    }

    pub fn print_as_json(&self) {
        for profile in &self.profiles {
            profile.print_json();
        }
    }

    pub fn print_profile_as_json(&self, name: String) {
        for profile in &self.profiles {
            if profile.name == name {
                profile.print_json();
            }
        }
    }

    pub fn print_sources(&self) -> Result<(), YabsError> {
        for profile in &self.profiles {
            println!("{}", profile.name);
            if let Some(proj) = profile.proj_desc.as_ref() {
                let sources = try!(proj.gen_obj_list());
                for file in sources.files {
                    println!("{}", file.display());
                }
            }
        }
        Ok(())
    }
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct ProjDesc {
    name: Option<String>,
    target: Option<String>,
    lang: Option<String>,
    os: Option<String>,
    version: Option<String>,
    compiler: Option<String>,
    src: Option<Vec<String>>,
    libs: Option<Vec<String>>,
    lib_dir: Option<Vec<String>>,
    inc: Option<Vec<String>>,
    inc_dir: Option<Vec<String>>,
    cflags: Option<String>,
    lflags: Option<String>,
    ignore: Option<Vec<String>>,
    before_script: Option<Vec<String>>,
    after_script: Option<Vec<String>>,
    lib: Option<bool>,
    ar: Option<String>,
}

#[derive(Default,RustcDecodable,RustcEncodable,PartialEq)]
struct Sources {
    files: Vec<PathBuf>,
    objects: Vec<PathBuf>,
}

impl ProjDesc {
    fn gen_obj_list(&self) -> Result<Sources, YabsError> {
        let mut sources = Sources::new();
        for entry in WalkDir::new(".") {
            let entry = try!(entry);
            if entry.path().is_file() {
                let lang = &self.lang.clone().unwrap();
                let file_ext = entry.path().extension().unwrap_or(OsStr::new(""));
                if let Some(ext) = file_ext.to_str() {
                    if let Some(lang) = self.lang.clone() {
                        if ext == lang {
                            sources.files.push(PathBuf::from(entry.path()));
                        }
                    }
                }
            }
        }
        Ok(sources)
    }
}

// Descibe how to install this project
#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct InstallDesc {
    prefix: Option<String>,
}

#[derive(Debug,Default,RustcDecodable,RustcEncodable,Clone,PartialEq)]
pub struct DocDesc {
    doc: Option<String>,
}

// General trait for any descriptions
pub trait Desc<T> {
    fn new() -> T;
    fn from_file(file: &str, name: &str) -> Result<T, Vec<YabsError>>;
    fn from_toml_table(table: toml::Value) -> Result<T, YabsError>;
    fn print_json(&self);
}

impl<T: Decodable + Encodable + Default> Desc<T> for T {
    fn new() -> T {
        Default::default()
    }

    fn from_file(file: &str, name: &str) -> Result<T, Vec<YabsError>> {
        parse_toml_file(file).and_then(|toml| {
            toml.get(name)
                .ok_or(vec![YabsError::NoDesc(name.to_owned())])
                .and_then(|desc| {
                    Decodable::decode(&mut toml::Decoder::new(desc.clone()))
                        .map_err(|err| vec![YabsError::TomlDecode(err)])
                })
        })
    }

    fn from_toml_table(table: toml::Value) -> Result<T, YabsError> {
        Ok(try!(Decodable::decode(&mut toml::Decoder::new(table.clone()))))
    }

    fn print_json(&self) {
        println!("{}", json::as_pretty_json(&self));
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix issues with previous cherry pick<commit_after><|endoftext|>


<commit_before>extern crate criterion;
extern crate noise;

use criterion::*;
use noise::{NoiseFn, Simplex};
use rand::Rng;

criterion_group!(simplex, bench_simplex);
// criterion_group!(
//     simplex_64x64,
//     bench_simplex2_64x64,
//     bench_simplex3_64x64,
//     bench_simplex4_64x64
// );
criterion_main!(simplex);

fn bench_simplex(c: &mut Criterion) {
    let mut group = c.benchmark_group("Simplex");

    let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic);

    group.plot_config(plot_config);

    let mut rng = rand_pcg::Pcg64Mcg::new(rand::random());

    let simplex = Simplex::default();

    for step in 0..10 {
        let size = 1 << step;

        group.throughput(Throughput::Elements(size as u64));

        // Generate input arrays
        let input_1 = criterion::black_box((0..size).map(|_| rng.gen()).collect::<Vec<f64>>());
        let input_2 = criterion::black_box((0..size).map(|_| rng.gen()).collect::<Vec<f64>>());

        // prefill output vector with random values
        let mut output = criterion::black_box((0..size).map(|_| rng.gen()).collect::<Vec<f64>>());

        group.bench_with_input(BenchmarkId::new("2D", size), &size, |b, &size| {
            b.iter(|| {
                for i in 0..size {
                    output[i] = criterion::black_box(simplex.get([input_1[i], input_2[i]]));
                }
            })
        });
    }

    group.finish();
}
<commit_msg>Disable Logarithmic scale for graphs<commit_after>extern crate criterion;
extern crate noise;

use criterion::*;
use noise::{NoiseFn, Simplex};
use rand::Rng;

criterion_group!(simplex, bench_simplex);
// criterion_group!(
//     simplex_64x64,
//     bench_simplex2_64x64,
//     bench_simplex3_64x64,
//     bench_simplex4_64x64
// );
criterion_main!(simplex);

fn bench_simplex(c: &mut Criterion) {
    let mut group = c.benchmark_group("Simplex");

    // let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic);
    // group.plot_config(plot_config);

    let mut rng = rand_pcg::Pcg64Mcg::new(rand::random());

    let simplex = Simplex::default();

    for step in 0..10 {
        let size = 1 << step;

        group.throughput(Throughput::Elements(size as u64));

        // Generate input arrays
        let input_1 = criterion::black_box((0..size).map(|_| rng.gen()).collect::<Vec<f64>>());
        let input_2 = criterion::black_box((0..size).map(|_| rng.gen()).collect::<Vec<f64>>());

        // prefill output vector with random values
        let mut output = criterion::black_box((0..size).map(|_| rng.gen()).collect::<Vec<f64>>());

        group.bench_with_input(BenchmarkId::new("2D", size), &size, |b, &size| {
            b.iter(|| {
                for i in 0..size {
                    output[i] = criterion::black_box(simplex.get([input_1[i], input_2[i]]));
                }
            })
        });
    }

    group.finish();
}
<|endoftext|>


<commit_before>// Copyright © 2012 Bart Massey
// [This program is licensed under the "MIT License"]
// Please see the file COPYING in the source
// distribution of this software for license terms.

// CipherSaber
// http://ciphersaber.gurus.com

extern crate getopts;
extern crate rpassword;

use getopts::Options;
use rpassword::read_password;
use std::env;

use std::default::Default;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::error::Error;

fn mkiv(ivb: &mut [u8;10]) {
    // http://rustbyexample.com/std_misc/file/open.html
    let urandom = Path::new("/dev/urandom");
    let mut fd = match File::open(&urandom) {
        Err(why) => panic!("couldn't open {}: {}",
                           urandom.display(),
                           why.description()),
        Ok(file) => file
    };
    let ok = fd.read_exact(ivb);
    match ok {
        Ok(()) => (),
        _ => panic!("couldn't read {}", urandom.display())
    }
}

enum Dirn {
    Encrypt,
    Decrypt
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();
    opts.optflag("e", "encrypt", "encrypt input to output");
    opts.optflag("d", "decrypt", "decrypt input to output");
    opts.optopt("k", "key", "KEY", "key on command line (dangerous)");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };
    let en = matches.opt_present("e");
    let de = matches.opt_present("d");
    if en && de {
        panic!("cannot both encrypt and decrypt");
    }
    if !en && !de {
        panic!("must encrypt or decrypt");
    }
    let dirn = if en {
        Dirn::Encrypt
    } else {
        assert!(de);
        Dirn::Decrypt
    };
    let keystr = match matches.opt_str("k") {
        Some(s) => s,
        _ => {
            let ok = read_password();
            match ok {
                Ok(s) => s,
                _ => panic!("password read error")
            }
        }
    };

    let mut sout = std::io::stdout();
    let mut sin = std::io::stdin();
    let mut ivb :[u8;10] = [Default::default();10];
    match dirn {
        Dirn::Encrypt => {
            mkiv(&mut ivb);
            sout.write(&mut ivb).expect("write failed");
        }
        Dirn::Decrypt => {
            let ok = sin.read_exact(&mut ivb);
            match ok {
                Ok(()) => (),
                _ => panic!("couldn't read iv")
            }
        }
    };

    let mut state: [u8;256] = [Default::default();256];
    for k in 0..256 {
        state[k] = k as u8;
    }
    let ks = keystr.as_bytes();
    let kl = ks.len();
    let mut j = 0;
    for k in 0..256 {
        j = (j + state[k] as usize + ks[k % kl] as usize) & 0xff;
        let tmp = state[k];
        state[k] = state[j];
        state[j] = tmp;
    }

    let mut i: usize = 0;
    let mut j: usize = 0;
    for ch in sin.bytes() {
        i = (i + 1) & 0xff;
        j = (j + state[i] as usize) & 0xff;
        let si = state[i];
        let sj = state[j];
        state[i] = sj;
        state[j] = si;
        let plain = ch.unwrap();
        let cipher = state[(si as usize + sj as usize) & 0xff] ^ plain;
        let b = [cipher];
        match sout.write(&b) {
            Ok(_) => (),
            _ => panic!("write error")
        };
    }
}
<commit_msg>got rust version working<commit_after>// Copyright © 2012 Bart Massey
// [This program is licensed under the "MIT License"]
// Please see the file COPYING in the source
// distribution of this software for license terms.

// CipherSaber
// http://ciphersaber.gurus.com

extern crate getopts;
extern crate rpassword;

use getopts::Options;
use rpassword::read_password;
use std::env;

use std::default::Default;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::error::Error;

fn mkiv(ivb: &mut [u8;10]) {
    // http://rustbyexample.com/std_misc/file/open.html
    let urandom = Path::new("/dev/urandom");
    let mut fd = match File::open(&urandom) {
        Err(why) => panic!("couldn't open {}: {}",
                           urandom.display(),
                           why.description()),
        Ok(file) => file
    };
    let ok = fd.read_exact(ivb);
    match ok {
        Ok(()) => (),
        _ => panic!("couldn't read {}", urandom.display())
    }
}

enum Dirn {
    Encrypt,
    Decrypt
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();
    opts.optflag("e", "encrypt", "encrypt input to output");
    opts.optflag("d", "decrypt", "decrypt input to output");
    opts.optopt("k", "key", "KEY", "key on command line (dangerous)");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };
    let en = matches.opt_present("e");
    let de = matches.opt_present("d");
    if en && de {
        panic!("cannot both encrypt and decrypt");
    }
    if !en && !de {
        panic!("must encrypt or decrypt");
    }
    let dirn = if en {
        Dirn::Encrypt
    } else {
        assert!(de);
        Dirn::Decrypt
    };
    let mut keybytes: Vec<u8> = vec![];
    match matches.opt_str("k") {
        Some(s) => keybytes.extend_from_slice(s.as_bytes()),
        _ => {
            let ok = read_password();
            match ok {
                Ok(s) => keybytes.extend_from_slice(s.as_bytes()),
                _ => panic!("password read error")
            }
        }
    };

    let mut sout = std::io::stdout();
    let mut sin = std::io::stdin();
    let mut ivb :[u8;10] = [Default::default();10];
    match dirn {
        Dirn::Encrypt => {
            mkiv(&mut ivb);
            sout.write(&mut ivb).expect("write failed");
        }
        Dirn::Decrypt => {
            let ok = sin.read_exact(&mut ivb);
            match ok {
                Ok(()) => (),
                _ => panic!("couldn't read iv")
            }
        }
    };
    keybytes.extend_from_slice(&ivb);

    let mut state: [u8;256] = [Default::default();256];
    for k in 0..256 {
        state[k] = k as u8;
    }
    let kl = keybytes.len();
    let mut j = 0;
    for k in 0..256 {
        j = (j + state[k] as usize + keybytes[k % kl] as usize) & 0xff;
        let tmp = state[k];
        state[k] = state[j];
        state[j] = tmp;
    }

    let mut i: usize = 0;
    let mut j: usize = 0;
    for ch in sin.bytes() {
        i = (i + 1) & 0xff;
        j = (j + state[i] as usize) & 0xff;
        let si = state[i];
        let sj = state[j];
        state[i] = sj;
        state[j] = si;
        let plain = ch.unwrap();
        let cipher = state[(si as usize + sj as usize) & 0xff] ^ plain;
        let b = [cipher];
        match sout.write(&b) {
            Ok(_) => (),
            _ => panic!("write error")
        };
    }
}
<|endoftext|>


<commit_before>use super::{Component, Draw};
use crate::err::Result;
use crate::series::LastWatched;
use crate::tui::widget_util::{block, style};
use crate::tui::{CurrentAction, UIState};
use crate::CmdOptions;
use termion::event::Key;
use tui::backend::Backend;
use tui::layout::Rect;
use tui::style::Color;
use tui::terminal::Frame;
use tui::widgets::{List, ListState, Text};

pub struct SeriesList {
    list_state: ListState,
}

impl SeriesList {
    pub fn init(args: &CmdOptions, state: &mut UIState, last_watched: &LastWatched) -> Self {
        let selected = {
            let desired_series = args.series.as_ref().or_else(|| last_watched.get());

            match desired_series {
                Some(desired) => state
                    .series
                    .iter()
                    .position(|series| series.nickname() == desired)
                    .unwrap_or(0),
                None => 0,
            }
        };

        state.series.set_selected(selected);
        state.init_selected_series();

        Self {
            list_state: ListState::default(),
        }
    }
}

impl Component for SeriesList {
    type State = UIState;
    type KeyResult = Result<()>;

    fn process_key(&mut self, key: Key, state: &mut Self::State) -> Self::KeyResult {
        match key {
            Key::Up | Key::Down => {
                match key {
                    Key::Up => state.series.dec_selected(),
                    Key::Down => state.series.inc_selected(),
                    _ => unreachable!(),
                }

                state.init_selected_series();
                Ok(())
            }
            _ => Ok(()),
        }
    }
}

impl<B> Draw<B> for SeriesList
where
    B: Backend,
{
    type State = UIState;

    fn draw(&mut self, state: &Self::State, rect: Rect, frame: &mut Frame<B>) {
        let series_names = state
            .series
            .iter()
            .map(|series| Text::raw(series.nickname()));

        let highlight_style = match &state.current_action {
            CurrentAction::Idle => style::italic().fg(Color::Green),
            _ => style::italic().fg(Color::DarkGray),
        };

        let series_list = List::new(series_names)
            .block(block::with_borders("Series"))
            .style(style::fg(Color::White))
            .highlight_style(highlight_style)
            .highlight_symbol(">");

        self.list_state.select(Some(state.series.index()));

        frame.render_stateful_widget(series_list, rect, &mut self.list_state);
    }
}
<commit_msg>anup: Apply color to each series in the series list based off its current status<commit_after>use super::{Component, Draw};
use crate::err::Result;
use crate::series::LastWatched;
use crate::tui::widget_util::{block, style, text};
use crate::tui::{CurrentAction, SeriesStatus, UIState};
use crate::CmdOptions;
use anime::remote::Status;
use termion::event::Key;
use tui::backend::Backend;
use tui::layout::Rect;
use tui::style::Color;
use tui::terminal::Frame;
use tui::widgets::{List, ListState, Text};

pub struct SeriesList {
    list_state: ListState,
}

impl SeriesList {
    pub fn init(args: &CmdOptions, state: &mut UIState, last_watched: &LastWatched) -> Self {
        let selected = {
            let desired_series = args.series.as_ref().or_else(|| last_watched.get());

            match desired_series {
                Some(desired) => state
                    .series
                    .iter()
                    .position(|series| series.nickname() == desired)
                    .unwrap_or(0),
                None => 0,
            }
        };

        state.series.set_selected(selected);
        state.init_selected_series();

        Self {
            list_state: ListState::default(),
        }
    }

    fn series_text(series: &SeriesStatus) -> Text {
        match series {
            SeriesStatus::Loaded(series) => {
                let color = match series.data.entry.status() {
                    Status::Watching => Color::Blue,
                    Status::Completed => Color::Green,
                    Status::OnHold => Color::Yellow,
                    Status::Dropped => Color::Red,
                    Status::PlanToWatch => Color::Gray,
                    Status::Rewatching => Color::Blue,
                };

                text::with_color(series.data.config.nickname.as_str(), color)
            }
            SeriesStatus::Error(cfg, _) => text::with_color(cfg.nickname.as_str(), Color::LightRed),
        }
    }
}

impl Component for SeriesList {
    type State = UIState;
    type KeyResult = Result<()>;

    fn process_key(&mut self, key: Key, state: &mut Self::State) -> Self::KeyResult {
        match key {
            Key::Up | Key::Down => {
                match key {
                    Key::Up => state.series.dec_selected(),
                    Key::Down => state.series.inc_selected(),
                    _ => unreachable!(),
                }

                state.init_selected_series();
                Ok(())
            }
            _ => Ok(()),
        }
    }
}

impl<B> Draw<B> for SeriesList
where
    B: Backend,
{
    type State = UIState;

    fn draw(&mut self, state: &Self::State, rect: Rect, frame: &mut Frame<B>) {
        let highlight_style = match &state.current_action {
            CurrentAction::Idle => style::italic().fg(Color::Green),
            _ => style::italic().fg(Color::DarkGray),
        };

        let series_names = state.series.iter().map(Self::series_text);

        let series_list = List::new(series_names)
            .block(block::with_borders("Series"))
            .style(style::fg(Color::White))
            .highlight_style(highlight_style)
            .highlight_symbol(">");

        self.list_state.select(Some(state.series.index()));

        frame.render_stateful_widget(series_list, rect, &mut self.list_state);
    }
}
<|endoftext|>


<commit_before>extern crate cmake;
extern crate gcc;
extern crate pkg_config;

use std::env;
use std::ffi::OsString;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

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

fn main() {
    let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
    let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
    let curl = env::var("CARGO_FEATURE_CURL").is_ok();
    if ssh {
        register_dep("SSH2");
    }
    if https {
        register_dep("OPENSSL");
    }
    if curl {
        register_dep("CURL");
    }
    let has_pkgconfig = Command::new("pkg-config").output().is_ok();

    if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    if !Path::new("libgit2/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let windows = target.contains("windows");
    let msvc = target.contains("msvc");
    let mut cfg = cmake::Config::new("libgit2");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cfg.cflag("/GL-");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cfg.define("STATIC_CRT", "OFF");
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install
    // (or when pkg-config isn't found). As a result we just manually turn on
    // SSH support in libgit2 (a little jankily) here...
    if ssh && (windows || !has_pkgconfig) {
        if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
            if msvc {
                cfg.cflag(format!("/I{}", libssh2_include))
                   .cflag("/DGIT_SSH");
            } else {
                cfg.cflag(format!("-I{}", libssh2_include))
                   .cflag("-DGIT_SSH");
            }
        }
    }

    // When cross-compiling, we're pretty unlikely to find a `dlltool` binary
    // lying around, so try to find another if it exists
    if windows && !host.contains("windows") {
        let c_compiler = gcc::Config::new().cargo_metadata(false)
                                           .get_compiler();
        let exe = c_compiler.path();
        let path = env::var_os("PATH").unwrap_or(OsString::new());
        let exe = env::split_paths(&path)
                      .map(|p| p.join(&exe))
                      .find(|p| p.exists());
        if let Some(exe) = exe {
            if let Some(name) = exe.file_name().and_then(|e| e.to_str()) {
                let name = name.replace("gcc", "dlltool");
                let dlltool = exe.with_file_name(name);
                cfg.define("DLLTOOL", &dlltool);
            }
        }
    }

    if ssh {
        cfg.register_dep("SSH2");
    } else {
        cfg.define("USE_SSH", "OFF");
    }
    if https {
        cfg.register_dep("OPENSSL");
    } else {
        cfg.define("USE_OPENSSL", "OFF");
    }
    if curl {
        cfg.register_dep("CURL");
    } else {
        cfg.define("CURL", "OFF");
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
                 .define("BUILD_CLAR", "OFF")
                 .register_dep("Z")
                 .build();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if ssh && !msvc {
        let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
        let mut contents = String::new();
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            panic!("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    // libgit2 requires the http_parser library for the HTTP transport to be
    // implemented, and it will attempt to use the system http_parser if it's
    // available. Detect this situation and report using the system http parser
    // the same way in this situation.
    //
    // Note that other dependencies of libgit2 like openssl, libz, and libssh2
    // are tracked via crates instead of this. Ideally this should be a crate as
    // well.
    let pkgconfig_file = dst.join("lib/pkgconfig/libgit2.pc");
    if let Ok(mut f) = File::open(&pkgconfig_file) {
        let mut contents = String::new();
        t!(f.read_to_string(&mut contents));
        if contents.contains("-lhttp_parser") {
            println!("cargo:rustc-link-lib=http_parser");
        }
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=CoreFoundation");
    }
}

fn register_dep(dep: &str) {
    if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) {
        prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        return
    }
    if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) {
        let root = Path::new(&s).parent().unwrap();
        env::set_var(&format!("DEP_{}_ROOT", dep), root);
        let path = root.join("lib/pkgconfig");
        if path.exists() {
            prepend("PKG_CONFIG_PATH", path);
            return
        }
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}
<commit_msg>Support /MT on MSVC<commit_after>extern crate cmake;
extern crate gcc;
extern crate pkg_config;

use std::env;
use std::ffi::OsString;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

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

fn main() {
    let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
    let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
    let curl = env::var("CARGO_FEATURE_CURL").is_ok();
    if ssh {
        register_dep("SSH2");
    }
    if https {
        register_dep("OPENSSL");
    }
    if curl {
        register_dep("CURL");
    }
    let has_pkgconfig = Command::new("pkg-config").output().is_ok();

    if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    if !Path::new("libgit2/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let windows = target.contains("windows");
    let msvc = target.contains("msvc");
    let mut cfg = cmake::Config::new("libgit2");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cfg.cflag("/GL-");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        let features = env::var("CARGO_CFG_TARGET_FEATURE")
                          .unwrap_or(String::new());
        if features.contains("crt-static") {
            cfg.define("STATIC_CRT", "ON");
        } else {
            cfg.define("STATIC_CRT", "OFF");
        }
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install
    // (or when pkg-config isn't found). As a result we just manually turn on
    // SSH support in libgit2 (a little jankily) here...
    if ssh && (windows || !has_pkgconfig) {
        if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
            if msvc {
                cfg.cflag(format!("/I{}", libssh2_include))
                   .cflag("/DGIT_SSH");
            } else {
                cfg.cflag(format!("-I{}", libssh2_include))
                   .cflag("-DGIT_SSH");
            }
        }
    }

    // When cross-compiling, we're pretty unlikely to find a `dlltool` binary
    // lying around, so try to find another if it exists
    if windows && !host.contains("windows") {
        let c_compiler = gcc::Config::new().cargo_metadata(false)
                                           .get_compiler();
        let exe = c_compiler.path();
        let path = env::var_os("PATH").unwrap_or(OsString::new());
        let exe = env::split_paths(&path)
                      .map(|p| p.join(&exe))
                      .find(|p| p.exists());
        if let Some(exe) = exe {
            if let Some(name) = exe.file_name().and_then(|e| e.to_str()) {
                let name = name.replace("gcc", "dlltool");
                let dlltool = exe.with_file_name(name);
                cfg.define("DLLTOOL", &dlltool);
            }
        }
    }

    if ssh {
        cfg.register_dep("SSH2");
    } else {
        cfg.define("USE_SSH", "OFF");
    }
    if https {
        cfg.register_dep("OPENSSL");
    } else {
        cfg.define("USE_OPENSSL", "OFF");
    }
    if curl {
        cfg.register_dep("CURL");
    } else {
        cfg.define("CURL", "OFF");
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
                 .define("BUILD_CLAR", "OFF")
                 .register_dep("Z")
                 .build();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if ssh && !msvc {
        let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
        let mut contents = String::new();
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            panic!("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    // libgit2 requires the http_parser library for the HTTP transport to be
    // implemented, and it will attempt to use the system http_parser if it's
    // available. Detect this situation and report using the system http parser
    // the same way in this situation.
    //
    // Note that other dependencies of libgit2 like openssl, libz, and libssh2
    // are tracked via crates instead of this. Ideally this should be a crate as
    // well.
    let pkgconfig_file = dst.join("lib/pkgconfig/libgit2.pc");
    if let Ok(mut f) = File::open(&pkgconfig_file) {
        let mut contents = String::new();
        t!(f.read_to_string(&mut contents));
        if contents.contains("-lhttp_parser") {
            println!("cargo:rustc-link-lib=http_parser");
        }
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=CoreFoundation");
    }
}

fn register_dep(dep: &str) {
    if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) {
        prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        return
    }
    if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) {
        let root = Path::new(&s).parent().unwrap();
        env::set_var(&format!("DEP_{}_ROOT", dep), root);
        let path = root.join("lib/pkgconfig");
        if path.exists() {
            prepend("PKG_CONFIG_PATH", path);
            return
        }
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}
<|endoftext|>