<commit_before>#[macro_use] extern crate quick_error;
#[macro_use] extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate chrono;
extern crate curl;

mod error;

use serde_json::Value;
use chrono::{NaiveDate, NaiveTime};
use curl::easy::Easy;
use std::str;
use std::str::FromStr;
use std::cell::RefCell;
use std::rc::Rc;
use error::Error;

pub fn get_weather<L: Into<&'static str>>(location: L) -> Result<Weather, Error> {
    // get the json values
    let json: Value = serde_json::from_str(&get_raw_data(location)?)?;
    // define the root data point
    let json = json.pointer("/query/results/channel").ok_or(Error::NoData)?;

    // set the weather
    let mut weather = Weather {
        temp: json.pointer("/item/condition/temp").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        temp_unit: json.pointer("/units/temperature").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        condition_code: usize::from_str(json.pointer("/item/condition/code").and_then(|v| v.as_str()).unwrap_or("")).unwrap_or(3200),
        condition: json.pointer("/item/condition/text").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        sunrise: NaiveTime::parse_from_str(json.pointer("/astronomy/sunrise").and_then(|v| v.as_str()).unwrap_or(""), "%l:%M %P")?,
        sunset: NaiveTime::parse_from_str(json.pointer("/astronomy/sunset").and_then(|v| v.as_str()).unwrap_or(""), "%l:%M %P")?,
        forecast: vec!()
    };

    // fill the forecast list with the data from the json
    for point in json.pointer("/item/forecast").ok_or(Error::NoData)?.as_array().ok_or(Error::NoData)? {
        weather.forecast.push(DataPoint {
            date: NaiveDate::parse_from_str(point.get("date").and_then(|v| v.as_str()).unwrap_or(""), "%d %b %Y")?,
            temp_high: point.get("high").and_then(|v| v.as_str()).unwrap_or("").to_string(),
            temp_low: point.get("low").and_then(|v| v.as_str()).unwrap_or("").to_string(),
            condition_code: usize::from_str(point.get("code").and_then(|v| v.as_str()).unwrap_or("")).unwrap_or(3200),
            condition: point.get("text").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        });
    }

    Ok(weather)
}

/// Request the data fromt the yahoo api and return the
/// result as String.
fn get_raw_data<L: Into<&'static str>>(location: L) -> Result<String, Error> {
    // define the empty contet string
    let content = Rc::new(RefCell::new("".to_string()));

    // prepare curl to load the data
    let mut curl = Easy::new();
    // define the url
    curl.url(format!("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22{}%2C%20de%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys", location.into()).as_str()).unwrap();
    // define how to handle the content
    let mut transfer = curl.transfer();

    // define the value return
    transfer.write_function(|data| {
        match str::from_utf8(data) {
            Ok(v) => {
                content.borrow_mut().push_str(v);
                return Ok(data.len());
            },
            Err(_) => Ok(data.len())
        }
    })?;

    // execute
    transfer.perform()?;

    // return the content
    let x = content.borrow_mut().clone();
    Ok(x)
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Weather {
    temp: String,
    temp_unit: String,
    condition_code: usize,
    condition: String,
    sunrise: NaiveTime,
    sunset: NaiveTime,
    forecast: Vec<DataPoint>
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DataPoint {
    date: NaiveDate,
    temp_high: String,
    temp_low: String,
    condition_code: usize,
    condition: String
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        println!("Weather: {:?}", get_weather("Ransbach-Baumbach").unwrap());
    }
}
<commit_msg>Make error public<commit_after>#[macro_use] extern crate quick_error;
#[macro_use] extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate chrono;
extern crate curl;

pub mod error;

use serde_json::Value;
use chrono::{NaiveDate, NaiveTime};
use curl::easy::Easy;
use std::str;
use std::str::FromStr;
use std::cell::RefCell;
use std::rc::Rc;
use error::Error;

pub fn get_weather<L: Into<&'static str>>(location: L) -> Result<Weather, Error> {
    // get the json values
    let json: Value = serde_json::from_str(&get_raw_data(location)?)?;
    // define the root data point
    let json = json.pointer("/query/results/channel").ok_or(Error::NoData)?;

    // set the weather
    let mut weather = Weather {
        temp: json.pointer("/item/condition/temp").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        temp_unit: json.pointer("/units/temperature").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        condition_code: usize::from_str(json.pointer("/item/condition/code").and_then(|v| v.as_str()).unwrap_or("")).unwrap_or(3200),
        condition: json.pointer("/item/condition/text").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        sunrise: NaiveTime::parse_from_str(json.pointer("/astronomy/sunrise").and_then(|v| v.as_str()).unwrap_or(""), "%l:%M %P")?,
        sunset: NaiveTime::parse_from_str(json.pointer("/astronomy/sunset").and_then(|v| v.as_str()).unwrap_or(""), "%l:%M %P")?,
        forecast: vec!()
    };

    // fill the forecast list with the data from the json
    for point in json.pointer("/item/forecast").ok_or(Error::NoData)?.as_array().ok_or(Error::NoData)? {
        weather.forecast.push(DataPoint {
            date: NaiveDate::parse_from_str(point.get("date").and_then(|v| v.as_str()).unwrap_or(""), "%d %b %Y")?,
            temp_high: point.get("high").and_then(|v| v.as_str()).unwrap_or("").to_string(),
            temp_low: point.get("low").and_then(|v| v.as_str()).unwrap_or("").to_string(),
            condition_code: usize::from_str(point.get("code").and_then(|v| v.as_str()).unwrap_or("")).unwrap_or(3200),
            condition: point.get("text").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        });
    }

    Ok(weather)
}

/// Request the data fromt the yahoo api and return the
/// result as String.
fn get_raw_data<L: Into<&'static str>>(location: L) -> Result<String, Error> {
    // define the empty contet string
    let content = Rc::new(RefCell::new("".to_string()));

    // prepare curl to load the data
    let mut curl = Easy::new();
    // define the url
    curl.url(format!("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22{}%2C%20de%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys", location.into()).as_str()).unwrap();
    // define how to handle the content
    let mut transfer = curl.transfer();

    // define the value return
    transfer.write_function(|data| {
        match str::from_utf8(data) {
            Ok(v) => {
                content.borrow_mut().push_str(v);
                return Ok(data.len());
            },
            Err(_) => Ok(data.len())
        }
    })?;

    // execute
    transfer.perform()?;

    // return the content
    let x = content.borrow_mut().clone();
    Ok(x)
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Weather {
    temp: String,
    temp_unit: String,
    condition_code: usize,
    condition: String,
    sunrise: NaiveTime,
    sunset: NaiveTime,
    forecast: Vec<DataPoint>
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DataPoint {
    date: NaiveDate,
    temp_high: String,
    temp_low: String,
    condition_code: usize,
    condition: String
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        println!("Weather: {:?}", get_weather("Ransbach-Baumbach").unwrap());
    }
}
<|endoftext|>


<commit_before>//! Open URLs in the web browsers available on a platform.
//!
//! Inspired by the [webbrowser](https://docs.python.org/2/library/webbrowser.html) python library.
//!
//! Currently state of platform support is:
//!
//! * macos => default, as well as browsers listed under [Browser](enum.Browser.html)
//! * windows => default browser only
//! * linux => default browser only (uses $BROWSER env var, failing back to xdg-open, gvfs-open and
//! gnome-open, in that order)
//! * android => not supported right now
//! * ios => not supported right now
//!
//! Important note:
//!
//! * This library requires availability of browsers and a graphical environment during runtime
//! * `cargo test` will actually open the browser locally.
//!
//! # Examples
//!
//! ```
//! use webbrowser;
//!
//! if webbrowser::open("http://github.com").is_ok() {
//!     // ...
//! }
//! ```

use std::process::{Command, Output};
use std::io::{Result, Error, ErrorKind};
use std::default::Default;
use std::fmt;
use std::str::FromStr;
use std::error;

#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
/// Browser types available
pub enum Browser {
    ///Operating system's default browser
    Default,

    ///Mozilla Firefox
    Firefox,

    ///Microsoft's Internet Explorer
    InternetExplorer,

    ///Google Chrome
    Chrome,

    ///Opera
    Opera,

    ///Mac OS Safari
    Safari
}

///The Error type for parsing a string into a Browser.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub struct ParseBrowserError;

impl fmt::Display for ParseBrowserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("Invalid browser given")
    }
}

impl error::Error for ParseBrowserError {
    fn description(&self) -> &str {
        "invalid browser"
    }
}

impl Default for Browser {
    fn default() -> Self {
        Browser::Default
    }
}

impl fmt::Display for Browser {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Browser::Default => f.write_str("Default"),
            Browser::Firefox => f.write_str("Firefox"),
            Browser::InternetExplorer => f.write_str("Internet Explorer"),
            Browser::Chrome => f.write_str("Chrome"),
            Browser::Opera => f.write_str("Opera"),
            Browser::Safari => f.write_str("Safari"),
        }
    }
}

impl FromStr for Browser {
    type Err = ParseBrowserError;

    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        match s {
            "firefox" => Ok(Browser::Firefox),
            "default" => Ok(Browser::Default),
            "ie" | "internet explorer" | "internetexplorer" => Ok(Browser::InternetExplorer),
            "chrome" => Ok(Browser::Chrome),
            "opera" => Ok(Browser::Opera),
            "safari" => Ok(Browser::Safari),
            _ => Err(ParseBrowserError)
        }
    }
}

/// Opens the URL on the default browser of this platform
///
/// Returns Ok(..) so long as the browser invocation was successful. An Err(..) is returned only if
/// there was an error in running the command, or if the browser was not found.
///
/// Equivalent to:
/// ```
/// # use webbrowser::{Browser, open_browser};
/// # let url = "http://example.com";
/// open_browser(Browser::Default, url);
/// ```
///
/// # Examples
/// ```
/// use webbrowser;
///
/// if webbrowser::open("http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open(url: &str) -> Result<Output> {
    open_browser(Browser::Default, url)
}

/// Opens the specified URL on the specific browser (if available) requested. Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```
/// use webbrowser::{open_browser, Browser};
///
/// if open_browser(Browser::Firefox, "http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser(browser: Browser, url: &str) -> Result<Output> {
    open_browser_internal(browser, url)
}

/// Deal with opening of browsers on Windows, using `start` command
#[cfg(target_os = "windows")]
#[inline]
fn open_browser_internal(browser: Browser, url: &str) -> Result<Output> {
    match browser {
        Browser::Default => Command::new("cmd").arg("/C").arg("start").arg(url).output(),
        _ => Err(Error::new(
            ErrorKind::NotFound,
            "Only the default browser is supported on this platform right now"
        ))
    }
}

/// Deal with opening of browsers on Mac OS X, using `open` command
#[cfg(target_os = "macos")]
#[inline]
fn open_browser_internal(browser: Browser, url: &str) -> Result<Output> {
    let mut cmd = Command::new("open");
    match browser {
        Browser::Default => cmd.arg(url).output(),
        _ => {
            let app: Option<&str> = match browser {
                Browser::Firefox => Some("Firefox"),
                Browser::Chrome => Some("Google Chrome"),
                Browser::Opera => Some("Opera"),
                Browser::Safari => Some("Safari"),
                _ => None
            };
            match app {
                Some(name) => cmd.arg("-a").arg(name).arg(url).output(),
                None => Err(Error::new(ErrorKind::NotFound, format!("Unsupported browser {:?}", browser)))
            }
        }
    }
}

/// Deal with opening of browsers on Linux - currently supports only the default browser
///
/// The mechanism of opening the default browser is as follows:
/// 1. Attempt to use $BROWSER env var if available
/// 2. Attempt to open the url via xdg-open, gvfs-open, gnome-open, respectively, whichever works
///    first
#[cfg(target_os = "linux")]
#[inline]
fn open_browser_internal(browser: Browser, url: &str) -> Result<Output> {
    match browser {
        Browser::Default => open_on_linux_using_browser_env(url)
            .or_else(|_| -> Result<Output> {Command::new("xdg-open").arg(url).output()})
            .or_else(|_| -> Result<Output> {Command::new("gvfs-open").arg(url).output()})
            .or_else(|_| -> Result<Output> {Command::new("gnome-open").arg(url).output()}),
        _ => Err(Error::new(
                ErrorKind::NotFound,
                "Only the default browser is supported on this platform right now"
            ))
    }
}

/// Open on Linux using the $BROWSER env var
#[cfg(target_os = "linux")]
fn open_on_linux_using_browser_env(url: &str) -> Result<Output> {
    let browsers = env::var("BROWSER").map_err(|_| -> Error { Error::new(ErrorKind::NotFound, format!("BROWSER env not set")) })?;
    for browser in browsers.split(':') { // $BROWSER can contain ':' delimited options, each representing a potential browser command line
        if !browser.is_empty() {
            // each browser command can have %s to represent URL, while %c needs to be replaced
            // with ':' and %% with '%'
            let cmdline = browser.replace("%s", url).replace("%c", ":").replace("%%", "%");
            let cmdarr: Vec<&str> = cmdline.split_whitespace().collect();
            let mut cmd = Command::new(&cmdarr[0]);
            if cmdarr.len() > 1 {
                cmd.args(&cmdarr[1..cmdarr.len()]);
            }
            if !browser.contains("%s") {
                // append the url as an argument only if it was not already set via %s
                cmd.arg(url);
            }
            if let Ok(output) = cmd.output() {
                return Ok(output);
            }
        }
    }
    return Err(Error::new(ErrorKind::NotFound, "No valid command in $BROWSER"));
}

#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
compile_error!("Only Windows, Mac OS and Linux are currently supported");

#[test]
fn test_open_default() {
    assert!(open("http://github.com").is_ok());
}

#[test]
#[cfg(target_os = "macos")]
fn test_open_browser() {
    assert!(open_browser(Browser::Firefox, "http://github.com").is_ok());
}
<commit_msg>Fix undeclared reference to `env`<commit_after>//! Open URLs in the web browsers available on a platform.
//!
//! Inspired by the [webbrowser](https://docs.python.org/2/library/webbrowser.html) python library.
//!
//! Currently state of platform support is:
//!
//! * macos => default, as well as browsers listed under [Browser](enum.Browser.html)
//! * windows => default browser only
//! * linux => default browser only (uses $BROWSER env var, failing back to xdg-open, gvfs-open and
//! gnome-open, in that order)
//! * android => not supported right now
//! * ios => not supported right now
//!
//! Important note:
//!
//! * This library requires availability of browsers and a graphical environment during runtime
//! * `cargo test` will actually open the browser locally.
//!
//! # Examples
//!
//! ```
//! use webbrowser;
//!
//! if webbrowser::open("http://github.com").is_ok() {
//!     // ...
//! }
//! ```

use std::process::{Command, Output};
use std::io::{Result, Error, ErrorKind};
use std::default::Default;
use std::fmt;
use std::str::FromStr;
use std::error;

#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
/// Browser types available
pub enum Browser {
    ///Operating system's default browser
    Default,

    ///Mozilla Firefox
    Firefox,

    ///Microsoft's Internet Explorer
    InternetExplorer,

    ///Google Chrome
    Chrome,

    ///Opera
    Opera,

    ///Mac OS Safari
    Safari
}

///The Error type for parsing a string into a Browser.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub struct ParseBrowserError;

impl fmt::Display for ParseBrowserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("Invalid browser given")
    }
}

impl error::Error for ParseBrowserError {
    fn description(&self) -> &str {
        "invalid browser"
    }
}

impl Default for Browser {
    fn default() -> Self {
        Browser::Default
    }
}

impl fmt::Display for Browser {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Browser::Default => f.write_str("Default"),
            Browser::Firefox => f.write_str("Firefox"),
            Browser::InternetExplorer => f.write_str("Internet Explorer"),
            Browser::Chrome => f.write_str("Chrome"),
            Browser::Opera => f.write_str("Opera"),
            Browser::Safari => f.write_str("Safari"),
        }
    }
}

impl FromStr for Browser {
    type Err = ParseBrowserError;

    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        match s {
            "firefox" => Ok(Browser::Firefox),
            "default" => Ok(Browser::Default),
            "ie" | "internet explorer" | "internetexplorer" => Ok(Browser::InternetExplorer),
            "chrome" => Ok(Browser::Chrome),
            "opera" => Ok(Browser::Opera),
            "safari" => Ok(Browser::Safari),
            _ => Err(ParseBrowserError)
        }
    }
}

/// Opens the URL on the default browser of this platform
///
/// Returns Ok(..) so long as the browser invocation was successful. An Err(..) is returned only if
/// there was an error in running the command, or if the browser was not found.
///
/// Equivalent to:
/// ```
/// # use webbrowser::{Browser, open_browser};
/// # let url = "http://example.com";
/// open_browser(Browser::Default, url);
/// ```
///
/// # Examples
/// ```
/// use webbrowser;
///
/// if webbrowser::open("http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open(url: &str) -> Result<Output> {
    open_browser(Browser::Default, url)
}

/// Opens the specified URL on the specific browser (if available) requested. Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```
/// use webbrowser::{open_browser, Browser};
///
/// if open_browser(Browser::Firefox, "http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser(browser: Browser, url: &str) -> Result<Output> {
    open_browser_internal(browser, url)
}

/// Deal with opening of browsers on Windows, using `start` command
#[cfg(target_os = "windows")]
#[inline]
fn open_browser_internal(browser: Browser, url: &str) -> Result<Output> {
    match browser {
        Browser::Default => Command::new("cmd").arg("/C").arg("start").arg(url).output(),
        _ => Err(Error::new(
            ErrorKind::NotFound,
            "Only the default browser is supported on this platform right now"
        ))
    }
}

/// Deal with opening of browsers on Mac OS X, using `open` command
#[cfg(target_os = "macos")]
#[inline]
fn open_browser_internal(browser: Browser, url: &str) -> Result<Output> {
    let mut cmd = Command::new("open");
    match browser {
        Browser::Default => cmd.arg(url).output(),
        _ => {
            let app: Option<&str> = match browser {
                Browser::Firefox => Some("Firefox"),
                Browser::Chrome => Some("Google Chrome"),
                Browser::Opera => Some("Opera"),
                Browser::Safari => Some("Safari"),
                _ => None
            };
            match app {
                Some(name) => cmd.arg("-a").arg(name).arg(url).output(),
                None => Err(Error::new(ErrorKind::NotFound, format!("Unsupported browser {:?}", browser)))
            }
        }
    }
}

/// Deal with opening of browsers on Linux - currently supports only the default browser
///
/// The mechanism of opening the default browser is as follows:
/// 1. Attempt to use $BROWSER env var if available
/// 2. Attempt to open the url via xdg-open, gvfs-open, gnome-open, respectively, whichever works
///    first
#[cfg(target_os = "linux")]
#[inline]
fn open_browser_internal(browser: Browser, url: &str) -> Result<Output> {
    match browser {
        Browser::Default => open_on_linux_using_browser_env(url)
            .or_else(|_| -> Result<Output> {Command::new("xdg-open").arg(url).output()})
            .or_else(|_| -> Result<Output> {Command::new("gvfs-open").arg(url).output()})
            .or_else(|_| -> Result<Output> {Command::new("gnome-open").arg(url).output()}),
        _ => Err(Error::new(
                ErrorKind::NotFound,
                "Only the default browser is supported on this platform right now"
            ))
    }
}

/// Open on Linux using the $BROWSER env var
#[cfg(target_os = "linux")]
fn open_on_linux_using_browser_env(url: &str) -> Result<Output> {
    let browsers = ::std::env::var("BROWSER").map_err(|_| -> Error { Error::new(ErrorKind::NotFound, format!("BROWSER env not set")) })?;
    for browser in browsers.split(':') { // $BROWSER can contain ':' delimited options, each representing a potential browser command line
        if !browser.is_empty() {
            // each browser command can have %s to represent URL, while %c needs to be replaced
            // with ':' and %% with '%'
            let cmdline = browser.replace("%s", url).replace("%c", ":").replace("%%", "%");
            let cmdarr: Vec<&str> = cmdline.split_whitespace().collect();
            let mut cmd = Command::new(&cmdarr[0]);
            if cmdarr.len() > 1 {
                cmd.args(&cmdarr[1..cmdarr.len()]);
            }
            if !browser.contains("%s") {
                // append the url as an argument only if it was not already set via %s
                cmd.arg(url);
            }
            if let Ok(output) = cmd.output() {
                return Ok(output);
            }
        }
    }
    return Err(Error::new(ErrorKind::NotFound, "No valid command in $BROWSER"));
}

#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
compile_error!("Only Windows, Mac OS and Linux are currently supported");

#[test]
fn test_open_default() {
    assert!(open("http://github.com").is_ok());
}

#[test]
#[cfg(target_os = "macos")]
fn test_open_browser() {
    assert!(open_browser(Browser::Firefox, "http://github.com").is_ok());
}
<|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/. */

#![crate_name = "azure"]
#![crate_type = "rlib"]
#![cfg_attr(feature = "plugins", feature(custom_derive, plugin, proc_macro, rustc_attrs))]

extern crate libc;
#[cfg(feature = "plugins")]
extern crate serde;
#[cfg(feature = "plugins")]
#[macro_use]
extern crate serde_derive;
extern crate euclid;
extern crate skia;

pub use azure::{AzFontOptions, AzFloat, enum_AzSurfaceType, AZ_SURFACE_DATA,
                AZ_SURFACE_D2D1_BITMAP, AZ_SURFACE_D2D1_DRAWTARGET, AZ_SURFACE_CAIRO, AZ_SURFACE_CAIRO_IMAGE,
                AZ_SURFACE_COREGRAPHICS_IMAGE, AZ_SURFACE_COREGRAPHICS_CGCONTEXT, AZ_SURFACE_SKIA, AZ_SURFACE_DUAL_DT,
                enum_AzSurfaceFormat, AZ_FORMAT_B8G8R8A8, AZ_FORMAT_B8G8R8X8, AZ_FORMAT_R5G6B5,
                AZ_FORMAT_A8, AzSurfaceFormat, enum_AzBackendType, AZ_BACKEND_NONE,
                AZ_BACKEND_DIRECT2D, AZ_BACKEND_COREGRAPHICS, AZ_BACKEND_COREGRAPHICS_ACCELERATED, AZ_BACKEND_CAIRO,
                AZ_BACKEND_SKIA, AZ_BACKEND_RECORDING, AzBackendType, enum_AzFontType,
                AZ_FONT_DWRITE, AZ_FONT_GDI, AZ_FONT_MAC, AZ_FONT_SKIA,
                AZ_FONT_CAIRO, AZ_FONT_COREGRAPHICS, enum_AzNativeSurfaceType, AZ_NATIVE_SURFACE_D3D10_TEXTURE,
                AZ_NATIVE_SURFACE_CAIRO_SURFACE, AZ_NATIVE_SURFACE_CGCONTEXT, enum_AzNativeFontType, AZ_NATIVE_FONT_DWRITE_FONT_FACE,
                AZ_NATIVE_FONT_GDI_FONT_FACE, AZ_NATIVE_FONT_MAC_FONT_FACE, AZ_NATIVE_FONT_SKIA_FONT_FACE, AZ_NATIVE_FONT_CAIRO_FONT_FACE,
                enum_AzFontStyle, AZ_FONT_STYLE_NORMAL, AZ_FONT_STYLE_ITALIC, AZ_FONT_STYLE_BOLD,
                AZ_FONT_STYLE_BOLD_ITALIC, enum_AzCompositionOp, AZ_OP_OVER, AZ_OP_ADD,
                AZ_OP_ATOP, AZ_OP_OUT, AZ_OP_IN, AZ_OP_SOURCE,
                AZ_OP_DEST_IN, AZ_OP_DEST_OUT, AZ_OP_DEST_OVER, AZ_OP_DEST_ATOP,
                AZ_OP_XOR, AZ_OP_MULTIPLY, AZ_OP_SCREEN, AZ_OP_OVERLAY,
                AZ_OP_DARKEN, AZ_OP_LIGHTEN, AZ_OP_COLOR_DODGE, AZ_OP_COLOR_BURN,
                AZ_OP_HARD_LIGHT, AZ_OP_SOFT_LIGHT, AZ_OP_DIFFERENCE, AZ_OP_EXCLUSION,
                AZ_OP_HUE, AZ_OP_SATURATION, AZ_OP_COLOR, AZ_OP_LUMINOSITY,
                AZ_OP_COUNT, enum_AzExtendMode, AZ_EXTEND_CLAMP, AZ_EXTEND_REPEAT,
                AZ_EXTEND_REFLECT, enum_AzFillRule, AZ_FILL_WINDING, AZ_FILL_EVEN_ODD,
                enum_AzAntialiasMode, AZ_AA_NONE, AZ_AA_GRAY, AZ_AA_SUBPIXEL,
                enum_AzFilter, AZ_FILTER_LINEAR, AZ_FILTER_POINT, AzFilter, enum_AzPatternType,
                AZ_PATTERN_COLOR, AZ_PATTERN_SURFACE, AZ_PATTERN_LINEAR_GRADIENT, AZ_PATTERN_RADIAL_GRADIENT,
                enum_AzJoinStyle, AZ_JOIN_BEVEL, AZ_JOIN_ROUND, AZ_JOIN_MITER,
                AZ_JOIN_MITER_OR_BEVEL, enum_AzCapStyle, AZ_CAP_BUTT, AZ_CAP_ROUND,
                AZ_CAP_SQUARE, enum_AzSamplingBounds, AZ_SAMPLING_UNBOUNDED, AZ_SAMPLING_BOUNDED,
                enum_AzSide, AZ_eSideTop, AZ_eSideRight, AZ_eSideBottom,
                AZ_eSideLeft, struct__AzColor, AzColor, struct__AzGradientStop,
                AzGradientStop, struct__AzIntRect, AzIntRect, struct__AzRect,
                AzRect, struct__AzIntPoint, AzIntPoint, struct__AzPoint,
                AzPoint, struct__AzIntSize, AzIntSize, struct__AzSize,
                AzSize, struct__AzMatrix, AzMatrix, struct__AzDrawOptions,
                AzDrawOptions, struct__AzStrokeOptions, AzStrokeOptions, struct__AzDrawSurfaceOptions,
                AzDrawSurfaceOptions, struct__AzGlyph, AzGlyph, struct__AzGlyphBuffer,
                AzGlyphBuffer, struct__AzNativeFont, AzNativeFont, AzGradientStopsRef,
                AzDrawTargetRef, AzPatternRef, AzColorPatternRef, AzScaledFontRef,
                AzGlyphRenderingOptionsRef, AzSourceSurfaceRef, AzDataSourceSurfaceRef, AzDrawSurfaceOptionsRef,
                AzGLContext, AzGLContextMetadataRef,
                AzPathRef, AzPathBuilderRef, AzSanityCheck, AzCreateColorPattern,
                AzCreateDrawTarget, AzCreateDrawTargetForData, AzCreateDrawTargetSkiaWithGrContextAndFBO,
                AzRetainDrawTarget, AzReleaseDrawTarget, AzDrawTargetGetSize, AzDrawTargetFlush,
                AzDrawTargetClearRect, AzDrawTargetCopySurface, AzDrawTargetFillRect, AzDrawTargetStrokeRect, AzDrawTargetStrokeLine,
                AzDrawTargetFill, AzDrawTargetStroke, AzDrawTargetPushClip, AzDrawTargetPopClip, AzDrawTargetFillGlyphs,
                AzDrawTargetDrawSurface, AzDrawTargetGetSnapshot, AzDrawTargetCreateSourceSurfaceFromData, AzReleaseSourceSurface,
                AzSourceSurfaceGetSize, AzSourceSurfaceGetFormat, AzSourceSurfaceGetDataSurface, AzDataSourceSurfaceGetData,
                AzDataSourceSurfaceGetStride, AzCreateScaledFontForNativeFont, AzReleaseScaledFont, AzDrawTargetSetTransform,
                AzCreateFontOptionsForName, AzDestroyFontOptions, AzCreatePathBuilder, AzPathCopyToBuilder, AzPathContainsPoint,
                AzReleasePathBuilder, AzPathBuilderMoveTo, AzPathBuilderLineTo, AzPathBuilderFinish, AzReleasePath};

pub mod azure_hl;

#[cfg(target_os = "linux")]
pub mod test;

pub mod linkhack;

pub mod azure;
<commit_msg>Remove unused rust features<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/. */

#![crate_name = "azure"]
#![crate_type = "rlib"]

extern crate libc;
#[cfg(feature = "plugins")]
extern crate serde;
#[cfg(feature = "plugins")]
#[macro_use]
extern crate serde_derive;
extern crate euclid;
extern crate skia;

pub use azure::{AzFontOptions, AzFloat, enum_AzSurfaceType, AZ_SURFACE_DATA,
                AZ_SURFACE_D2D1_BITMAP, AZ_SURFACE_D2D1_DRAWTARGET, AZ_SURFACE_CAIRO, AZ_SURFACE_CAIRO_IMAGE,
                AZ_SURFACE_COREGRAPHICS_IMAGE, AZ_SURFACE_COREGRAPHICS_CGCONTEXT, AZ_SURFACE_SKIA, AZ_SURFACE_DUAL_DT,
                enum_AzSurfaceFormat, AZ_FORMAT_B8G8R8A8, AZ_FORMAT_B8G8R8X8, AZ_FORMAT_R5G6B5,
                AZ_FORMAT_A8, AzSurfaceFormat, enum_AzBackendType, AZ_BACKEND_NONE,
                AZ_BACKEND_DIRECT2D, AZ_BACKEND_COREGRAPHICS, AZ_BACKEND_COREGRAPHICS_ACCELERATED, AZ_BACKEND_CAIRO,
                AZ_BACKEND_SKIA, AZ_BACKEND_RECORDING, AzBackendType, enum_AzFontType,
                AZ_FONT_DWRITE, AZ_FONT_GDI, AZ_FONT_MAC, AZ_FONT_SKIA,
                AZ_FONT_CAIRO, AZ_FONT_COREGRAPHICS, enum_AzNativeSurfaceType, AZ_NATIVE_SURFACE_D3D10_TEXTURE,
                AZ_NATIVE_SURFACE_CAIRO_SURFACE, AZ_NATIVE_SURFACE_CGCONTEXT, enum_AzNativeFontType, AZ_NATIVE_FONT_DWRITE_FONT_FACE,
                AZ_NATIVE_FONT_GDI_FONT_FACE, AZ_NATIVE_FONT_MAC_FONT_FACE, AZ_NATIVE_FONT_SKIA_FONT_FACE, AZ_NATIVE_FONT_CAIRO_FONT_FACE,
                enum_AzFontStyle, AZ_FONT_STYLE_NORMAL, AZ_FONT_STYLE_ITALIC, AZ_FONT_STYLE_BOLD,
                AZ_FONT_STYLE_BOLD_ITALIC, enum_AzCompositionOp, AZ_OP_OVER, AZ_OP_ADD,
                AZ_OP_ATOP, AZ_OP_OUT, AZ_OP_IN, AZ_OP_SOURCE,
                AZ_OP_DEST_IN, AZ_OP_DEST_OUT, AZ_OP_DEST_OVER, AZ_OP_DEST_ATOP,
                AZ_OP_XOR, AZ_OP_MULTIPLY, AZ_OP_SCREEN, AZ_OP_OVERLAY,
                AZ_OP_DARKEN, AZ_OP_LIGHTEN, AZ_OP_COLOR_DODGE, AZ_OP_COLOR_BURN,
                AZ_OP_HARD_LIGHT, AZ_OP_SOFT_LIGHT, AZ_OP_DIFFERENCE, AZ_OP_EXCLUSION,
                AZ_OP_HUE, AZ_OP_SATURATION, AZ_OP_COLOR, AZ_OP_LUMINOSITY,
                AZ_OP_COUNT, enum_AzExtendMode, AZ_EXTEND_CLAMP, AZ_EXTEND_REPEAT,
                AZ_EXTEND_REFLECT, enum_AzFillRule, AZ_FILL_WINDING, AZ_FILL_EVEN_ODD,
                enum_AzAntialiasMode, AZ_AA_NONE, AZ_AA_GRAY, AZ_AA_SUBPIXEL,
                enum_AzFilter, AZ_FILTER_LINEAR, AZ_FILTER_POINT, AzFilter, enum_AzPatternType,
                AZ_PATTERN_COLOR, AZ_PATTERN_SURFACE, AZ_PATTERN_LINEAR_GRADIENT, AZ_PATTERN_RADIAL_GRADIENT,
                enum_AzJoinStyle, AZ_JOIN_BEVEL, AZ_JOIN_ROUND, AZ_JOIN_MITER,
                AZ_JOIN_MITER_OR_BEVEL, enum_AzCapStyle, AZ_CAP_BUTT, AZ_CAP_ROUND,
                AZ_CAP_SQUARE, enum_AzSamplingBounds, AZ_SAMPLING_UNBOUNDED, AZ_SAMPLING_BOUNDED,
                enum_AzSide, AZ_eSideTop, AZ_eSideRight, AZ_eSideBottom,
                AZ_eSideLeft, struct__AzColor, AzColor, struct__AzGradientStop,
                AzGradientStop, struct__AzIntRect, AzIntRect, struct__AzRect,
                AzRect, struct__AzIntPoint, AzIntPoint, struct__AzPoint,
                AzPoint, struct__AzIntSize, AzIntSize, struct__AzSize,
                AzSize, struct__AzMatrix, AzMatrix, struct__AzDrawOptions,
                AzDrawOptions, struct__AzStrokeOptions, AzStrokeOptions, struct__AzDrawSurfaceOptions,
                AzDrawSurfaceOptions, struct__AzGlyph, AzGlyph, struct__AzGlyphBuffer,
                AzGlyphBuffer, struct__AzNativeFont, AzNativeFont, AzGradientStopsRef,
                AzDrawTargetRef, AzPatternRef, AzColorPatternRef, AzScaledFontRef,
                AzGlyphRenderingOptionsRef, AzSourceSurfaceRef, AzDataSourceSurfaceRef, AzDrawSurfaceOptionsRef,
                AzGLContext, AzGLContextMetadataRef,
                AzPathRef, AzPathBuilderRef, AzSanityCheck, AzCreateColorPattern,
                AzCreateDrawTarget, AzCreateDrawTargetForData, AzCreateDrawTargetSkiaWithGrContextAndFBO,
                AzRetainDrawTarget, AzReleaseDrawTarget, AzDrawTargetGetSize, AzDrawTargetFlush,
                AzDrawTargetClearRect, AzDrawTargetCopySurface, AzDrawTargetFillRect, AzDrawTargetStrokeRect, AzDrawTargetStrokeLine,
                AzDrawTargetFill, AzDrawTargetStroke, AzDrawTargetPushClip, AzDrawTargetPopClip, AzDrawTargetFillGlyphs,
                AzDrawTargetDrawSurface, AzDrawTargetGetSnapshot, AzDrawTargetCreateSourceSurfaceFromData, AzReleaseSourceSurface,
                AzSourceSurfaceGetSize, AzSourceSurfaceGetFormat, AzSourceSurfaceGetDataSurface, AzDataSourceSurfaceGetData,
                AzDataSourceSurfaceGetStride, AzCreateScaledFontForNativeFont, AzReleaseScaledFont, AzDrawTargetSetTransform,
                AzCreateFontOptionsForName, AzDestroyFontOptions, AzCreatePathBuilder, AzPathCopyToBuilder, AzPathContainsPoint,
                AzReleasePathBuilder, AzPathBuilderMoveTo, AzPathBuilderLineTo, AzPathBuilderFinish, AzReleasePath};

pub mod azure_hl;

#[cfg(target_os = "linux")]
pub mod test;

pub mod linkhack;

pub mod azure;
<|endoftext|>


<commit_before>extern crate libc;
use std::ffi::CString;

#[allow(dead_code,
        non_snake_case,
        non_camel_case_types,
        non_upper_case_globals)]
pub mod libpq;

// Implementation of initialization and callbacks.

pub unsafe extern fn init(cb: *mut libpq::OutputPluginCallbacks) {
    (*cb).startup_cb = Some(startup);
    (*cb).begin_cb = Some(begin);
    (*cb).change_cb = Some(change);
    (*cb).commit_cb = Some(commit);
    (*cb).shutdown_cb = Some(shutdown);
}

#[allow(unused_variables)]
extern fn startup(ctx: *mut libpq::Struct_LogicalDecodingContext,
                  options: *mut libpq::OutputPluginOptions,
                  is_init: libpq::_bool) {
    unsafe {
        (*options).output_type = libpq::OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
    }
}

#[allow(unused_variables)]
extern fn begin(ctx: *mut libpq::Struct_LogicalDecodingContext,
                txn: *mut libpq::ReorderBufferTXN) {
    unsafe {
        let is_last = 1;                                  // True in C language
        let s = CString::new("{ \"begin\": %u }").unwrap();
        libpq::OutputPluginPrepareWrite(ctx, is_last);
        libpq::appendStringInfo((*ctx).out, s.as_ptr(), (*txn).xid);
        libpq::OutputPluginWrite(ctx, is_last);
    }
}

#[allow(unused_variables)]
extern fn change(ctx: *mut libpq::Struct_LogicalDecodingContext,
                 txn: *mut libpq::ReorderBufferTXN,
                 relation: libpq::Relation,
                 change: *mut libpq::ReorderBufferChange) {
    unsafe {
        let last = 1;                                     // True in C language
        libpq::OutputPluginPrepareWrite(ctx, last);
        append_change(relation, change, (*ctx).out);
        libpq::OutputPluginWrite(ctx, last);
    }
}

#[allow(unused_variables)]
extern fn commit(ctx: *mut libpq::Struct_LogicalDecodingContext,
                 txn: *mut libpq::ReorderBufferTXN,
                 lsn: libpq::XLogRecPtr) {
    unsafe {
        let last = 1;                                     // True in C language
        let s = CString::new("{ \"commit\": %u }").unwrap();
        libpq::OutputPluginPrepareWrite(ctx, last);
        libpq::appendStringInfo((*ctx).out, s.as_ptr(), (*txn).xid);
        libpq::OutputPluginWrite(ctx, last);
    }
}

#[allow(unused_variables)]
extern fn shutdown(ctx: *mut libpq::Struct_LogicalDecodingContext) {
  // Do nothing.
}

unsafe fn append_change(relation: libpq::Relation,
                        change: *mut libpq::ReorderBufferChange,
                        out: libpq::StringInfo) {
    let tuple_desc = (*relation).rd_att;
    let tuples = (*change).data.tp();
    let tuple_new = (*tuples).newtuple;
    let tuple_old = (*tuples).oldtuple;
    let token = match (*change).action {
        libpq::REORDER_BUFFER_CHANGE_INSERT => "insert",
        libpq::REORDER_BUFFER_CHANGE_UPDATE => "update",
        libpq::REORDER_BUFFER_CHANGE_DELETE => "delete",
        _ => panic!("Unrecognized change action!")
    };
    append("{ ", out);
    append("\"", out);
    append(token, out);
    append("\": ", out);
    append_tuple_buf_as_json(tuple_new, tuple_desc, out);
    if !tuple_old.is_null() {
        append(", \"@\": ", out);
        append_tuple_buf_as_json(tuple_old, tuple_desc, out);
    }
    append(" }", out);
}

unsafe fn append_tuple_buf_as_json(data: *mut libpq::ReorderBufferTupleBuf,
                                   desc: libpq::TupleDesc,
                                   out: libpq::StringInfo) {
    if !data.is_null() {
        let heap_tuple = &mut (*data).tuple;
        let datum = libpq::heap_copy_tuple_as_datum(heap_tuple, desc);
        let empty_oid: libpq::Oid = 0;
        let json = libpq::DirectFunctionCall1Coll(Some(row_to_json),
                                                  empty_oid,
                                                  datum);
        let json_output_function: libpq::Oid = 322;     // TODO: Dynamic lookup
        let text = libpq::OidOutputFunctionCall(json_output_function, json);
        libpq::appendStringInfoString(out, text);
    } else {
        append("{}", out);
    }
}

unsafe fn append<T: Into<Vec<u8>>>(t: T, out: libpq::StringInfo) {
    libpq::appendStringInfoString(out, CString::new(t).unwrap().as_ptr());
}

extern fn row_to_json(fcinfo: libpq::FunctionCallInfo) -> libpq::Datum {
    // We wrap the unsafe call to make it safe.
    unsafe {
        libpq::row_to_json(fcinfo)
    }
}

// Symbols Postgres needs to find.

#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern fn _PG_init() { }

#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern fn
    _PG_output_plugin_init(cb: *mut libpq::OutputPluginCallbacks) { init(cb); }
<commit_msg>Rely on text internals to render `json`<commit_after>extern crate libc;
use std::ffi::CString;

#[allow(dead_code,
        non_snake_case,
        non_camel_case_types,
        non_upper_case_globals)]
pub mod libpq;

// Implementation of initialization and callbacks.

pub unsafe extern fn init(cb: *mut libpq::OutputPluginCallbacks) {
    (*cb).startup_cb = Some(startup);
    (*cb).begin_cb = Some(begin);
    (*cb).change_cb = Some(change);
    (*cb).commit_cb = Some(commit);
    (*cb).shutdown_cb = Some(shutdown);
}

#[allow(unused_variables)]
extern fn startup(ctx: *mut libpq::Struct_LogicalDecodingContext,
                  options: *mut libpq::OutputPluginOptions,
                  is_init: libpq::_bool) {
    unsafe {
        (*options).output_type = libpq::OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
    }
}

#[allow(unused_variables)]
extern fn begin(ctx: *mut libpq::Struct_LogicalDecodingContext,
                txn: *mut libpq::ReorderBufferTXN) {
    unsafe {
        let is_last = 1;                                  // True in C language
        let s = CString::new("{ \"begin\": %u }").unwrap();
        libpq::OutputPluginPrepareWrite(ctx, is_last);
        libpq::appendStringInfo((*ctx).out, s.as_ptr(), (*txn).xid);
        libpq::OutputPluginWrite(ctx, is_last);
    }
}

#[allow(unused_variables)]
extern fn change(ctx: *mut libpq::Struct_LogicalDecodingContext,
                 txn: *mut libpq::ReorderBufferTXN,
                 relation: libpq::Relation,
                 change: *mut libpq::ReorderBufferChange) {
    unsafe {
        let last = 1;                                     // True in C language
        libpq::OutputPluginPrepareWrite(ctx, last);
        append_change(relation, change, (*ctx).out);
        libpq::OutputPluginWrite(ctx, last);
    }
}

#[allow(unused_variables)]
extern fn commit(ctx: *mut libpq::Struct_LogicalDecodingContext,
                 txn: *mut libpq::ReorderBufferTXN,
                 lsn: libpq::XLogRecPtr) {
    unsafe {
        let last = 1;                                     // True in C language
        let s = CString::new("{ \"commit\": %u }").unwrap();
        libpq::OutputPluginPrepareWrite(ctx, last);
        libpq::appendStringInfo((*ctx).out, s.as_ptr(), (*txn).xid);
        libpq::OutputPluginWrite(ctx, last);
    }
}

#[allow(unused_variables)]
extern fn shutdown(ctx: *mut libpq::Struct_LogicalDecodingContext) {
  // Do nothing.
}

unsafe fn append_change(relation: libpq::Relation,
                        change: *mut libpq::ReorderBufferChange,
                        out: libpq::StringInfo) {
    let tuple_desc = (*relation).rd_att;
    let tuples = (*change).data.tp();
    let tuple_new = (*tuples).newtuple;
    let tuple_old = (*tuples).oldtuple;
    let token = match (*change).action {
        libpq::REORDER_BUFFER_CHANGE_INSERT => "insert",
        libpq::REORDER_BUFFER_CHANGE_UPDATE => "update",
        libpq::REORDER_BUFFER_CHANGE_DELETE => "delete",
        _ => panic!("Unrecognized change action!")
    };
    append("{ ", out);
    append("\"", out);
    append(token, out);
    append("\": ", out);
    append_tuple_buf_as_json(tuple_new, tuple_desc, out);
    if !tuple_old.is_null() {
        append(", \"@\": ", out);
        append_tuple_buf_as_json(tuple_old, tuple_desc, out);
    }
    append(" }", out);
}

unsafe fn append_tuple_buf_as_json(data: *mut libpq::ReorderBufferTupleBuf,
                                   desc: libpq::TupleDesc,
                                   out: libpq::StringInfo) {
    if !data.is_null() {
        let heap_tuple = &mut (*data).tuple;
        let datum = libpq::heap_copy_tuple_as_datum(heap_tuple, desc);
        let empty_oid: libpq::Oid = 0;
        let json = libpq::DirectFunctionCall1Coll(Some(row_to_json),
                                                  empty_oid,
                                                  datum);
        let ptr = json as *const libpq::Struct_varlena;
        let text = libpq::text_to_cstring(ptr);
        libpq::appendStringInfoString(out, text);
    } else {
        append("{}", out);
    }
}

unsafe fn append<T: Into<Vec<u8>>>(t: T, out: libpq::StringInfo) {
    libpq::appendStringInfoString(out, CString::new(t).unwrap().as_ptr());
}

extern fn row_to_json(fcinfo: libpq::FunctionCallInfo) -> libpq::Datum {
    // We wrap the unsafe call to make it safe.
    unsafe {
        libpq::row_to_json(fcinfo)
    }
}

// Symbols Postgres needs to find.

#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern fn _PG_init() { }

#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern fn
    _PG_output_plugin_init(cb: *mut libpq::OutputPluginCallbacks) { init(cb); }
<|endoftext|>


<commit_before>//! A undo/redo library.
//!
//! It uses the [Command Pattern](https://en.wikipedia.org/wiki/Command_pattern) where the user
//! implements the `UndoCmd` trait for each command and then the commands can be used with the
//! `UndoStack`.
//!
//! The `UndoStack` has two different states, the clean state and the dirty state. The `UndoStack`
//! is in a clean state when there are no more commands that can be redone, otherwise it's in a dirty
//! state.
//!
//! # Example
//! ```
//! use std::rc::Rc;
//! use std::cell::RefCell;
//! use undo::{UndoCmd, UndoStack};
//!
//! /// Pops an element from a vector.
//! #[derive(Clone)]
//! struct PopCmd {
//!     vec: Rc<RefCell<Vec<i32>>>,
//!     e: Option<i32>,
//! }
//!
//! impl UndoCmd for PopCmd {
//!     fn redo(&mut self) {
//!         self.e = self.vec.borrow_mut().pop();
//!     }
//!
//!     fn undo(&mut self) {
//!         self.vec.borrow_mut().push(self.e.unwrap());
//!         self.e = None;
//!     }
//! }
//!
//! // We need to use Rc<RefCell> since all commands are going to mutate the vec.
//! let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
//! let mut undo_stack = UndoStack::new()
//!     .on_clean(|| println!("This is called when the stack changes from dirty to clean!"))
//!     .on_dirty(|| println!("This is called when the stack changes from clean to dirty!"));
//!
//! let cmd = PopCmd { vec: vec.clone(), e: None };
//! undo_stack.push(cmd.clone());
//! undo_stack.push(cmd.clone());
//! undo_stack.push(cmd.clone());
//!
//! assert_eq!(vec.borrow().len(), 7);
//!
//! undo_stack.undo(); // on_dirty is going to be called here.
//! undo_stack.undo();
//! undo_stack.undo();
//!
//! assert_eq!(vec.borrow().len(), 10);
//! ```

/// Every command needs to implement the `UndoCmd` trait to be able to be used with the `UndoStack`.
pub trait UndoCmd {
    /// Executes the desired command.
    fn redo(&mut self);
    /// Restores the state as it was before `redo` was called.
    fn undo(&mut self);
}

/// `UndoStack` maintains a stack of `UndoCmd`s that can be undone and redone by using methods
/// on the `UndoStack`.
///
/// `UndoStack` will notice when it's state changes to either dirty or clean, and the user can
/// set methods that should be called for either state change. This is useful for example if
/// you want to automatically enable or disable undo or redo buttons based on there are any
/// more actions that can be undone or redone.
///
/// Note: An empty `UndoStack` is clean, so the first push will not trigger the clean method.
pub struct UndoStack<'a, T: UndoCmd> {
    stack: Vec<T>,
    len: usize,
    on_clean: Option<Box<FnMut() + 'a>>,
    on_dirty: Option<Box<FnMut() + 'a>>,
}

impl<'a, T: UndoCmd> UndoStack<'a, T> {
    /// Creates a new `UndoStack`.
    pub fn new() -> Self {
        UndoStack {
            stack: Vec::new(),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Creates a new `UndoStack` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        UndoStack {
            stack: Vec::with_capacity(capacity),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Sets what should happen if the state changes from dirty to clean.
    /// By default the `UndoStack` does nothing when the state changes.
    /// Consumes the `UndoStack` so this method should be called when creating the `UndoStack`.
    pub fn on_clean<F: FnMut() + 'a>(mut self, f: F) -> Self {
        self.on_clean = Some(Box::new(f));
        self
    }

    /// Sets what should happen if the state changes from clean to dirty.
    /// By default the `UndoStack` does nothing when the state changes.
    /// Consumes the `UndoStack` so this method should be called when creating the `UndoStack`.
    pub fn on_dirty<F: FnMut() + 'a>(mut self, f: F) -> Self {
        self.on_dirty = Some(Box::new(f));
        self
    }

    /// Returns true if the state of `UndoStack` is clean.
    pub fn is_clean(&self) -> bool {
        self.len == self.stack.len()
    }

    /// Returns true if the state of `UndoStack` is dirty.
    pub fn is_dirty(&self) -> bool {
        !self.is_clean()
    }

    /// Pushes a `UndoCmd` to the top of the `UndoStack` and executes its `redo()` method.
    /// This pops off all `UndoCmd`s that is above the active `UndoCmd` from the `UndoStack`.
    pub fn push(&mut self, mut cmd: T) {
        let is_dirty = self.is_dirty();
        // Pop off all elements after len from stack.
        self.stack.truncate(self.len);
        cmd.redo();
        self.stack.push(cmd);
        self.len = self.stack.len();
        // State is always clean after a push, check if it was dirty before.
        if is_dirty {
            if let Some(ref mut f) = self.on_clean {
                f();
            }
        }
    }

    /// Calls the `redo()` method for the active `UndoCmd` and sets the next `UndoCmd` as the new
    /// active `UndoCmd`.
    pub fn redo(&mut self) {
        if self.len < self.stack.len() {
            let is_dirty = self.is_dirty();
            {
                let ref mut cmd = self.stack[self.len];
                cmd.redo();
            }
            self.len += 1;
            // Check if stack went from dirty to clean.
            if is_dirty == self.is_clean() {
                if let Some(ref mut f) = self.on_clean {
                    f();
                }
            }
        }
    }

    /// Calls the `undo()` method for the active `UndoCmd` and sets the previous `UndoCmd` as the
    /// new active `UndoCmd`.
    pub fn undo(&mut self) {
        if self.len != 0 {
            let is_clean = self.is_clean();
            self.len -= 1;
            {
                let ref mut cmd = self.stack[self.len];
                cmd.undo();
            }
            // Check if stack went from clean to dirty.
            if is_clean == self.is_dirty() {
                if let Some(ref mut f) = self.on_dirty {
                    f();
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use {UndoStack, UndoCmd};

    #[test]
    fn pop() {
        use std::rc::Rc;
        use std::cell::{Cell, RefCell};

        /// Pops an element from a vector.
        #[derive(Clone)]
        struct PopCmd {
            vec: Rc<RefCell<Vec<i32>>>,
            e: Option<i32>,
        }

        impl UndoCmd for PopCmd {
            fn redo(&mut self) {
                self.e = self.vec.borrow_mut().pop();
            }

            fn undo(&mut self) {
                self.vec.borrow_mut().push(self.e.unwrap());
                self.e = None;
            }
        }

        let a = Cell::new(0);
        let b = Cell::new(0);
        // We need to use Rc<RefCell> since all commands are going to mutate the vec.
        let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
        let mut undo_stack = UndoStack::with_capacity(3)
            .on_clean(|| a.set(1))
            .on_dirty(|| b.set(1));

        let cmd = PopCmd { vec: vec.clone(), e: None };
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());

        assert!(vec.borrow().is_empty());

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));

        assert_eq!(a.get(), 0);
        undo_stack.push(cmd.clone());
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8])));

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));

        assert_eq!(a.get(), 0);
        undo_stack.redo();
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8])));
    }
}
<commit_msg>Change the state tests to use && instead of ==<commit_after>//! A undo/redo library.
//!
//! It uses the [Command Pattern](https://en.wikipedia.org/wiki/Command_pattern) where the user
//! implements the `UndoCmd` trait for each command and then the commands can be used with the
//! `UndoStack`.
//!
//! The `UndoStack` has two different states, the clean state and the dirty state. The `UndoStack`
//! is in a clean state when there are no more commands that can be redone, otherwise it's in a dirty
//! state.
//!
//! # Example
//! ```
//! use std::rc::Rc;
//! use std::cell::RefCell;
//! use undo::{UndoCmd, UndoStack};
//!
//! /// Pops an element from a vector.
//! #[derive(Clone)]
//! struct PopCmd {
//!     vec: Rc<RefCell<Vec<i32>>>,
//!     e: Option<i32>,
//! }
//!
//! impl UndoCmd for PopCmd {
//!     fn redo(&mut self) {
//!         self.e = self.vec.borrow_mut().pop();
//!     }
//!
//!     fn undo(&mut self) {
//!         self.vec.borrow_mut().push(self.e.unwrap());
//!         self.e = None;
//!     }
//! }
//!
//! // We need to use Rc<RefCell> since all commands are going to mutate the vec.
//! let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
//! let mut undo_stack = UndoStack::new()
//!     .on_clean(|| println!("This is called when the stack changes from dirty to clean!"))
//!     .on_dirty(|| println!("This is called when the stack changes from clean to dirty!"));
//!
//! let cmd = PopCmd { vec: vec.clone(), e: None };
//! undo_stack.push(cmd.clone());
//! undo_stack.push(cmd.clone());
//! undo_stack.push(cmd.clone());
//!
//! assert_eq!(vec.borrow().len(), 7);
//!
//! undo_stack.undo(); // on_dirty is going to be called here.
//! undo_stack.undo();
//! undo_stack.undo();
//!
//! assert_eq!(vec.borrow().len(), 10);
//! ```

/// Every command needs to implement the `UndoCmd` trait to be able to be used with the `UndoStack`.
pub trait UndoCmd {
    /// Executes the desired command.
    fn redo(&mut self);
    /// Restores the state as it was before `redo` was called.
    fn undo(&mut self);
}

/// `UndoStack` maintains a stack of `UndoCmd`s that can be undone and redone by using methods
/// on the `UndoStack`.
///
/// `UndoStack` will notice when it's state changes to either dirty or clean, and the user can
/// set methods that should be called for either state change. This is useful for example if
/// you want to automatically enable or disable undo or redo buttons based on there are any
/// more actions that can be undone or redone.
///
/// Note: An empty `UndoStack` is clean, so the first push will not trigger the `on_clean` method.
pub struct UndoStack<'a, T: UndoCmd> {
    stack: Vec<T>,
    len: usize,
    on_clean: Option<Box<FnMut() + 'a>>,
    on_dirty: Option<Box<FnMut() + 'a>>,
}

impl<'a, T: UndoCmd> UndoStack<'a, T> {
    /// Creates a new `UndoStack`.
    pub fn new() -> Self {
        UndoStack {
            stack: Vec::new(),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Creates a new `UndoStack` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        UndoStack {
            stack: Vec::with_capacity(capacity),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Sets what should happen if the state changes from dirty to clean.
    /// By default the `UndoStack` does nothing when the state changes.
    /// Consumes the `UndoStack` so this method should be called when creating the `UndoStack`.
    pub fn on_clean<F: FnMut() + 'a>(mut self, f: F) -> Self {
        self.on_clean = Some(Box::new(f));
        self
    }

    /// Sets what should happen if the state changes from clean to dirty.
    /// By default the `UndoStack` does nothing when the state changes.
    /// Consumes the `UndoStack` so this method should be called when creating the `UndoStack`.
    pub fn on_dirty<F: FnMut() + 'a>(mut self, f: F) -> Self {
        self.on_dirty = Some(Box::new(f));
        self
    }

    /// Returns true if the state of `UndoStack` is clean.
    pub fn is_clean(&self) -> bool {
        self.len == self.stack.len()
    }

    /// Returns true if the state of `UndoStack` is dirty.
    pub fn is_dirty(&self) -> bool {
        !self.is_clean()
    }

    /// Pushes a `UndoCmd` to the top of the `UndoStack` and executes its `redo()` method.
    /// This pops off all `UndoCmd`s that is above the active `UndoCmd` from the `UndoStack`.
    pub fn push(&mut self, mut cmd: T) {
        let is_dirty = self.is_dirty();
        // Pop off all elements after len from stack.
        self.stack.truncate(self.len);
        cmd.redo();
        self.stack.push(cmd);
        self.len = self.stack.len();
        // State is always clean after a push, check if it was dirty before.
        if is_dirty {
            if let Some(ref mut f) = self.on_clean {
                f();
            }
        }
    }

    /// Calls the `redo` method for the active `UndoCmd` and sets the next `UndoCmd` as the new
    /// active `UndoCmd`. Calling this method when the state is clean does nothing.
    pub fn redo(&mut self) {
        if self.len < self.stack.len() {
            let is_dirty = self.is_dirty();
            {
                let ref mut cmd = self.stack[self.len];
                cmd.redo();
            }
            self.len += 1;
            // Check if stack went from dirty to clean.
            if is_dirty && self.is_clean() {
                if let Some(ref mut f) = self.on_clean {
                    f();
                }
            }
        }
    }

    /// Calls the `undo` method for the active `UndoCmd` and sets the previous `UndoCmd` as the
    /// new active `UndoCmd`.
    pub fn undo(&mut self) {
        if self.len != 0 {
            let is_clean = self.is_clean();
            self.len -= 1;
            {
                let ref mut cmd = self.stack[self.len];
                cmd.undo();
            }
            // Check if stack went from clean to dirty.
            if is_clean && self.is_dirty() {
                if let Some(ref mut f) = self.on_dirty {
                    f();
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use {UndoStack, UndoCmd};

    #[test]
    fn pop() {
        use std::rc::Rc;
        use std::cell::{Cell, RefCell};

        /// Pops an element from a vector.
        #[derive(Clone)]
        struct PopCmd {
            vec: Rc<RefCell<Vec<i32>>>,
            e: Option<i32>,
        }

        impl UndoCmd for PopCmd {
            fn redo(&mut self) {
                self.e = self.vec.borrow_mut().pop();
            }

            fn undo(&mut self) {
                self.vec.borrow_mut().push(self.e.unwrap());
                self.e = None;
            }
        }

        let a = Cell::new(0);
        let b = Cell::new(0);
        // We need to use Rc<RefCell> since all commands are going to mutate the vec.
        let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
        let mut undo_stack = UndoStack::with_capacity(3)
            .on_clean(|| a.set(1))
            .on_dirty(|| b.set(1));

        let cmd = PopCmd { vec: vec.clone(), e: None };
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());

        assert!(vec.borrow().is_empty());

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));

        assert_eq!(a.get(), 0);
        undo_stack.push(cmd.clone());
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8])));

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));

        assert_eq!(a.get(), 0);
        undo_stack.redo();
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8])));
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Jan Likar.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub mod ops {
    use std::env;
    use std::fs;
    use std::path::{Path, PathBuf};

    use cargo::core::dependency::Dependency;
    use cargo::core::source::{Source, SourceId};
    use cargo::core::Package;
    use cargo::sources::{GitSource, PathSource, SourceConfigMap};
    use cargo::util::to_semver::ToSemver;
    use cargo::util::{CargoResult, Config};

    use failure::bail;

    use walkdir::WalkDir;

    pub fn clone(
        krate: Option<&str>,
        srcid: &SourceId,
        prefix: Option<&str>,
        vers: Option<&str>,
        config: &Config,
    ) -> CargoResult<()> {
        let _lock = config.acquire_package_cache_lock()?;

        let map = SourceConfigMap::new(config)?;
        let pkg = if srcid.is_path() {
            let path = srcid.url().to_file_path().ok().expect("path must be valid");
            let mut src = PathSource::new(&path, srcid.clone(), config);
            src.update()?;

            select_pkg(config, src, krate, vers, &mut |path| path.read_packages())?
        } else if srcid.is_git() {
            select_pkg(
                config,
                GitSource::new(srcid.clone(), config)?,
                krate,
                vers,
                &mut |git| git.read_packages(),
            )?
        } else {
            select_pkg(
                config,
                map.load(srcid.clone(), &Default::default())?,
                krate,
                vers,
                &mut |_| {
                    bail!(
                        "must specify a crate to clone from \
                         crates.io, or use --path or --git to \
                         specify alternate source"
                    )
                },
            )?
        };

        // If prefix was not supplied, clone into current dir
        let mut dest_path = match prefix {
            Some(path) => PathBuf::from(path),
            None => env::current_dir()?,
        };

        dest_path.push(format!("{}", pkg.name()));

        clone_directory(&pkg.root(), &dest_path)?;

        Ok(())
    }

    fn select_pkg<'a, T>(
        config: &Config,
        mut src: T,
        name: Option<&str>,
        vers: Option<&str>,
        list_all: &mut dyn FnMut(&mut T) -> CargoResult<Vec<Package>>,
    ) -> CargoResult<Package>
    where
        T: Source + 'a,
    {
        src.update()?;

        match name {
            Some(name) => {
                let vers = match vers {
                    Some(v) => match v.to_semver() {
                        Ok(v) => Some(v.to_string()),
                        Err(e) => bail!("{}", e),
                    },
                    None => None,
                };
                let vers = vers.as_ref().map(|s| &**s);
                let dep = Dependency::parse_no_deprecated(name, vers, src.source_id())?;
                let mut summaries = vec![];
                src.query(&dep, &mut |summary| summaries.push(summary.clone()))?;

                let latest = summaries.iter().max_by_key(|s| s.version());

                match latest {
                    Some(l) => {
                        let pkg = Box::new(src).download_now(l.package_id(), config)?;
                        Ok(pkg)
                    }
                    None => bail!("package '{}' not found", name),
                }
            }
            None => {
                let candidates = list_all(&mut src)?;
                Ok(candidates[0].clone())
            }
        }
    }

    fn clone_directory(from: &Path, to: &Path) -> CargoResult<()> {
        for entry in WalkDir::new(from) {
            let entry = entry.unwrap();
            let file_type = entry.file_type();
            let mut to = to.to_owned();
            to.push(entry.path().strip_prefix(from).unwrap());

            if file_type.is_file() && entry.file_name() != ".cargo-ok" {
                // .cargo-ok is not wanted in this context
                fs::copy(&entry.path(), &to)?;
            } else if file_type.is_dir() {
                fs::create_dir(&to)?;
            }
        }

        Ok(())
    }
}
<commit_msg>Fix destination path creation.<commit_after>// Copyright 2015 Jan Likar.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub mod ops {
    use std::env;
    use std::fs;
    use std::path::{Path, PathBuf};

    use cargo::core::dependency::Dependency;
    use cargo::core::source::{Source, SourceId};
    use cargo::core::Package;
    use cargo::sources::{GitSource, PathSource, SourceConfigMap};
    use cargo::util::to_semver::ToSemver;
    use cargo::util::{CargoResult, Config};

    use failure::bail;

    use walkdir::WalkDir;

    pub fn clone(
        krate: Option<&str>,
        srcid: &SourceId,
        prefix: Option<&str>,
        vers: Option<&str>,
        config: &Config,
    ) -> CargoResult<()> {
        let _lock = config.acquire_package_cache_lock()?;

        let map = SourceConfigMap::new(config)?;
        let pkg = if srcid.is_path() {
            let path = srcid.url().to_file_path().ok().expect("path must be valid");
            let mut src = PathSource::new(&path, srcid.clone(), config);
            src.update()?;

            select_pkg(config, src, krate, vers, &mut |path| path.read_packages())?
        } else if srcid.is_git() {
            select_pkg(
                config,
                GitSource::new(srcid.clone(), config)?,
                krate,
                vers,
                &mut |git| git.read_packages(),
            )?
        } else {
            select_pkg(
                config,
                map.load(srcid.clone(), &Default::default())?,
                krate,
                vers,
                &mut |_| {
                    bail!(
                        "must specify a crate to clone from \
                         crates.io, or use --path or --git to \
                         specify alternate source"
                    )
                },
            )?
        };

        // If prefix was not supplied, clone into current dir
        let dest_path = match prefix {
            Some(path) => PathBuf::from(path),
            None => {
            	let mut dest = env::current_dir()?;
            	dest.push(format!("{}", pkg.name()));
            	dest
            },
        };

        // Cloning into an existing directory is only allowed if the directory is empty.
        if !dest_path.exists() {
        	fs::create_dir_all(&dest_path)?;
        } else {
        	let is_empty = dest_path.read_dir()?.next().is_none();
        	if !is_empty {
        		bail!("destination path '{}' already exists and is not an empty directory.", dest_path.display());
        	}
        }

        clone_directory(&pkg.root(), &dest_path)?;

        Ok(())
    }

    fn select_pkg<'a, T>(
        config: &Config,
        mut src: T,
        name: Option<&str>,
        vers: Option<&str>,
        list_all: &mut dyn FnMut(&mut T) -> CargoResult<Vec<Package>>,
    ) -> CargoResult<Package>
    where
        T: Source + 'a,
    {
        src.update()?;

        match name {
            Some(name) => {
                let vers = match vers {
                    Some(v) => match v.to_semver() {
                        Ok(v) => Some(v.to_string()),
                        Err(e) => bail!("{}", e),
                    },
                    None => None,
                };
                let vers = vers.as_ref().map(|s| &**s);
                let dep = Dependency::parse_no_deprecated(name, vers, src.source_id())?;
                let mut summaries = vec![];
                src.query(&dep, &mut |summary| summaries.push(summary.clone()))?;

                let latest = summaries.iter().max_by_key(|s| s.version());

                match latest {
                    Some(l) => {
                        let pkg = Box::new(src).download_now(l.package_id(), config)?;
                        Ok(pkg)
                    }
                    None => bail!("package '{}' not found", name),
                }
            }
            None => {
                let candidates = list_all(&mut src)?;
                Ok(candidates[0].clone())
            }
        }
    }

    fn clone_directory(from: &Path, to: &Path) -> CargoResult<()> {
        for entry in WalkDir::new(from) {
            let entry = entry.unwrap();
            let file_type = entry.file_type();
            let mut to = to.to_owned();
            to.push(entry.path().strip_prefix(from).unwrap());

            if file_type.is_file() && entry.file_name() != ".cargo-ok" {
                // .cargo-ok is not wanted in this context
                fs::copy(&entry.path(), &to)?;
            } else if file_type.is_dir() {
                fs::create_dir(&to)?;
            }
        }

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


<commit_before>#![feature(custom_derive, plugin, proc_macro)]
#![cfg_attr(test, feature(test))]
#[cfg(test)]
extern crate test;

#[macro_use] extern crate nom;
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate serde_derive;
extern crate mio;
extern crate bytes;
extern crate time;
extern crate serde;
extern crate serde_json;
extern crate rand;
extern crate openssl;
extern crate pool;
extern crate uuid;
extern crate net2;
extern crate libc;
extern crate slab;

pub mod network;
pub mod parser;
pub mod messages;
<commit_msg>Add some top level documentation<commit_after>//! This library provides tools to build a HTTP proxy
//!
//! It handles network polling, HTTP parsing, TLS in a fast single threaded event
//! loop.
//!
//! It is designed to receive configuration changes at runtime instead of
//! reloading from a file regularly. The event loop runs in its own thread
//! and receives commands through a message queue.
//!
//! To create a HTTP proxy, you first need to create a `HttpProxyConfiguration`
//! structure (there are configuration structures for the HTTPS and TCP proxies
//! too).
//!
//! ```ignore
//! let config = messages::HttpProxyConfiguration {
//!   front: "198.51.100.0:80".parse().unwrap(),
//!   ..Default::default()
//! };
//! ```
//!
//! Then create the required elements to communicate with the proxy thread,
//! and launch the thread:
//!
//! ```ignore
//! let config = messages::HttpProxyConfiguration {
//!   front: "198.51.100.0:80".parse().unwrap(),
//!   ..Default::default()
//! };
//!
//! let poll          = mio::Poll::new().unwrap();
//! let (tx, rx)      = mio::channel::channel::<ProxyOrder>();
//! let (sender, rec) = mpsc::channel::<network::ServerMessage>();
//!
//! let jg            = thread::spawn(move || {
//!   network::http::start_listener(config, sender, poll, rx);
//! });
//! ```
//!
//! The `tx, rx` channel here is a mio channel through which the proxy will
//! receive its orders, and it will use the `(sender,rec)` one to send
//! acknowledgements and various data.
//!
//! Once the thread is launched, the proxy will start its event loop and handle
//! events on the listening interface and port specified in the configuration
//! object. Since no applications to proxy for were specified, it will receive
//! the connections, parse the request, then send a default (but configurable)
//! answer.
//!
//! ```ignore
//! let http_front = messages::HttpFront {
//!   app_id:     String::from("test"),
//!   hostname:   String::from("example.com"),
//!   path_begin: String::from("/")
//! };
//! let http_instance = messages::Instance {
//!   app_id:     String::from("test"),
//!   ip_address: String::from("192.0.2.1"),
//!   port:       8080
//! };
//!
//! tx.send(network::ProxyOrder::Command(
//!   String::from("ID_ABCD"),
//!   messages::Command::AddHttpFront(http_front)
//! ));
//!
//! tx.send(network::ProxyOrder::Command(
//!   String::from("ID_EFGH"),
//!   messages::Command::AddInstance(http_instance)
//! ));
//!
//! println!("HTTP -> {:?}", rec.recv().unwrap());
//! println!("HTTP -> {:?}", rec.recv().unwrap());
//! ```
//!
//! An application is identified by its `app_id`, a string that will be shared
//! between one or multiple "fronts", and one or multiple "instances".
//!
//! A "front" is a way to recognize a request and match it to an `app_id`,
//! depending on the hostname and the beginning of the URL path.
//!
//! An instance corresponds to one backend server, indicated by its IP and port.
//!
//! An application can have multiple backend servers, and they can be added or
//! removed while the proxy is running. If a backend is removed from the configuration
//! while the proxy is handling a request to that server, it will finish that
//! request and stop sending new traffic to that server.
//!
//! The fronts and instances are specified with messages sent through the
//! communication channels with the proxy event loop. Once the configuration
//! options are added to the proxy's state, it will send back an acknowledgement
//! message.
//!
//! Here is the comple example for reference:
//!
//! ```ignore
//! #![allow(unused_variables,unused_must_use)]
//! #[macro_use] extern crate log;
//! extern crate env_logger;
//! extern crate yxorp;
//! extern crate openssl;
//! extern crate mio;
//!
//! use std::thread;
//! use std::sync::mpsc;
//! use yxorp::messages;
//! use yxorp::network::{self,ProxyOrder};

//! fn main() {
//!   env_logger::init().unwrap();
//!   info!("starting up");
//!
//!   let config = messages::HttpProxyConfiguration {
//!     front: "198.51.100.0:80".parse().unwrap(),
//!     ..Default::default()
//!   };
//!
//!   let poll          = mio::Poll::new().unwrap();
//!   let (tx, rx)      = mio::channel::channel::<ProxyOrder>();
//!   let (sender, rec) = mpsc::channel::<network::ServerMessage>();
//!
//!   let jg            = thread::spawn(move || {
//!     network::http::start_listener(config, sender, poll, rx);
//!   });
//!
//!   let http_front = messages::HttpFront {
//!     app_id:     String::from("test"),
//!     hostname:   String::from("example.com"),
//!     path_begin: String::from("/")
//!   };
//!   let http_instance = messages::Instance {
//!     app_id:     String::from("test"),
//!     ip_address: String::from("192.0.2.1"),
//!     port:       8080
//!   };
//!
//!   tx.send(network::ProxyOrder::Command(
//!     String::from("ID_ABCD"),
//!     messages::Command::AddHttpFront(http_front)
//!   ));
//!
//!   tx.send(network::ProxyOrder::Command(
//!     String::from("ID_EFGH"),
//!     messages::Command::AddInstance(http_instance)
//!   ));
//!
//!   println!("HTTP -> {:?}", rec.recv().unwrap());
//!   println!("HTTP -> {:?}", rec.recv().unwrap());
//!
//!   let _ = jg.join();
//!   info!("good bye");
//! }
//! ```
//!
#![feature(custom_derive, plugin, proc_macro)]
#![cfg_attr(test, feature(test))]
#[cfg(test)]
extern crate test;

#[macro_use] extern crate nom;
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate serde_derive;
extern crate mio;
extern crate bytes;
extern crate time;
extern crate serde;
extern crate serde_json;
extern crate rand;
extern crate openssl;
extern crate pool;
extern crate uuid;
extern crate net2;
extern crate libc;
extern crate slab;

pub mod network;
pub mod parser;
pub mod messages;
<|endoftext|>


<commit_before>#![crate_name = "hvif_rs"]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

//! This is documentation for the hvif_parser

/// Test function
pub fn main() {
    println!("Hello world!")
}

#[cfg(test)]
mod tests {
    use main;
    #[test]
    fn it_works() {
        main()
    }
}
<commit_msg>Added HVIF Types<commit_after>#![crate_name = "hvif_rs"]
#![allow(dead_code)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

//! This is documentation for the hvif_rs module
//!
//! This module provides facilities for reading or writing Haiku Vector Icon Format images

use std::collections::VecDeque;
use std::io::{Bytes, Read, Result};

/// Read an image from bytes
fn read_from_bytes<R: Read>(readable: R) -> Result<HVIFImage> {
  //let bytes: Bytes<R> = readable.bytes();
  unimplemented!()
}

/// Types
struct HVIFImage {
  styles: VecDeque<HVIFStyle>,
  paths: VecDeque<HVIFPath>,
  shapes: VecDeque<HVIFShape>
}

/// Style types
enum HVIFStyle {
  SolidColor { alpha: u8, red: u8, green: u8, blue: u8 },
  Gradient { gradient: HVIFGradient },
  SolidColorNoAlpha,
  SolidGray,
  SolidGrayNoAlpha
}

struct HVIFGradient {
  gradient_type: HVIFGradientType,
  flags: u8,
  colors: VecDeque<HVIFGradientColor>
}

enum HVIFGradientType {
  Linear,
  Circular,
  Diamond,
  Conic,
  XY,
  SqrtXY
}

enum GradientFlags {
  Transform       = 0b0000_0001,
  NoAlpha         = 0b0000_0010,
  Colors16Bit     = 0b0000_0100,
  Grays           = 0b0000_1000,
}

struct HVIFGradientColor {
  stop_offset: u8,
  alpha: u8,
  red: u8,
  green: u8,
  blue: u8
}

/// Path types
struct HVIFPath {
  flags: u8,
  points: VecDeque<HVIFPointCommand>
}

enum HVIFPathFlags {
  Closed       = 0b0000_0001,
  UsesCommands = 0b0000_0010,
  NoCurves     = 0b0000_0100,
}

enum HVIFPointCommand {
  HLine { y_coord: f32 },
  VLine { x_coord: f32 },
  Line  { point: HVIFPoint },
  Curve { point_in: HVIFPoint, point: HVIFPoint, point_out: HVIFPoint}, // Cubic curve
}

struct HVIFPoint { x: f32, y: f32 }

/// Shape types
struct HVIFShape {
  style_index: u8,
  path_indices: VecDeque<u8>,
  flags: u8,
  transform: Option<HVIFMatrix>,
  translate: Option<HVIFPoint>,
  lod_scale: Option<HVIFLODScale>,
  transformer_list: VecDeque<HVIFTransformer>
}

enum HVIFShapeFlags {
  Transform       = 0b0000_0001,
  Hinting         = 0b0000_0010,
  LODScale        = 0b0000_0100,
  HasTransformers = 0b0000_1000,
  Translation     = 0b0001_0000,
}

struct HVIFMatrix {
  x1: HVIFf24, y1: HVIFf24, z1: HVIFf24,
  x2: HVIFf24, y2: HVIFf24, z2: HVIFf24,
}
struct HVIFf24 { fst: u8, snd: u8, thr: u8 }

struct HVIFLODScale { min: f32, max: f32 }

enum HVIFTransformer {
  Affine { matrix: HVIFMatrix },
  Contour { width: f32, line_join: u8, miter_limit: u8 },
  Perspective,
  Stroke { width: f32, line_join: u8, line_cap: u8, miter_limit: u8 }
}

/// Test function
fn empty_image() -> HVIFImage {
  HVIFImage {
    styles: VecDeque::new(),
    paths:  VecDeque::new(),
    shapes: VecDeque::new()
  }
}

#[cfg(test)]
mod tests {
    use empty_image;
    #[test]
    fn it_works() {
        empty_image();
    }
}
<|endoftext|>


<commit_before>//! Implementation of MurmurHash2 (64bit version)
//!
//! Based on the implementation for Redis
//! ([antirez/redis src/hyperloglog.c](https://github.com/antirez/redis/blob/93eed9ae0163e328c33b16ab9ea3c4fbe0f98674/src/hyperloglog.c#L390-L439))
//!
//! More info and different implementations available at:
//! <https://sites.google.com/site/murmurhash/>
//!
//! # Basic Example
//!
//! ```rust
//! # use murmurhash64::murmur_hash64a;
//! let key = "Pizza & Mandolino";
//! let seed = 2915580697;
//!
//! let hash = murmur_hash64a(key.as_bytes(), seed);
//! ```

#![feature(default_type_params)]

#![experimental]

pub use murmurhash64::murmur_hash64a;
pub use hasher::MurmurState;
pub use hasher::MurmurHasher;

mod hasher;

mod murmurhash64 {
    /// Hash the given key and the given seed.
    ///
    /// Returns the resulting 64bit hash.
    ///
    /// Example:
    ///
    /// ```rust
    /// # use murmurhash64::murmur_hash64a;
    /// let key = "Pizza & Mandolino";
    /// let seed = 2915580697;
    ///
    /// let hash = murmur_hash64a(key.as_bytes(), seed);
    /// ```
    pub fn murmur_hash64a(key: &[u8], seed: u64) -> u64 {
        let m : u64 = 0xc6a4a7935bd1e995;
        let r : uint = 47;

        let len = key.len();
        let mut h : u64 = seed ^ (len as u64 * m);

        let endpos = len-(len&7);
        let mut i = 0u;
        while i != endpos {
            let mut k : u64;

            k  = key[i+0] as u64;
            k |= (key[i+1] as u64) << 8;
            k |= (key[i+2] as u64) << 16;
            k |= (key[i+3] as u64) << 24;
            k |= (key[i+4] as u64) << 32;
            k |= (key[i+5] as u64) << 40;
            k |= (key[i+6] as u64) << 48;
            k |= (key[i+7] as u64) << 56;

            k *= m;
            k ^= k >> r;
            k *= m;
            h ^= k;
            h *= m;

            i += 8;
        };

        let over = len & 7;
        if over == 7 { h ^= (key[i+6] as u64) << 48; }
        if over >= 6 { h ^= (key[i+5] as u64) << 40; }
        if over >= 5 { h ^= (key[i+4] as u64) << 32; }
        if over >= 4 { h ^= (key[i+3] as u64) << 24; }
        if over >= 3 { h ^= (key[i+2] as u64) << 16; }
        if over >= 2 { h ^= (key[i+1] as u64) << 8; }
        if over >= 1 { h ^= key[i+0] as u64; }
        if over >  0 { h *= m; }

        h ^= h >> r;
        h *= m;
        h ^= h >> r;
        h
    }
}

#[test]
fn test_mumurhash() {
    use murmurhash64::murmur_hash64a;
    assert_eq!(0, murmur_hash64a("".as_bytes(), 0));
    assert_eq!(0xc26e8bc196329b0f, murmur_hash64a("".as_bytes(), 10));
    assert_eq!(0x472ff7d324321dfe,
               murmur_hash64a("Pizza & Mandolino".as_bytes(), 2915580697));
}
<commit_msg>Use wrapping where necessary<commit_after>//! Implementation of MurmurHash2 (64bit version)
//!
//! Based on the implementation for Redis
//! ([antirez/redis src/hyperloglog.c](https://github.com/antirez/redis/blob/93eed9ae0163e328c33b16ab9ea3c4fbe0f98674/src/hyperloglog.c#L390-L439))
//!
//! More info and different implementations available at:
//! <https://sites.google.com/site/murmurhash/>
//!
//! # Basic Example
//!
//! ```rust
//! # use murmurhash64::murmur_hash64a;
//! let key = "Pizza & Mandolino";
//! let seed = 2915580697;
//!
//! let hash = murmur_hash64a(key.as_bytes(), seed);
//! ```

#![feature(default_type_params)]

#![experimental]

pub use murmurhash64::murmur_hash64a;
pub use hasher::MurmurState;
pub use hasher::MurmurHasher;

mod hasher;

mod murmurhash64 {
    /// Hash the given key and the given seed.
    ///
    /// Returns the resulting 64bit hash.
    ///
    /// Example:
    ///
    /// ```rust
    /// # use murmurhash64::murmur_hash64a;
    /// let key = "Pizza & Mandolino";
    /// let seed = 2915580697;
    ///
    /// let hash = murmur_hash64a(key.as_bytes(), seed);
    /// ```
    pub fn murmur_hash64a(key: &[u8], seed: u64) -> u64 {
        let m : u64 = 0xc6a4a7935bd1e995;
        let r : u8 = 47;

        let len = key.len();
        let mut h : u64 = seed ^ ((len as u64).wrapping_mul(m));

        let endpos = len-(len&7);
        let mut i = 0;
        while i != endpos {
            let mut k : u64;

            k  = key[i+0] as u64;
            k |= (key[i+1] as u64) << 8;
            k |= (key[i+2] as u64) << 16;
            k |= (key[i+3] as u64) << 24;
            k |= (key[i+4] as u64) << 32;
            k |= (key[i+5] as u64) << 40;
            k |= (key[i+6] as u64) << 48;
            k |= (key[i+7] as u64) << 56;

            k = k.wrapping_mul(m);
            k ^= k >> r;
            k = k.wrapping_mul(m);
            h ^= k;
            h = h.wrapping_mul(m);

            i += 8;
        };

        let over = len & 7;
        if over == 7 { h ^= (key[i+6] as u64) << 48; }
        if over >= 6 { h ^= (key[i+5] as u64) << 40; }
        if over >= 5 { h ^= (key[i+4] as u64) << 32; }
        if over >= 4 { h ^= (key[i+3] as u64) << 24; }
        if over >= 3 { h ^= (key[i+2] as u64) << 16; }
        if over >= 2 { h ^= (key[i+1] as u64) << 8; }
        if over >= 1 { h ^= key[i+0] as u64; }
        if over >  0 { h = h.wrapping_mul(m); }

        h ^= h >> r;
        h = h.wrapping_mul(m);
        h ^= h >> r;
        h
    }
}

#[test]
fn test_mumurhash() {
    use murmurhash64::murmur_hash64a;
    assert_eq!(0, murmur_hash64a("".as_bytes(), 0));
    assert_eq!(0xc26e8bc196329b0f, murmur_hash64a("".as_bytes(), 10));
    assert_eq!(0x472ff7d324321dfe,
               murmur_hash64a("Pizza & Mandolino".as_bytes(), 2915580697));
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![deny(warnings)]

//! # `toml_edit`
//!
//! This crate allows you to parse and modify toml
//! documents, while preserving comments, spaces* and
//! relative order* or items.
//!
//! It is primarily tailored to the needs of [cargo-edit](https://github.com/killercup/cargo-edit/).
//!
//! # Example
//!
//! ```rust
//! extern crate toml_edit;
//!
//! use toml_edit::{Document, value};
//!
//! fn main() {
//!     let toml = r#"
//! "hello" = 'toml!' # comment
//! ['a'.b]
//!     "#;
//!     let mut doc = toml.parse::<Document>().expect("invalid doc");
//!     assert_eq!(doc.to_string(), toml);
//!     // let's add a new key/value pair inside a.b: c = {d = "hello"}
//!     doc["a"]["b"]["c"]["d"] = value("hello");
//!     // autoformat inline table a.b.c: { d = "hello" }
//!     doc["a"]["b"]["c"].as_inline_table_mut().map(|t| t.fmt());
//!     let expected = r#"
//! "hello" = 'toml!' # comment
//! ['a'.b]
//! c = { d = "hello" }
//!     "#;
//!     assert_eq!(doc.to_string(), expected);
//! }
//! ```
//!
//! ## Limitations
//!
//! *Things it does not preserve:
//! 1. Different quotes and spaces around the same table key, e.g.
//! ```toml
//! [ 'a'. b]
//! [ "a"  .c]
//! [a.d]
//! ```
//! will be represented as (spaces are removed, the first encountered quote type is used)
//! ```toml
//! ['a'.b]
//! ['a'.c]
//! ['a'.d]
//! ```
//! 2. Children tables before parent table (tables are reordered, see [test]).
//! 3. Scattered array of tables (tables are reordered, see [test]).
//!
//! The reason behind the first limitation is that `Table` does not store its header,
//! allowing us to safely swap two tables
//! (we store a mapping in each table: child key -> child table).
//!
//! This last two limitations allow us to represent a toml document as a tree-like data structure,
//! which enables easier implementation of editing operations
//! and an easy to use and type-safe API.
extern crate chrono;
#[macro_use]
extern crate combine;
extern crate linked_hash_map;

pub(crate) mod formatted;
mod value;
mod display;
mod parser;
mod decor;
mod key;
mod array_of_tables;
mod table;
mod document;
mod index;

pub use value::{Array, InlineTable, Value};
pub use key::Key;
pub use parser::TomlError;
pub use table::{array, table, value, Item, Iter, Table, TableLike};
pub use array_of_tables::ArrayOfTables;
pub use document::Document;
<commit_msg>doc(lib): Fix toml snippet in markdown<commit_after>#![deny(missing_docs)]
#![deny(warnings)]

//! # `toml_edit`
//!
//! This crate allows you to parse and modify toml
//! documents, while preserving comments, spaces* and
//! relative order* or items.
//!
//! It is primarily tailored to the needs of [cargo-edit](https://github.com/killercup/cargo-edit/).
//!
//! # Example
//!
//! ```rust
//! extern crate toml_edit;
//!
//! use toml_edit::{Document, value};
//!
//! fn main() {
//!     let toml = r#"
//! "hello" = 'toml!' # comment
//! ['a'.b]
//!     "#;
//!     let mut doc = toml.parse::<Document>().expect("invalid doc");
//!     assert_eq!(doc.to_string(), toml);
//!     // let's add a new key/value pair inside a.b: c = {d = "hello"}
//!     doc["a"]["b"]["c"]["d"] = value("hello");
//!     // autoformat inline table a.b.c: { d = "hello" }
//!     doc["a"]["b"]["c"].as_inline_table_mut().map(|t| t.fmt());
//!     let expected = r#"
//! "hello" = 'toml!' # comment
//! ['a'.b]
//! c = { d = "hello" }
//!     "#;
//!     assert_eq!(doc.to_string(), expected);
//! }
//! ```
//!
//! ## Limitations
//!
//! *Things it does not preserve:
//! 1. Different quotes and spaces around the same table key, e.g.
//!
//! ```text
//! [ 'a'. b]
//! [ "a"  .c]
//! [a.d]
//! ```
//!
//! will be represented as (spaces are removed, the first encountered quote type is used)
//!
//! ```text
//! ['a'.b]
//! ['a'.c]
//! ['a'.d]
//! ```
//!
//! 2. Children tables before parent table (tables are reordered, see [test]).
//! 3. Scattered array of tables (tables are reordered, see [test]).
//!
//! The reason behind the first limitation is that `Table` does not store its header,
//! allowing us to safely swap two tables
//! (we store a mapping in each table: child key -> child table).
//!
//! This last two limitations allow us to represent a toml document as a tree-like data structure,
//! which enables easier implementation of editing operations
//! and an easy to use and type-safe API.
extern crate chrono;
#[macro_use]
extern crate combine;
extern crate linked_hash_map;

pub(crate) mod formatted;
mod value;
mod display;
mod parser;
mod decor;
mod key;
mod array_of_tables;
mod table;
mod document;
mod index;

pub use value::{Array, InlineTable, Value};
pub use key::Key;
pub use parser::TomlError;
pub use table::{array, table, value, Item, Iter, Table, TableLike};
pub use array_of_tables::ArrayOfTables;
pub use document::Document;
<|endoftext|>