<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 = "cssparser"]
#![crate_type = "rlib"]

#![cfg_attr(feature = "bench", feature(test))]
#![deny(missing_docs)]

/*!

Implementation of [CSS Syntax Module Level 3](https://drafts.csswg.org/css-syntax/) for Rust.

# Input

Everything is based on `Parser` objects, which borrow a `&str` input.
If you have bytes (from a file, the network, or something)
and want to support character encodings other than UTF-8,
see the `stylesheet_encoding` function,
which can be used together with rust-encoding or encoding-rs.

# Conventions for parsing functions

* Take (at least) a `input: &mut cssparser::Parser` parameter
* Return `Result<_, ()>`
* When returning `Ok(_)`,
  the function must have consume exactly the amount of input that represents the parsed value.
* When returning `Err(())`, any amount of input may have been consumed.

As a consequence, when calling another parsing function, either:

* Any `Err(())` return value must be propagated.
  This happens by definition for tail calls,
  and can otherwise be done with the `try!` macro.
* Or the call must be wrapped in a `Parser::try` call.
  `try` takes a closure that takes a `Parser` and returns a `Result`,
  calls it once,
  and returns itself that same result.
  If the result is `Err`,
  it restores the position inside the input to the one saved before calling the closure.

Examples:

```{rust,ignore}
// 'none' | <image>
fn parse_background_image(context: &ParserContext, input: &mut Parser)
                                    -> Result<Option<Image>, ()> {
    if input.try(|input| input.expect_ident_matching("none")).is_ok() {
        Ok(None)
    } else {
        Image::parse(context, input).map(Some)  // tail call
    }
}
```

```{rust,ignore}
// [ <length> | <percentage> ] [ <length> | <percentage> ]?
fn parse_border_spacing(_context: &ParserContext, input: &mut Parser)
                          -> Result<(LengthOrPercentage, LengthOrPercentage), ()> {
    let first = try!(LengthOrPercentage::parse);
    let second = input.try(LengthOrPercentage::parse).unwrap_or(first);
    (first, second)
}
```

*/

#![recursion_limit="200"]  // For color::parse_color_keyword

#[macro_use] extern crate cssparser_macros;
#[macro_use] extern crate matches;
extern crate phf;
#[cfg(test)] extern crate encoding_rs;
#[cfg(test)] extern crate tempdir;
#[cfg(test)] extern crate rustc_serialize;
#[cfg(feature = "serde")] extern crate serde;
#[cfg(feature = "heapsize")] #[macro_use] extern crate heapsize;

pub use tokenizer::{Token, NumericValue, PercentageValue, SourceLocation};
pub use rules_and_declarations::{parse_important};
pub use rules_and_declarations::{DeclarationParser, DeclarationListParser, parse_one_declaration};
pub use rules_and_declarations::{RuleListParser, parse_one_rule};
pub use rules_and_declarations::{AtRuleType, QualifiedRuleParser, AtRuleParser};
pub use from_bytes::{stylesheet_encoding, EncodingSupport};
pub use color::{RGBA, Color, parse_color_keyword};
pub use nth::parse_nth;
pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_string, TokenSerializationType};
pub use parser::{Parser, Delimiter, Delimiters, SourcePosition};
pub use unicode_range::UnicodeRange;

/// Expands to an expression equivalent to a `match` with string patterns,
/// but matching is case-insensitive in the ASCII range.
///
/// Requirements:
///
/// * The `cssparser_macros` crate must also be imported at the crate root
/// * The patterns must not contain ASCII upper case letters. (They must be already be lower-cased.)
///
/// # Example
///
/// ```rust
/// #[macro_use] extern crate cssparser;
/// #[macro_use] extern crate cssparser_macros;
///
/// # fn main() {}  // Make doctest not wrap everythig in its own main
/// # fn dummy(function_name: &String) { let _ =
/// match_ignore_ascii_case! { &function_name,
///     "rgb" => parse_rgb(..),
///     "rgba" => parse_rgba(..),
///     "hsl" => parse_hsl(..),
///     "hsla" => parse_hsla(..),
///     _ => Err("unknown function")
/// }
/// # ;}
/// # use std::ops::RangeFull;
/// # fn parse_rgb(_: RangeFull) -> Result<(), &'static str> { Err("") }
/// # fn parse_rgba(_: RangeFull) -> Result<(), &'static str> { Err("") }
/// # fn parse_hsl(_: RangeFull) -> Result<(), &'static str> { Err("") }
/// # fn parse_hsla(_: RangeFull) -> Result<(), &'static str> { Err("") }
/// ```
#[macro_export]
macro_rules! match_ignore_ascii_case {
    // parse the last case plus the fallback
    (@inner $value:expr, ($string:expr => $result:expr, _ => $fallback:expr) -> ($($parsed:tt)*) ) => {
        match_ignore_ascii_case!(@inner $value, () -> ($($parsed)* ($string => $result)) $fallback)
    };

    // parse a case (not the last one)
    (@inner $value:expr, ($string:expr => $result:expr, $($rest:tt)*) -> ($($parsed:tt)*) ) => {
        match_ignore_ascii_case!(@inner $value, ($($rest)*) -> ($($parsed)* ($string => $result)))
    };

    // finished parsing
    (@inner $value:expr, () -> ($(($string:expr => $result:expr))*) $fallback:expr ) => {
        {
            #[derive(cssparser__assert_ascii_lowercase)]
            #[cssparser__assert_ascii_lowercase__data($(string = $string),+)]
            #[allow(dead_code)]
            struct Dummy;

            _cssparser_internal__max_len!($value => lowercase, $($string),+);
            match lowercase {
                $(
                    Some($string) => $result,
                )+
                _ => $fallback
            }
        }
    };

    // entry point, start parsing
    ( $value:expr, $($rest:tt)* ) => {
        match_ignore_ascii_case!(@inner $value, ($($rest)*) -> ())
    };
}

/// Define a placeholder type `$Name`
/// with a method `fn get(input: &str) -> Option<&'static $ValueType>`.
///
/// This method uses finds a match for the input string
/// in a [`phf` map](https://github.com/sfackler/rust-phf).
/// Matching is case-insensitive in the ASCII range.
///
/// Requirements:
///
/// * The `phf` and `cssparser_macros` crates must also be imported at the crate root
/// * The values must be given a strings that contain Rust syntax for a constant expression.
///
/// ## Example:
///
/// ```rust
/// extern crate phf;
/// #[macro_use] extern crate cssparser;
/// #[macro_use] extern crate cssparser_macros;
///
/// # fn main() {}  // Make doctest not wrap everythig in its own main
///
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
///     ascii_case_insensitive_phf_map! {
///         KEYWORDS: Map<(u8, u8, u8)> = {
///             "red" => "(255, 0, 0)",
///             "green" => "(0, 255, 0)",
///             "blue" => "(0, 0, 255)",
///         }
///     }
///     KEYWORDS::get(input).cloned()
/// }
#[macro_export]
macro_rules! ascii_case_insensitive_phf_map {
    ($Name: ident : Map<$ValueType: ty> = {
        $( $key: expr => $value: expr, )*
    }) => {
        #[derive(cssparser__phf_map)]
        #[cssparser__phf_map__kv_pairs(
            $(
                key = $key,
                value = $value
            ),+
        )]
        struct $Name($ValueType);

        impl $Name {
            #[inline]
            fn get(input: &str) -> Option<&'static $ValueType> {
                _cssparser_internal__max_len!(input => lowercase, $($key),+);
                lowercase.and_then(|string| $Name::map().get(string))
            }
        }
    }
}

/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
///
/// * Check at compile-time that none of the `$string`s contain ASCII uppercase letters
/// * Define a local variable named `$output`
///   to the result of calling `_match_ignore_ascii_case__to_lowercase`
///   with a stack-allocated buffer as long as the longest `$string`.
#[macro_export]
#[doc(hidden)]
macro_rules! _cssparser_internal__max_len {
    ($input: expr => $output: ident, $($string: expr),+) => {
        #[derive(cssparser__max_len)]
        #[cssparser__max_len__data($(string = $string),+)]
        #[allow(dead_code)]
        struct Dummy2;

        // MAX_LENGTH is generated by cssparser__match_ignore_ascii_case__max_len
        let mut buffer: [u8; MAX_LENGTH] =
            // `buffer` is only used in `_match_ignore_ascii_case__to_lowercase`,
            // which initializes with `copy_from_slice` the part of the buffer it uses,
            // before it uses it.
            unsafe {
                ::std::mem::uninitialized()
            };
        let $output = $crate::_match_ignore_ascii_case__to_lowercase(&mut buffer, $input);
    }
}

/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
///
/// Return `input`, lower-cased, unless larger than `buffer`
/// which is used temporary space for lower-casing a copy of `input` if necessary.
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn _match_ignore_ascii_case__to_lowercase<'a>(buffer: &'a mut [u8], input: &'a str) -> Option<&'a str> {
    if let Some(buffer) = buffer.get_mut(..input.len()) {
        if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'...b'Z')) {
            buffer.copy_from_slice(input.as_bytes());
            std::ascii::AsciiExt::make_ascii_lowercase(&mut buffer[first_uppercase..]);
            // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
            // then lowercased (which preserves UTF-8 well-formedness)
            unsafe {
                Some(::std::str::from_utf8_unchecked(buffer))
            }
        } else {
            // Input is already lower-case
            Some(input)
        }
    } else {
        // Input is longer than buffer, which has the length of the longest expected string:
        // none of the expected strings would match.
        None
    }
}

mod rules_and_declarations;

#[cfg(feature = "dummy_match_byte")]
macro_rules! match_byte {
    ($value:expr, $($rest:tt)* ) => {
        match $value {
            $(
                $rest
            )+
        }
    };
}

#[cfg(feature = "dummy_match_byte")]
mod tokenizer;

#[cfg(not(feature = "dummy_match_byte"))]
mod tokenizer {
    include!(concat!(env!("OUT_DIR"), "/tokenizer.rs"));
}
mod parser;
mod from_bytes;
mod color;
mod nth;
mod serializer;
mod unicode_range;

#[cfg(test)]
mod tests;
<commit_msg>Rename internal things per what they do.<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 = "cssparser"]
#![crate_type = "rlib"]

#![cfg_attr(feature = "bench", feature(test))]
#![deny(missing_docs)]

/*!

Implementation of [CSS Syntax Module Level 3](https://drafts.csswg.org/css-syntax/) for Rust.

# Input

Everything is based on `Parser` objects, which borrow a `&str` input.
If you have bytes (from a file, the network, or something)
and want to support character encodings other than UTF-8,
see the `stylesheet_encoding` function,
which can be used together with rust-encoding or encoding-rs.

# Conventions for parsing functions

* Take (at least) a `input: &mut cssparser::Parser` parameter
* Return `Result<_, ()>`
* When returning `Ok(_)`,
  the function must have consume exactly the amount of input that represents the parsed value.
* When returning `Err(())`, any amount of input may have been consumed.

As a consequence, when calling another parsing function, either:

* Any `Err(())` return value must be propagated.
  This happens by definition for tail calls,
  and can otherwise be done with the `try!` macro.
* Or the call must be wrapped in a `Parser::try` call.
  `try` takes a closure that takes a `Parser` and returns a `Result`,
  calls it once,
  and returns itself that same result.
  If the result is `Err`,
  it restores the position inside the input to the one saved before calling the closure.

Examples:

```{rust,ignore}
// 'none' | <image>
fn parse_background_image(context: &ParserContext, input: &mut Parser)
                                    -> Result<Option<Image>, ()> {
    if input.try(|input| input.expect_ident_matching("none")).is_ok() {
        Ok(None)
    } else {
        Image::parse(context, input).map(Some)  // tail call
    }
}
```

```{rust,ignore}
// [ <length> | <percentage> ] [ <length> | <percentage> ]?
fn parse_border_spacing(_context: &ParserContext, input: &mut Parser)
                          -> Result<(LengthOrPercentage, LengthOrPercentage), ()> {
    let first = try!(LengthOrPercentage::parse);
    let second = input.try(LengthOrPercentage::parse).unwrap_or(first);
    (first, second)
}
```

*/

#![recursion_limit="200"]  // For color::parse_color_keyword

#[macro_use] extern crate cssparser_macros;
#[macro_use] extern crate matches;
extern crate phf;
#[cfg(test)] extern crate encoding_rs;
#[cfg(test)] extern crate tempdir;
#[cfg(test)] extern crate rustc_serialize;
#[cfg(feature = "serde")] extern crate serde;
#[cfg(feature = "heapsize")] #[macro_use] extern crate heapsize;

pub use tokenizer::{Token, NumericValue, PercentageValue, SourceLocation};
pub use rules_and_declarations::{parse_important};
pub use rules_and_declarations::{DeclarationParser, DeclarationListParser, parse_one_declaration};
pub use rules_and_declarations::{RuleListParser, parse_one_rule};
pub use rules_and_declarations::{AtRuleType, QualifiedRuleParser, AtRuleParser};
pub use from_bytes::{stylesheet_encoding, EncodingSupport};
pub use color::{RGBA, Color, parse_color_keyword};
pub use nth::parse_nth;
pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_string, TokenSerializationType};
pub use parser::{Parser, Delimiter, Delimiters, SourcePosition};
pub use unicode_range::UnicodeRange;

/// Expands to an expression equivalent to a `match` with string patterns,
/// but matching is case-insensitive in the ASCII range.
///
/// Requirements:
///
/// * The `cssparser_macros` crate must also be imported at the crate root
/// * The patterns must not contain ASCII upper case letters. (They must be already be lower-cased.)
///
/// # Example
///
/// ```rust
/// #[macro_use] extern crate cssparser;
/// #[macro_use] extern crate cssparser_macros;
///
/// # fn main() {}  // Make doctest not wrap everythig in its own main
/// # fn dummy(function_name: &String) { let _ =
/// match_ignore_ascii_case! { &function_name,
///     "rgb" => parse_rgb(..),
///     "rgba" => parse_rgba(..),
///     "hsl" => parse_hsl(..),
///     "hsla" => parse_hsla(..),
///     _ => Err("unknown function")
/// }
/// # ;}
/// # use std::ops::RangeFull;
/// # fn parse_rgb(_: RangeFull) -> Result<(), &'static str> { Err("") }
/// # fn parse_rgba(_: RangeFull) -> Result<(), &'static str> { Err("") }
/// # fn parse_hsl(_: RangeFull) -> Result<(), &'static str> { Err("") }
/// # fn parse_hsla(_: RangeFull) -> Result<(), &'static str> { Err("") }
/// ```
#[macro_export]
macro_rules! match_ignore_ascii_case {
    // parse the last case plus the fallback
    (@inner $value:expr, ($string:expr => $result:expr, _ => $fallback:expr) -> ($($parsed:tt)*) ) => {
        match_ignore_ascii_case!(@inner $value, () -> ($($parsed)* ($string => $result)) $fallback)
    };

    // parse a case (not the last one)
    (@inner $value:expr, ($string:expr => $result:expr, $($rest:tt)*) -> ($($parsed:tt)*) ) => {
        match_ignore_ascii_case!(@inner $value, ($($rest)*) -> ($($parsed)* ($string => $result)))
    };

    // finished parsing
    (@inner $value:expr, () -> ($(($string:expr => $result:expr))*) $fallback:expr ) => {
        {
            #[derive(cssparser__assert_ascii_lowercase)]
            #[cssparser__assert_ascii_lowercase__data($(string = $string),+)]
            #[allow(dead_code)]
            struct Dummy;

            _cssparser_internal__to_lowercase!($value => lowercase, $($string),+);
            match lowercase {
                $(
                    Some($string) => $result,
                )+
                _ => $fallback
            }
        }
    };

    // entry point, start parsing
    ( $value:expr, $($rest:tt)* ) => {
        match_ignore_ascii_case!(@inner $value, ($($rest)*) -> ())
    };
}

/// Define a placeholder type `$Name`
/// with a method `fn get(input: &str) -> Option<&'static $ValueType>`.
///
/// This method uses finds a match for the input string
/// in a [`phf` map](https://github.com/sfackler/rust-phf).
/// Matching is case-insensitive in the ASCII range.
///
/// Requirements:
///
/// * The `phf` and `cssparser_macros` crates must also be imported at the crate root
/// * The values must be given a strings that contain Rust syntax for a constant expression.
///
/// ## Example:
///
/// ```rust
/// extern crate phf;
/// #[macro_use] extern crate cssparser;
/// #[macro_use] extern crate cssparser_macros;
///
/// # fn main() {}  // Make doctest not wrap everythig in its own main
///
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
///     ascii_case_insensitive_phf_map! {
///         KEYWORDS: Map<(u8, u8, u8)> = {
///             "red" => "(255, 0, 0)",
///             "green" => "(0, 255, 0)",
///             "blue" => "(0, 0, 255)",
///         }
///     }
///     KEYWORDS::get(input).cloned()
/// }
#[macro_export]
macro_rules! ascii_case_insensitive_phf_map {
    ($Name: ident : Map<$ValueType: ty> = {
        $( $key: expr => $value: expr, )*
    }) => {
        #[derive(cssparser__phf_map)]
        #[cssparser__phf_map__kv_pairs(
            $(
                key = $key,
                value = $value
            ),+
        )]
        struct $Name($ValueType);

        impl $Name {
            #[inline]
            fn get(input: &str) -> Option<&'static $ValueType> {
                _cssparser_internal__to_lowercase!(input => lowercase, $($key),+);
                lowercase.and_then(|string| $Name::map().get(string))
            }
        }
    }
}

/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
///
/// **This macro is not part of the public API. It can change or be removed between any versions.**
///
/// * Check at compile-time that none of the `$string`s contain ASCII uppercase letters
/// * Define a local variable named `$output` to the result of calling `_internal__to_lowercase`
///   with a stack-allocated buffer as long as the longest `$string`.
#[macro_export]
#[doc(hidden)]
macro_rules! _cssparser_internal__to_lowercase {
    ($input: expr => $output: ident, $($string: expr),+) => {
        #[derive(cssparser__max_len)]
        #[cssparser__max_len__data($(string = $string),+)]
        #[allow(dead_code)]
        struct Dummy2;

        // MAX_LENGTH is generated by cssparser__match_ignore_ascii_case__max_len
        let mut buffer: [u8; MAX_LENGTH] =
            // `buffer` is only used in `_internal__to_lowercase`,
            // which initializes with `copy_from_slice` the part of the buffer it uses,
            // before it uses it.
            unsafe {
                ::std::mem::uninitialized()
            };
        let $output = $crate::_internal__to_lowercase(&mut buffer, $input);
    }
}

/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
///
/// **This function is not part of the public API. It can change or be removed between any verisons.**
///
/// Return `input`, lower-cased, unless larger than `buffer`
/// which is used temporary space for lower-casing a copy of `input` if necessary.
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn _internal__to_lowercase<'a>(buffer: &'a mut [u8], input: &'a str) -> Option<&'a str> {
    if let Some(buffer) = buffer.get_mut(..input.len()) {
        if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'...b'Z')) {
            buffer.copy_from_slice(input.as_bytes());
            std::ascii::AsciiExt::make_ascii_lowercase(&mut buffer[first_uppercase..]);
            // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
            // then lowercased (which preserves UTF-8 well-formedness)
            unsafe {
                Some(::std::str::from_utf8_unchecked(buffer))
            }
        } else {
            // Input is already lower-case
            Some(input)
        }
    } else {
        // Input is longer than buffer, which has the length of the longest expected string:
        // none of the expected strings would match.
        None
    }
}

mod rules_and_declarations;

#[cfg(feature = "dummy_match_byte")]
macro_rules! match_byte {
    ($value:expr, $($rest:tt)* ) => {
        match $value {
            $(
                $rest
            )+
        }
    };
}

#[cfg(feature = "dummy_match_byte")]
mod tokenizer;

#[cfg(not(feature = "dummy_match_byte"))]
mod tokenizer {
    include!(concat!(env!("OUT_DIR"), "/tokenizer.rs"));
}
mod parser;
mod from_bytes;
mod color;
mod nth;
mod serializer;
mod unicode_range;

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>// DOCS

extern crate tempdir;

use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;
use std::convert::AsRef;

use tempdir::TempDir;

pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Clone,Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    pub fn new<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior) -> Self {
        let p = path.as_ref();
        AtomicFile::new_with_tmpdir(p, overwrite, p.parent().unwrap_or(p))
    }

    pub fn new_with_tmpdir<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior, tmpdir: P) -> Self {
        AtomicFile {
            path: path.as_ref().to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.as_ref().to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Get the target filepath.
    pub fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<E, F: FnMut(&mut fs::File) -> io::Result<E>>(&self, mut f: F) -> io::Result<E> {
        let tmpdir = match TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ) {
            Ok(x) => x,
            Err(_) => return Err(io::Error::new(
                io::ErrorKind::Other,
                "Failed to create a temporary directory."
            ))
        };

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        let rv = try!({
            let mut tmpfile = try!(fs::File::create(&tmppath));
            f(&mut tmpfile)
        });
        try!(self.commit(&tmppath));
        Ok(rv)
    }
}

#[cfg(unix)]
mod imp {
    use std::{io,fs,path};

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        fs::rename(src, dst)
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::hard_link(src, dst));
        fs::remove_file(src)
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;
    extern crate kernel32 as win32kernel;

    use std::{io,path};
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    macro_rules! call {
        ($e: expr) => (
            if $e != 0 {
                Ok(())
            } else {
                Err(io::Error::last_os_error())
            }
        )
    }

    fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::WCHAR> {
        x.as_ref().encode_wide().chain(Some(0)).collect()
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH | winapi::MOVEFILE_REPLACE_EXISTING
        )})
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH
        )})
    }
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::replace_atomic(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::move_atomic(src, dst)
}
<commit_msg>Better error reporting<commit_after>// DOCS

extern crate tempdir;

use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;
use std::convert::AsRef;

use tempdir::TempDir;

pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Clone,Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    pub fn new<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior) -> Self {
        let p = path.as_ref();
        AtomicFile::new_with_tmpdir(p, overwrite, p.parent().unwrap_or(p))
    }

    pub fn new_with_tmpdir<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior, tmpdir: P) -> Self {
        AtomicFile {
            path: path.as_ref().to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.as_ref().to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Get the target filepath.
    pub fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<E, F: FnMut(&mut fs::File) -> io::Result<E>>(&self, mut f: F) -> io::Result<E> {
        let tmpdir = try!(TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ));

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        let rv = try!({
            let mut tmpfile = try!(fs::File::create(&tmppath));
            f(&mut tmpfile)
        });
        try!(self.commit(&tmppath));
        Ok(rv)
    }
}

#[cfg(unix)]
mod imp {
    use std::{io,fs,path};

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        fs::rename(src, dst)
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::hard_link(src, dst));
        fs::remove_file(src)
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;
    extern crate kernel32 as win32kernel;

    use std::{io,path};
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    macro_rules! call {
        ($e: expr) => (
            if $e != 0 {
                Ok(())
            } else {
                Err(io::Error::last_os_error())
            }
        )
    }

    fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::WCHAR> {
        x.as_ref().encode_wide().chain(Some(0)).collect()
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH | winapi::MOVEFILE_REPLACE_EXISTING
        )})
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH
        )})
    }
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::replace_atomic(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::move_atomic(src, dst)
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate clap;
extern crate hyper;
extern crate libc;
extern crate multirust;
extern crate rust_install;
extern crate term;

use std::{error, fmt, str};
use std::ffi::OsStr;

use chrono::NaiveDate;
use hyper::client::Client;
use rust_install::dist::ToolchainDesc;

const NIGHTLY: &'static str = "nightly";

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

mod bisect;
pub use bisect::least_satisfying;

pub mod cli;

#[derive(Clone, Copy, Debug)]
pub struct Nightly {
    pub date: NaiveDate,
}

impl Nightly {
    fn to_toolchain_desc(&self) -> ToolchainDesc {
        ToolchainDesc {
            date: Some(self.date.to_string()),
            channel: String::from(NIGHTLY),
            arch: None,
            os: None,
            env: None,
        }
    }
}

impl From<NaiveDate> for Nightly {
    fn from(date: NaiveDate) -> Nightly {
        Nightly { date: date }
    }
}

impl str::FromStr for Nightly {
    type Err = Error;
    fn from_str(s: &str) -> Result<Nightly> {
        let desc = try!(ToolchainDesc::from_str(s).ok_or("invalid toolchain name"));
        if desc.channel != NIGHTLY || desc.date.is_none() {
            return Err(Error::from("not a dated nightly"));
        }
        Ok(Nightly { date: try!(desc.date.unwrap().parse()) })
    }
}

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

#[derive(Debug)]
pub struct Cfg<'a> {
    pub good: Nightly,
    pub bad: Nightly,
    pub cmd: &'a OsStr,
    pub args: Vec<&'a OsStr>,
}

fn list_available_nightlies(dist_root: &str,
                            from: NaiveDate,
                            to: NaiveDate)
                            -> Result<Vec<Nightly>> {
    assert!(from < to, "`from` must be less than `to`");
    let client = Client::new();
    let mut nightlies = Vec::with_capacity((to - from).num_days() as usize);
    let mut date = from;
    while date < to {
        let nightly = Nightly::from(date);
        let manifest_url = nightly.to_toolchain_desc().manifest_url(dist_root);
        let resp = try!(client.head(&manifest_url).send());
        // TODO: ensure failures are 404
        if resp.status.is_success() {
            nightlies.push(nightly);
        }
        date = date.succ();
    }
    Ok(nightlies)
}

pub fn run<'a>(cfg: &'a Cfg, mr_cfg: &multirust::Cfg) -> Result<i32> {

    println!("finding available nightlies between {} and {}",
             cfg.good,
             cfg.bad);
    let nightlies = try!(list_available_nightlies(&*mr_cfg.dist_root_url,
                                                  cfg.good.date,
                                                  cfg.bad.date));
    if nightlies.is_empty() {
        try!(cli::display_error(format!("no nightlies found between {} and {}",
                                        cfg.good,
                                        cfg.bad)));
        return Ok(libc::EXIT_FAILURE);
    }

    println!("found {} nightlies", nightlies.len());
    println!("bisecting across {} nightlies (about {} steps)",
             nightlies.len(),
             nightlies.len().next_power_of_two().trailing_zeros());

    let idx = least_satisfying(&nightlies[..], |nightly| {
        println!("testing with {}", nightly);

        let toolchain = mr_cfg.get_toolchain(&nightly.to_string(), false)
                              .expect("could not get toolchain");
        toolchain.install_from_dist_if_not_installed().expect("could not install toolchain");

        let mut cmd = toolchain.create_command(cfg.cmd).expect("could not create command");
        cmd.args(&cfg.args);
        let res = cmd.status().expect("could not run command").success();

        println!("command {} with {}",
                 if res {
                     "succeeded"
                 } else {
                     "failed"
                 },
                 nightly);
        !res
    });

    println!("{} is the first failing nightly", nightlies[idx]);
    Ok(libc::EXIT_SUCCESS)
}
<commit_msg>Remove redundant info message<commit_after>extern crate chrono;
extern crate clap;
extern crate hyper;
extern crate libc;
extern crate multirust;
extern crate rust_install;
extern crate term;

use std::{error, fmt, str};
use std::ffi::OsStr;

use chrono::NaiveDate;
use hyper::client::Client;
use rust_install::dist::ToolchainDesc;

const NIGHTLY: &'static str = "nightly";

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

mod bisect;
pub use bisect::least_satisfying;

pub mod cli;

#[derive(Clone, Copy, Debug)]
pub struct Nightly {
    pub date: NaiveDate,
}

impl Nightly {
    fn to_toolchain_desc(&self) -> ToolchainDesc {
        ToolchainDesc {
            date: Some(self.date.to_string()),
            channel: String::from(NIGHTLY),
            arch: None,
            os: None,
            env: None,
        }
    }
}

impl From<NaiveDate> for Nightly {
    fn from(date: NaiveDate) -> Nightly {
        Nightly { date: date }
    }
}

impl str::FromStr for Nightly {
    type Err = Error;
    fn from_str(s: &str) -> Result<Nightly> {
        let desc = try!(ToolchainDesc::from_str(s).ok_or("invalid toolchain name"));
        if desc.channel != NIGHTLY || desc.date.is_none() {
            return Err(Error::from("not a dated nightly"));
        }
        Ok(Nightly { date: try!(desc.date.unwrap().parse()) })
    }
}

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

#[derive(Debug)]
pub struct Cfg<'a> {
    pub good: Nightly,
    pub bad: Nightly,
    pub cmd: &'a OsStr,
    pub args: Vec<&'a OsStr>,
}

fn list_available_nightlies(dist_root: &str,
                            from: NaiveDate,
                            to: NaiveDate)
                            -> Result<Vec<Nightly>> {
    assert!(from < to, "`from` must be less than `to`");
    let client = Client::new();
    let mut nightlies = Vec::with_capacity((to - from).num_days() as usize);
    let mut date = from;
    while date < to {
        let nightly = Nightly::from(date);
        let manifest_url = nightly.to_toolchain_desc().manifest_url(dist_root);
        let resp = try!(client.head(&manifest_url).send());
        // TODO: ensure failures are 404
        if resp.status.is_success() {
            nightlies.push(nightly);
        }
        date = date.succ();
    }
    Ok(nightlies)
}

pub fn run<'a>(cfg: &'a Cfg, mr_cfg: &multirust::Cfg) -> Result<i32> {

    println!("finding available nightlies between {} and {}",
             cfg.good,
             cfg.bad);
    let nightlies = try!(list_available_nightlies(&*mr_cfg.dist_root_url,
                                                  cfg.good.date,
                                                  cfg.bad.date));
    if nightlies.is_empty() {
        try!(cli::display_error(format!("no nightlies found between {} and {}",
                                        cfg.good,
                                        cfg.bad)));
        return Ok(libc::EXIT_FAILURE);
    }

    println!("bisecting across {} nightlies (about {} steps)",
             nightlies.len(),
             nightlies.len().next_power_of_two().trailing_zeros());

    let idx = least_satisfying(&nightlies[..], |nightly| {
        println!("testing with {}", nightly);

        let toolchain = mr_cfg.get_toolchain(&nightly.to_string(), false)
                              .expect("could not get toolchain");
        toolchain.install_from_dist_if_not_installed().expect("could not install toolchain");

        let mut cmd = toolchain.create_command(cfg.cmd).expect("could not create command");
        cmd.args(&cfg.args);
        let res = cmd.status().expect("could not run command").success();

        println!("command {} with {}",
                 if res {
                     "succeeded"
                 } else {
                     "failed"
                 },
                 nightly);
        !res
    });

    println!("{} is the first failing nightly", nightlies[idx]);
    Ok(libc::EXIT_SUCCESS)
}
<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
//! # Cairo bindings
//!   This library contains safe Rust bindings for [Cairo](https://www.cairographics.org/).
//!   It is a part of [Gtk-rs](http://gtk-rs.org/).
//! ## Crate features
//! ### Default-on features
//! * **use_glib** -  Use with [glib](https://gtk-rs.org/docs/glib/)
//! ### Fileformat features
//! * **png** - Reading and writing PNG images
//! * **pdf** - Rendering PDF documents
//! * **svg** - Rendering SVG documents
//! * **ps** - Rendering PostScript documents
//! ### Cairo API version features
//! * **v1_14** - Use Cairo 1.14 APIs
//! * **v1_16** - Use Cairo 1.16 APIs
//! ### Documentation features
//! * **embed-lgpl-docs** - Embed API docs locally
//! * **purge-lgpl-docs** - Remove API docs again (counterpart to `embed-lgpl-docs`)
//! * **dox** - Used to keep system dependent items in documentation
//! ### X Window features
//! * **xcb** - X Window System rendering using the XCB library
//! * **xlib** - X Window System rendering using XLib
//! ### Windows API features
//! * **win32-surface** - Microsoft Windows surface support
extern crate cairo_sys as ffi;
extern crate libc;

#[macro_use]
extern crate bitflags;

#[cfg(feature = "use_glib")]
#[macro_use]
extern crate glib;

#[cfg(feature = "use_glib")]
extern crate glib_sys as glib_ffi;

#[cfg(feature = "use_glib")]
extern crate gobject_sys as gobject_ffi;

#[cfg(test)]
extern crate tempfile;

// Helper macro for our GValue related trait impls
#[cfg(feature = "use_glib")]
macro_rules! gvalue_impl {
    ($name:ty, $ffi_name:ty, $get_type:expr) => {
        use glib;
        #[allow(unused_imports)]
        use glib::translate::*;
        use glib_ffi;
        use gobject_ffi;

        impl glib::types::StaticType for $name {
            fn static_type() -> glib::types::Type {
                unsafe { from_glib($get_type()) }
            }
        }

        impl<'a> glib::value::FromValueOptional<'a> for $name {
            unsafe fn from_value_optional(v: &'a glib::value::Value) -> Option<Self> {
                let ptr = gobject_ffi::g_value_get_boxed(v.to_glib_none().0);
                assert!(!ptr.is_null());
                from_glib_none(ptr as *mut $ffi_name)
            }
        }

        impl glib::value::SetValue for $name {
            unsafe fn set_value(v: &mut glib::value::Value, s: &Self) {
                gobject_ffi::g_value_set_boxed(
                    v.to_glib_none_mut().0,
                    s.to_glib_none().0 as glib_ffi::gpointer,
                );
            }
        }

        impl glib::value::SetValueOptional for $name {
            unsafe fn set_value_optional(v: &mut glib::value::Value, s: Option<&Self>) {
                if let Some(s) = s {
                    gobject_ffi::g_value_set_boxed(
                        v.to_glib_none_mut().0,
                        s.to_glib_none().0 as glib_ffi::gpointer,
                    );
                } else {
                    gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, ::std::ptr::null_mut());
                }
            }
        }
    };
}

pub use user_data::UserDataKey;

pub use context::{Context, RectangleList};

pub use paths::{Path, PathSegment, PathSegments};

pub use device::Device;

pub use enums::*;

pub use error::{BorrowError, IoError};

pub use patterns::{
    Gradient, LinearGradient, Mesh, Pattern, RadialGradient, SolidPattern, SurfacePattern,
};

pub use font::{
    FontExtents, FontFace, FontOptions, FontSlant, FontType, FontWeight, Glyph, ScaledFont,
    TextCluster, TextExtents,
};

pub use matrices::Matrix;

pub use recording_surface::RecordingSurface;
pub use rectangle::Rectangle;
pub use rectangle_int::RectangleInt;

pub use region::Region;

pub use surface::{MappedImageSurface, Surface};

pub use image_surface::{ImageSurface, ImageSurfaceData};

#[cfg(any(feature = "pdf", feature = "svg", feature = "ps", feature = "dox"))]
pub use stream::StreamWithError;

#[cfg(any(feature = "pdf", feature = "dox"))]
pub use pdf::PdfSurface;

#[cfg(any(feature = "ps", feature = "dox"))]
pub use ps::PsSurface;

#[cfg(any(feature = "svg", feature = "dox"))]
pub use svg::SvgSurface;

#[cfg(any(feature = "xcb", feature = "dox"))]
pub use xcb::{
    XCBConnection, XCBDrawable, XCBPixmap, XCBRenderPictFormInfo, XCBScreen, XCBSurface,
    XCBVisualType,
};

#[macro_use]
mod user_data;
mod constants;
pub use constants::*;
mod utils;
pub use utils::*;

mod context;
mod device;
mod enums;
mod error;
mod font;
mod image_surface;
#[cfg(any(feature = "png", feature = "dox"))]
mod image_surface_png;
mod matrices;
mod paths;
mod patterns;
mod recording_surface;
mod rectangle;
mod rectangle_int;
mod region;
mod surface;
#[cfg(any(feature = "xcb", feature = "dox"))]
mod xcb;

#[cfg(any(feature = "pdf", feature = "svg", feature = "ps", feature = "dox"))]
#[macro_use]
mod stream;
#[cfg(any(feature = "pdf", feature = "dox"))]
mod pdf;
#[cfg(any(feature = "ps", feature = "dox"))]
mod ps;
#[cfg(any(feature = "svg", feature = "dox"))]
mod svg;

#[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
mod quartz_surface;
#[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
pub use quartz_surface::QuartzSurface;

#[cfg(any(all(windows, feature = "win32-surface"), feature = "dox"))]
mod win32_surface;

#[cfg(any(all(windows, feature = "win32-surface"), feature = "dox"))]
pub use win32_surface::Win32Surface;
<commit_msg>Improve cairo library documentation<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # Cairo bindings
//!
//! This library contains safe Rust bindings for [Cairo](https://www.cairographics.org/).
//! It is a part of [Gtk-rs](http://gtk-rs.org/).
//!
//! ## Crate features
//!
//! ### Default-on features
//!
//! * **use_glib** - Use with [glib](https://gtk-rs.org/docs/glib/)
//!
//! ### Fileformat features
//!
//! * **png** - Reading and writing PNG images
//! * **pdf** - Rendering PDF documents
//! * **svg** - Rendering SVG documents
//! * **ps** - Rendering PostScript documents
//!
//! ### Cairo API version features
//!
//! * **v1_14** - Use Cairo 1.14 APIs
//! * **v1_16** - Use Cairo 1.16 APIs
//!
//! ### Documentation features
//!
//! * **embed-lgpl-docs** - Embed API docs locally
//! * **purge-lgpl-docs** - Remove API docs again (counterpart to `embed-lgpl-docs`)
//! * **dox** - Used to keep system dependent items in documentation
//!
//! ### X Window features
//!
//! * **xcb** - X Window System rendering using the XCB library
//! * **xlib** - X Window System rendering using XLib
//!
//! ### Windows API features
//!
//! * **win32-surface** - Microsoft Windows surface support

extern crate cairo_sys as ffi;
extern crate libc;

#[macro_use]
extern crate bitflags;

#[cfg(feature = "use_glib")]
#[macro_use]
extern crate glib;

#[cfg(feature = "use_glib")]
extern crate glib_sys as glib_ffi;

#[cfg(feature = "use_glib")]
extern crate gobject_sys as gobject_ffi;

#[cfg(test)]
extern crate tempfile;

// Helper macro for our GValue related trait impls
#[cfg(feature = "use_glib")]
macro_rules! gvalue_impl {
    ($name:ty, $ffi_name:ty, $get_type:expr) => {
        use glib;
        #[allow(unused_imports)]
        use glib::translate::*;
        use glib_ffi;
        use gobject_ffi;

        impl glib::types::StaticType for $name {
            fn static_type() -> glib::types::Type {
                unsafe { from_glib($get_type()) }
            }
        }

        impl<'a> glib::value::FromValueOptional<'a> for $name {
            unsafe fn from_value_optional(v: &'a glib::value::Value) -> Option<Self> {
                let ptr = gobject_ffi::g_value_get_boxed(v.to_glib_none().0);
                assert!(!ptr.is_null());
                from_glib_none(ptr as *mut $ffi_name)
            }
        }

        impl glib::value::SetValue for $name {
            unsafe fn set_value(v: &mut glib::value::Value, s: &Self) {
                gobject_ffi::g_value_set_boxed(
                    v.to_glib_none_mut().0,
                    s.to_glib_none().0 as glib_ffi::gpointer,
                );
            }
        }

        impl glib::value::SetValueOptional for $name {
            unsafe fn set_value_optional(v: &mut glib::value::Value, s: Option<&Self>) {
                if let Some(s) = s {
                    gobject_ffi::g_value_set_boxed(
                        v.to_glib_none_mut().0,
                        s.to_glib_none().0 as glib_ffi::gpointer,
                    );
                } else {
                    gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, ::std::ptr::null_mut());
                }
            }
        }
    };
}

pub use user_data::UserDataKey;

pub use context::{Context, RectangleList};

pub use paths::{Path, PathSegment, PathSegments};

pub use device::Device;

pub use enums::*;

pub use error::{BorrowError, IoError};

pub use patterns::{
    Gradient, LinearGradient, Mesh, Pattern, RadialGradient, SolidPattern, SurfacePattern,
};

pub use font::{
    FontExtents, FontFace, FontOptions, FontSlant, FontType, FontWeight, Glyph, ScaledFont,
    TextCluster, TextExtents,
};

pub use matrices::Matrix;

pub use recording_surface::RecordingSurface;
pub use rectangle::Rectangle;
pub use rectangle_int::RectangleInt;

pub use region::Region;

pub use surface::{MappedImageSurface, Surface};

pub use image_surface::{ImageSurface, ImageSurfaceData};

#[cfg(any(feature = "pdf", feature = "svg", feature = "ps", feature = "dox"))]
pub use stream::StreamWithError;

#[cfg(any(feature = "pdf", feature = "dox"))]
pub use pdf::PdfSurface;

#[cfg(any(feature = "ps", feature = "dox"))]
pub use ps::PsSurface;

#[cfg(any(feature = "svg", feature = "dox"))]
pub use svg::SvgSurface;

#[cfg(any(feature = "xcb", feature = "dox"))]
pub use xcb::{
    XCBConnection, XCBDrawable, XCBPixmap, XCBRenderPictFormInfo, XCBScreen, XCBSurface,
    XCBVisualType,
};

#[macro_use]
mod user_data;
mod constants;
pub use constants::*;
mod utils;
pub use utils::*;

mod context;
mod device;
mod enums;
mod error;
mod font;
mod image_surface;
#[cfg(any(feature = "png", feature = "dox"))]
mod image_surface_png;
mod matrices;
mod paths;
mod patterns;
mod recording_surface;
mod rectangle;
mod rectangle_int;
mod region;
mod surface;
#[cfg(any(feature = "xcb", feature = "dox"))]
mod xcb;

#[cfg(any(feature = "pdf", feature = "svg", feature = "ps", feature = "dox"))]
#[macro_use]
mod stream;
#[cfg(any(feature = "pdf", feature = "dox"))]
mod pdf;
#[cfg(any(feature = "ps", feature = "dox"))]
mod ps;
#[cfg(any(feature = "svg", feature = "dox"))]
mod svg;

#[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
mod quartz_surface;
#[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
pub use quartz_surface::QuartzSurface;

#[cfg(any(all(windows, feature = "win32-surface"), feature = "dox"))]
mod win32_surface;

#[cfg(any(all(windows, feature = "win32-surface"), feature = "dox"))]
pub use win32_surface::Win32Surface;
<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # **glib**, **gobject** and **gio** bindings for Rust
//!
//! This library contains
//!
//! - bindings to some essential GLib, GObject, GIO types and APIs,
//!
//! - common building blocks used in both handmade and machine generated
//! bindings to GTK+ and other GLib-based libraries.
//!
//! It is the foundation for higher level libraries with uniform Rusty (safe and
//! strongly typed) APIs. It avoids exposing GLib-specific data types where
//! possible and is not meant to provide comprehensive GLib bindings, which
//! would often amount to duplicating the Rust Standard Library or other utility
//! crates.
//!
//! The library is a work in progress: expect missing functionality and breaking
//! changes.
//!
//! # Dynamic typing
//!
//! Most types in the GLib family have type identifiers
//! ([`Type`](types/enum.Type.html)). Their corresponding Rust types implement
//! the [`StaticType`](types/trait.StaticType.html) trait.
//!
//! Dynamically typed [`Value`](value/index.html) can carry values of any `T:
//! StaticType`.
//!
//! # Errors
//!
//! Errors are represented by [`Error`](error/struct.Error.html), which can
//! carry values from various [error
//! domains](error/trait.ErrorDomain.html#implementors) (such as
//! [`FileError`](enum.FileError.html)).
//!
//! # Objects
//!
//! Each class and interface has a corresponding smart pointer struct
//! representing an instance of that type (e.g. `Object` for `GObject`,
//! `gtk::Widget` for `GtkWidget`). They are reference counted and feature
//! interior mutability similarly to Rust's `Rc<RefCell<T>>` idiom.
//! Consequently, cloning objects is cheap and their methods never require
//! mutable borrows. Two smart pointers are equal iff they point to the same
//! object.
//!
//! The root of the object hierarchy is [`Object`](object/struct.Object.html).
//! Inheritance and subtyping is denoted with the [`IsA`](object/trait.IsA.html)
//! marker trait. The [`Cast`](object/trait.Cast.html) trait enables upcasting
//! and downcasting.
//!
//! Interfaces and non-leaf classes also have corresponding traits (e.g.
//! `ObjectExt` and `gtk::WidgetExt`), which are blanketly implemented for all
//! their subtypes.
//!
//! # Under the hood
//!
//! GLib-based libraries largely operate on pointers to various boxed or
//! reference counted structures so the bindings have to implement corresponding
//! smart pointers (wrappers), which encapsulate resource management and safety
//! checks. Such wrappers are defined via the
//! [`glib_wrapper!`](macro.glib_wrapper!.html) macro, which uses abstractions
//! defined in the [`wrapper`](wrapper/index.html), [`boxed`](boxed/index.html),
//! [`shared`](shared/index.html) and [`object`](object/index.html) modules.
//!
//! The [`translate`](translate/index.html) module defines and partly implements
//! conversions between high level Rust types (including the aforementioned
//! wrappers) and their FFI counterparts.

extern crate libc;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate gio_sys as gio_ffi;

use libc::c_char;

pub use self::app_info::AppInfo;
pub use self::glib_container::GlibContainer;
pub use self::error::Error;
pub use file_error::FileError;
pub use self::object::{
    Cast,
    IsA,
    Object,
};
pub use self::permission::Permission;
pub use self::source::{Continue, idle_add, timeout_add, timeout_add_seconds};
pub use self::traits::FFIGObject;
pub use types::Type;
pub use value::{TypedValue, Value};
pub use self::date::{TimeVal, Time, Date, Year, Month, Weekday, Day};

#[macro_use]
pub mod wrapper;
#[macro_use]
pub mod boxed;
#[macro_use]
pub mod shared;
#[macro_use]
pub mod object;

mod app_info;
pub mod glib_container;
pub mod error;
mod file_error;
mod permission;
pub mod signal;
pub mod source;
pub mod traits;
pub mod translate;
pub mod value;

pub mod types;
pub mod date;

pub fn to_gboolean(b: bool) -> glib_ffi::gboolean {
    match b {
        true => glib_ffi::GTRUE,
        false => glib_ffi::GFALSE
    }
}

pub fn to_bool(b: glib_ffi::gboolean) -> bool {
    b != glib_ffi::GFALSE
}

// An opaque structure used as the base of all interface types.
pub struct TypeInterface;

// An opaque structure used as the base of all type instances.
pub struct TypeInstance;

// An opaque structure used as the base of all classes.
pub struct TypeClass;

//FIXME: Check if this is actually correct (maybe not since ParamFlags is deprecated)
#[derive(Clone, Copy)]
pub enum ParamFlags{
    Readable,
    Writable,
    ReadWrite,
    Construct,
    ConstructOnly,
    LaxValidation,
    StaticName,
    Private,
    StaticNick,
    StaticBlurb,
    Deprecated
}

#[repr(C)]
pub struct ParamSpec {
    g_type_instance: TypeInstance,
    name: *mut c_char,
    flags: ParamFlags,
    value_type: glib_ffi::GType,
    owner_type: glib_ffi::GType,
}
<commit_msg>Adjust type and value reexports<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # **glib**, **gobject** and **gio** bindings for Rust
//!
//! This library contains
//!
//! - bindings to some essential GLib, GObject, GIO types and APIs,
//!
//! - common building blocks used in both handmade and machine generated
//! bindings to GTK+ and other GLib-based libraries.
//!
//! It is the foundation for higher level libraries with uniform Rusty (safe and
//! strongly typed) APIs. It avoids exposing GLib-specific data types where
//! possible and is not meant to provide comprehensive GLib bindings, which
//! would often amount to duplicating the Rust Standard Library or other utility
//! crates.
//!
//! The library is a work in progress: expect missing functionality and breaking
//! changes.
//!
//! # Dynamic typing
//!
//! Most types in the GLib family have type identifiers
//! ([`Type`](types/enum.Type.html)). Their corresponding Rust types implement
//! the [`StaticType`](types/trait.StaticType.html) trait.
//!
//! Dynamically typed [`Value`](value/index.html) can carry values of any `T:
//! StaticType`.
//!
//! # Errors
//!
//! Errors are represented by [`Error`](error/struct.Error.html), which can
//! carry values from various [error
//! domains](error/trait.ErrorDomain.html#implementors) (such as
//! [`FileError`](enum.FileError.html)).
//!
//! # Objects
//!
//! Each class and interface has a corresponding smart pointer struct
//! representing an instance of that type (e.g. `Object` for `GObject`,
//! `gtk::Widget` for `GtkWidget`). They are reference counted and feature
//! interior mutability similarly to Rust's `Rc<RefCell<T>>` idiom.
//! Consequently, cloning objects is cheap and their methods never require
//! mutable borrows. Two smart pointers are equal iff they point to the same
//! object.
//!
//! The root of the object hierarchy is [`Object`](object/struct.Object.html).
//! Inheritance and subtyping is denoted with the [`IsA`](object/trait.IsA.html)
//! marker trait. The [`Cast`](object/trait.Cast.html) trait enables upcasting
//! and downcasting.
//!
//! Interfaces and non-leaf classes also have corresponding traits (e.g.
//! `ObjectExt` and `gtk::WidgetExt`), which are blanketly implemented for all
//! their subtypes.
//!
//! # Under the hood
//!
//! GLib-based libraries largely operate on pointers to various boxed or
//! reference counted structures so the bindings have to implement corresponding
//! smart pointers (wrappers), which encapsulate resource management and safety
//! checks. Such wrappers are defined via the
//! [`glib_wrapper!`](macro.glib_wrapper!.html) macro, which uses abstractions
//! defined in the [`wrapper`](wrapper/index.html), [`boxed`](boxed/index.html),
//! [`shared`](shared/index.html) and [`object`](object/index.html) modules.
//!
//! The [`translate`](translate/index.html) module defines and partly implements
//! conversions between high level Rust types (including the aforementioned
//! wrappers) and their FFI counterparts.

extern crate libc;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate gio_sys as gio_ffi;

use libc::c_char;

pub use self::app_info::AppInfo;
pub use self::glib_container::GlibContainer;
pub use self::error::Error;
pub use file_error::FileError;
pub use self::object::{
    Cast,
    IsA,
    Object,
};
pub use self::permission::Permission;
pub use self::source::{Continue, idle_add, timeout_add, timeout_add_seconds};
pub use self::traits::FFIGObject;
pub use types::{
    StaticType,
    Type,
};
pub use value::{
    ToValue,
    TypedValue,
    Value,
};
pub use self::date::{TimeVal, Time, Date, Year, Month, Weekday, Day};

#[macro_use]
pub mod wrapper;
#[macro_use]
pub mod boxed;
#[macro_use]
pub mod shared;
#[macro_use]
pub mod object;

mod app_info;
pub mod glib_container;
pub mod error;
mod file_error;
mod permission;
pub mod signal;
pub mod source;
pub mod traits;
pub mod translate;
pub mod value;

pub mod types;
pub mod date;

pub fn to_gboolean(b: bool) -> glib_ffi::gboolean {
    match b {
        true => glib_ffi::GTRUE,
        false => glib_ffi::GFALSE
    }
}

pub fn to_bool(b: glib_ffi::gboolean) -> bool {
    b != glib_ffi::GFALSE
}

// An opaque structure used as the base of all interface types.
pub struct TypeInterface;

// An opaque structure used as the base of all type instances.
pub struct TypeInstance;

// An opaque structure used as the base of all classes.
pub struct TypeClass;

//FIXME: Check if this is actually correct (maybe not since ParamFlags is deprecated)
#[derive(Clone, Copy)]
pub enum ParamFlags{
    Readable,
    Writable,
    ReadWrite,
    Construct,
    ConstructOnly,
    LaxValidation,
    StaticName,
    Private,
    StaticNick,
    StaticBlurb,
    Deprecated
}

#[repr(C)]
pub struct ParamSpec {
    g_type_instance: TypeInstance,
    name: *mut c_char,
    flags: ParamFlags,
    value_type: glib_ffi::GType,
    owner_type: glib_ffi::GType,
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;

use std::net::{SocketAddr, ToSocketAddrs};
use std::fs::File;
use std::io::Write;
use serde::de::{Error, Type};
use serde_json::value::Value;

#[derive(Debug)]
pub struct ChatUser {
	pub name: String,
	pub poster: SocketAddr,
}

#[derive(Debug)]
pub struct ChatMessage {
	pub sender: ChatUser,
	pub value: String,
}

impl ChatUser {
	//TODO: look it up somewhere, maybe?
	/// Creates a user defined by the supplied arguments
	pub fn get<Addr: ToSocketAddrs>(name: String, poster: Addr) -> ChatUser {
		ChatUser{
			name: name,
			poster: poster.to_socket_addrs().ok().unwrap().next().unwrap(),  //TODO: This should probably be handled, eh?
		}
	}

	pub fn to_json(&self) -> serde_json::Value {
		serde_json::builder::ObjectBuilder::new().insert("name", &self.name).insert("poster", self.poster.to_string()).unwrap()
	}

	pub fn from_json(json: serde_json::Value) -> Result<ChatUser, serde_json::error::Error> {
		match json {
			Value::Object(map) => {
				let name =
					match map.get("name") {
						Some(name) =>
							match name {
								&Value::String(ref name) => name,
								_ => return Err(serde_json::error::Error::type_mismatch(Type::String)),
							},
						None => return Err(serde_json::error::Error::missing_field("Missing \"name\"")),
					};
				let poster =
					match map.get("poster") {
						Some(poster) =>
							match poster {
								&Value::String(ref poster) => poster,
								_ => return Err(serde_json::error::Error::type_mismatch(Type::String)),
							},
						None => return Err(serde_json::error::Error::missing_field("Missing \"poster\"")),
					};

				Ok(ChatUser::get(name.clone(), &poster[..]))
			},
			_ => Err(serde_json::error::Error::type_mismatch(Type::Struct)),
		}
	}
}

#[test]
fn asdf() {
	let cu = ChatUser::get("keke".to_string(), "127.0.0.1:50030");
	let jsoned = serde_json::to_string(&cu.to_json());
	let _ = File::create("lol").ok().unwrap().write_fmt(format_args!("{:?}", jsoned));
	let decoded = ChatUser::from_json(serde_json::from_str(&*&jsoned.ok().unwrap()).ok().unwrap());
	let _ = File::create("kek").ok().unwrap().write_fmt(format_args!("{:?}", decoded));
}
<commit_msg>Simplify long namespace resolutions<commit_after>extern crate serde;
extern crate serde_json;

use std::net::{SocketAddr, ToSocketAddrs};
use std::fs::File;
use std::io::Write;
use serde::de::{Error, Type};
use serde_json::value::Value;
use serde_json::builder::ObjectBuilder;
use serde_json::error::Error as JsonError;

#[derive(Debug)]
pub struct ChatUser {
	pub name: String,
	pub poster: SocketAddr,
}

#[derive(Debug)]
pub struct ChatMessage {
	pub sender: ChatUser,
	pub value: String,
}

impl ChatUser {
	//TODO: look it up somewhere, maybe?
	/// Creates a user defined by the supplied arguments
	pub fn get<Addr: ToSocketAddrs>(name: String, poster: Addr) -> ChatUser {
		ChatUser{
			name: name,
			poster: poster.to_socket_addrs().ok().unwrap().next().unwrap(),  //TODO: This should probably be handled, eh?
		}
	}

	pub fn to_json(&self) -> Value {
		ObjectBuilder::new().insert("name", &self.name).insert("poster", self.poster.to_string()).unwrap()
	}

	pub fn from_json(json: Value) -> Result<ChatUser, JsonError> {
		match json {
			Value::Object(map) => {
				let name =
					match map.get("name") {
						Some(name) =>
							match name {
								&Value::String(ref name) => name,
								_ => return Err(JsonError::type_mismatch(Type::String)),
							},
						None => return Err(JsonError::missing_field("Missing \"name\"")),
					};
				let poster =
					match map.get("poster") {
						Some(poster) =>
							match poster {
								&Value::String(ref poster) => poster,
								_ => return Err(JsonError::type_mismatch(Type::String)),
							},
						None => return Err(JsonError::missing_field("Missing \"poster\"")),
					};

				Ok(ChatUser::get(name.clone(), &poster[..]))
			},
			_ => Err(JsonError::type_mismatch(Type::Struct)),
		}
	}
}

#[test]
fn asdf() {
	let cu = ChatUser::get("keke".to_string(), "127.0.0.1:50030");
	let jsoned = serde_json::to_string(&cu.to_json());
	let _ = File::create("lol").ok().unwrap().write_fmt(format_args!("{:?}", jsoned));
	let decoded = ChatUser::from_json(serde_json::from_str(&*&jsoned.ok().unwrap()).ok().unwrap());
	let _ = File::create("kek").ok().unwrap().write_fmt(format_args!("{:?}", decoded));
}
<|endoftext|>


<commit_before>pub use self::image_pub::CifarImage;
pub use self::dataset::CifarDataset;
mod image;
pub mod image_pub;
pub mod dataset;
<commit_msg>pub mod change<commit_after>pub use self::image_pub::CifarImage;
pub use self::dataset::CifarDataset;
mod image;
mod image_pub;
mod dataset;
<|endoftext|>


<commit_before>//! A contiguous region of bytes, useful for I/O operations.
//!
//! An Iobuf consists of:
//!
//!   - buffer
//!   - limits (a subrange of the buffer)
//!   - window (a subrange of the limits)
//!
//! All iobuf operations are restricted to operate within the limits. Initially,
//! the window of an Iobuf is identical to the limits. If you have an `&mut` to
//! an Iobuf, you may change the window and limits. If you only have a `&`, you
//! may not. Similarly, if you have a `RWIobuf`, you may modify the data in the
//! buffer. If you have a `ROIobuf`, you may not.
//!
//! The limits can be `narrow`ed, but never widened. The window may be set to
//! any arbitrary subrange of the limits.
//!
//! Iobufs are cheap to `clone`, since the buffers are refcounted. Use this to
//! construct multiple views into the same data.
//!
//! To keep the struct small (24 bytes!), the maximum size of an Iobuf is 2 GB.
//! Please let me know if you need more than this. I have never before seen a
//! use case for Iobufs larger than 2 GB, and it gives us a 40% smaller struct
//! compared to support INT64_MAX bytes. The improved size allows much better
//! register/cache usage and faster moves, both of which are critical for
//! performance.
//!
//! Although this library is designed for efficiency, and hence gives you lots
//! of ways to omit bounds checks, that does not mean it's recommended you do.
//! They merely provide a way for you to manually bounds check a whole bunch
//! of data at once (with `check_range`), and then `peek` or `poke` out the data
//! you want. See the documentation for `check_range` for an example.
//!
//! To repeat: Do not omit bounds checks unless you've checked _very_ carefully
//! that they are redundant. This can cause terrifying security issues.

#![license = "MIT"]

#![feature(phase)]
#![feature(unsafe_destructor)]
#![no_std]

                                   extern crate alloc;
                                   extern crate collections;
             #[phase(plugin,link)] extern crate core;
#[cfg(test)] #[phase(plugin,link)] extern crate std;
#[cfg(test)]                       extern crate native;
#[cfg(test)]                       extern crate test;

pub use raw::Prim;
pub use iobuf::Iobuf;
pub use impls::{ROIobuf, RWIobuf};
pub use ringbuf::IORingbuf;
pub use bufspan::{BufSpan, SpanIter, SpanMoveIter};

// https://github.com/rust-lang/rust/issues/18491#issuecomment-61293267
#[cfg(not(test))]
mod std { pub use core::fmt; }

mod raw;
mod iobuf;
mod impls;
mod ringbuf;
mod bufspan;
<commit_msg>pub ByteIter<commit_after>//! A contiguous region of bytes, useful for I/O operations.
//!
//! An Iobuf consists of:
//!
//!   - buffer
//!   - limits (a subrange of the buffer)
//!   - window (a subrange of the limits)
//!
//! All iobuf operations are restricted to operate within the limits. Initially,
//! the window of an Iobuf is identical to the limits. If you have an `&mut` to
//! an Iobuf, you may change the window and limits. If you only have a `&`, you
//! may not. Similarly, if you have a `RWIobuf`, you may modify the data in the
//! buffer. If you have a `ROIobuf`, you may not.
//!
//! The limits can be `narrow`ed, but never widened. The window may be set to
//! any arbitrary subrange of the limits.
//!
//! Iobufs are cheap to `clone`, since the buffers are refcounted. Use this to
//! construct multiple views into the same data.
//!
//! To keep the struct small (24 bytes!), the maximum size of an Iobuf is 2 GB.
//! Please let me know if you need more than this. I have never before seen a
//! use case for Iobufs larger than 2 GB, and it gives us a 40% smaller struct
//! compared to support INT64_MAX bytes. The improved size allows much better
//! register/cache usage and faster moves, both of which are critical for
//! performance.
//!
//! Although this library is designed for efficiency, and hence gives you lots
//! of ways to omit bounds checks, that does not mean it's recommended you do.
//! They merely provide a way for you to manually bounds check a whole bunch
//! of data at once (with `check_range`), and then `peek` or `poke` out the data
//! you want. See the documentation for `check_range` for an example.
//!
//! To repeat: Do not omit bounds checks unless you've checked _very_ carefully
//! that they are redundant. This can cause terrifying security issues.

#![license = "MIT"]

#![feature(phase)]
#![feature(unsafe_destructor)]
#![no_std]

                                   extern crate alloc;
                                   extern crate collections;
             #[phase(plugin,link)] extern crate core;
#[cfg(test)] #[phase(plugin,link)] extern crate std;
#[cfg(test)]                       extern crate native;
#[cfg(test)]                       extern crate test;

pub use raw::Prim;
pub use iobuf::Iobuf;
pub use impls::{ROIobuf, RWIobuf};
pub use ringbuf::IORingbuf;
pub use bufspan::{BufSpan, ByteIter, SpanIter, SpanMoveIter};

// https://github.com/rust-lang/rust/issues/18491#issuecomment-61293267
#[cfg(not(test))]
mod std { pub use core::fmt; }

mod raw;
mod iobuf;
mod impls;
mod ringbuf;
mod bufspan;
<|endoftext|>


<commit_before>#![feature(alloc)]
#![feature(collections)]
#![feature(core)]
#![feature(hash)]

#![feature(unsafe_destructor)]

extern crate alloc;
extern crate collections;
extern crate core;

use collections::vec;
use core::hash::{self, Hash};
use core::iter::{self, repeat};
use core::mem;
use core::num::Int;
use core::ptr;
use core::slice;

use unadorned::{Unadorned, Extent};

mod unadorned;

#[unsafe_no_drop_flag]
pub struct Soa2<A, B> {
    d0: Unadorned<A>,
    d1: Unadorned<B>,
    e:  Extent,
}

impl<A, B> Soa2<A, B> {
    pub fn new() -> Soa2<A, B> {
        unsafe {
            let (d0, d0u) = Unadorned::new();
            let (d1, d1u) = Unadorned::new();

            let e = unadorned::new_update(&[d0u, d1u]);

            Soa2 { d0: d0, d1: d1, e: e }
        }
    }

    #[inline]
    fn is_boring(&self) -> bool {
        self.d0.is_boring() && self.d1.is_boring()
    }

    pub fn with_capacity(capacity: usize) -> Soa2<A, B> {
        unsafe {
            let (d0, d0u) = Unadorned::with_capacity(capacity);
            let (d1, d1u) = Unadorned::with_capacity(capacity);

            let is_boring = mem::size_of::<A>() == 0 && mem::size_of::<B>() == 0;

            let e = unadorned::with_capacity_update(&[d0u, d1u], is_boring, capacity);

            Soa2 { d0: d0, d1: d1, e: e }
        }
    }

    pub unsafe fn from_raw_parts(
        ptra: *mut A, ptrb: *mut B, len: usize, cap: usize) -> Soa2<A, B> {
        let (d0, d0u) = Unadorned::from_raw_parts(ptra);
        let (d1, d1u) = Unadorned::from_raw_parts(ptrb);

        let e = unadorned::from_raw_parts_update(&[d0u, d1u], len, cap);

        Soa2 { d0: d0, d1: d1, e: e }
    }

    #[inline]
    pub unsafe fn from_raw_bufs(ptra: *const A, ptrb: *const B, elts: usize) -> Soa2<A, B> {
        let (d0, d0u) = Unadorned::from_raw_bufs(ptra, elts);
        let (d1, d1u) = Unadorned::from_raw_bufs(ptrb, elts);

        let e = unadorned::from_raw_bufs_update(&[d0u, d1u], elts);

        Soa2 { d0: d0, d1: d1, e: e }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.e.len
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    #[inline]
    pub unsafe fn set_len(&mut self, len: usize) {
        self.e.len = len;
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.e.cap
    }

    pub fn reserve(&mut self, additional: usize) {
        let space =
            match unadorned::calc_reserve_space(&self.e, additional) {
                None        => return,
                Some(space) => space,
            };

        unsafe {
            let d0u = self.d0.reserve(&self.e, &space);
            let d1u = self.d1.reserve(&self.e, &space);

            unadorned::reserve_update(&[d0u, d1u], space, &mut self.e);
        }
    }

    pub fn reserve_exact(&mut self, additional: usize) {
        let space =
            match unadorned::calc_reserve_exact_space(&self.e, additional) {
                None        => return,
                Some(space) => space,
            };

        unsafe {
            let d0u = self.d0.reserve(&self.e, &space);
            let d1u = self.d1.reserve(&self.e, &space);

            unadorned::reserve_update(&[d0u, d1u], space, &mut self.e);
        }
    }

    pub fn shrink_to_fit(&mut self) {
        if self.is_boring() { return }

        unsafe {
            let d0u = self.d0.shrink_to_fit(&self.e);
            let d1u = self.d1.shrink_to_fit(&self.e);

            unadorned::shrink_to_fit_update(&[d0u, d1u], &mut self.e);
        }
    }

    pub fn truncate(&mut self, len: usize) {
        if self.is_boring() { return }

        unsafe {
            let d0u = self.d0.truncate(len, &self.e);
            let d1u = self.d1.truncate(len, &self.e);

            unadorned::truncate_update(&[d0u, d1u], len, &mut self.e);
        }
    }

    #[inline]
    pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [A], &'a mut [B]) {
        unsafe {
            let len = self.e.len;
            (self.d0.as_mut_slice(len), self.d1.as_mut_slice(len))
        }
    }

    #[inline]
    pub fn as_slices<'a>(&'a self) -> (&'a [A], &'a [B]) {
        unsafe {
            let len = self.e.len;
            (self.d0.as_slice(len), self.d1.as_slice(len))
        }
    }

    #[inline]
    pub fn iter(&self) -> iter::Zip<slice::Iter<A>, slice::Iter<B>> {
        let (d0, d1) = self.as_slices();
        d0.iter().zip(d1.iter())
    }

    #[inline]
    pub fn iter_mut(&mut self) -> iter::Zip<slice::IterMut<A>, slice::IterMut<B>> {
        let (d0, d1) = self.as_mut_slices();
        d0.iter_mut().zip(d1.iter_mut())
    }

    #[inline]
    pub fn into_iter(mut self) -> iter::Zip<vec::IntoIter<A>, vec::IntoIter<B>> {
        unsafe {
            let e_copy = self.e;
            self.e.cap = 0; // Will skip the drop. into_iter will handle it.
            self.d0.shallow_copy().into_iter(&e_copy).zip(self.d1.shallow_copy().into_iter(&e_copy))
        }
    }

    #[inline]
    pub fn swap_remove(&mut self, index: usize) -> (A, B) {
        let length = self.e.len;
        {
            let (d0, d1) = self.as_mut_slices();
            d0.swap(index, length - 1);
            d1.swap(index, length - 1);
        }
        self.pop().unwrap()
    }

    pub fn insert(&mut self, index: usize, element: (A, B)) {
        unsafe {
            assert!(index < self.e.len);

            let space = unadorned::calc_reserve_space(&self.e, 1);

            let d0u = self.d0.insert(index, element.0, &self.e, &space);
            let d1u = self.d1.insert(index, element.1, &self.e, &space);

            unadorned::insert_update(&[d0u, d1u], space, &mut self.e);
        }
    }

    pub fn remove(&mut self, index: usize) -> (A, B) {
        unsafe {
            let (x0, d0u) = self.d0.remove(index, &self.e);
            let (x1, d1u) = self.d1.remove(index, &self.e);

            unadorned::remove_update(&[d0u, d1u], &mut self.e);
            (x0, x1)
        }
    }

    pub fn retain<F>(&mut self, mut f: F) where F: FnMut((&A, &B)) -> bool {
        let len = self.len();
        let mut del = 0us;

        {
            let (d0, d1) = self.as_mut_slices();

            for i in range(0us, len) {
                if !f((&d0[i], &d1[i])) {
                    del += 1;
                } else if del > 0 {
                    d0.swap(i-del, i);
                    d1.swap(i-del, i);
                }
            }
        }

        self.truncate(len - del);
    }

    #[inline]
    pub fn push(&mut self, value: (A, B)) {
        if self.is_boring() {
            // zero-size types consume no memory, so we can't rely on the
            // address space running out
            self.e.len = self.e.len.checked_add(1).expect("length overflow");
            unsafe { mem::forget(value) }
            return
        }

        unsafe {
            let d0u = self.d0.push(value.0, &self.e);
            let d1u = self.d1.push(value.1, &self.e);

            unadorned::push_update(&[d0u, d1u], &mut self.e);
        }
    }

    #[inline]
    pub fn pop(&mut self) -> Option<(A, B)> {
        if self.e.len == 0 {
            None
        } else {
            unsafe {
                self.e.len -= 1;
                let len = self.e.len;

                let (d0, d1) = self.as_mut_slices();

                Some((ptr::read(d0.get_unchecked(len)),
                      ptr::read(d1.get_unchecked(len))))
            }
        }
    }

    #[inline]
    pub fn append(&mut self, other: &mut Self) {
        if self.is_boring() {
            // zero-size types consume no memory, so we can't rely on the address
            // space running out
            self.e.len = self.e.len.checked_add(other.len()).expect("length overflow");
            other.e.len = 0;
            return;
        }

        unsafe {
            let space = unadorned::calc_reserve_space(&self.e, 1);

            let d0u = self.d0.append(&self.e, &other.d0, &other.e, &space);
            let d1u = self.d1.append(&self.e, &other.d1, &other.e, &space);

            unadorned::append_update(&[d0u, d1u], &mut self.e, &mut other.e, space);
        }
    }

    // TODO: drain

    #[inline]
    pub fn clear(&mut self) {
        self.truncate(0);
    }

    // TODO: map_in_place

    pub fn extend<I0, I1>(&mut self, i0: I0, i1: I1)
        where I0: Iterator<Item=A>, I1: Iterator<Item=B> {
        unsafe {
            let d0u = self.d0.extend(&self.e, i0);
            let d1u = self.d1.extend(&self.e, i1);

            unadorned::extend_update(&[d0u, d1u], &mut self.e);
        }
    }

    // TODO: dedup
}

impl<A: Clone, B: Clone> Soa2<A, B> {
    #[inline]
    pub fn resize(&mut self, new_len: usize, value: (A, B)) {
        let len = self.len();

        if new_len > len {
            self.extend(repeat(value.0).take(new_len - len), repeat(value.1).take(new_len - len));
        } else {
            self.truncate(new_len);
        }
    }

    #[inline]
    pub fn push_all(&mut self, x0: &[A], x1: &[B]) {
        unsafe {
            assert_eq!(x0.len(), x1.len());

            let space = unadorned::calc_reserve_space(&self.e, x0.len());

            let d0u = self.d0.push_all(x0, &self.e, &space);
            let d1u = self.d1.push_all(x1, &self.e, &space);

            unadorned::push_all_update(&[d0u, d1u], &mut self.e, x0.len(), space);
        }
    }
}

impl<A: Clone, B: Clone> Clone for Soa2<A, B> {
    #[inline]
    fn clone(&self) -> Soa2<A, B> {
        let mut ret = Soa2::new();
        let (d0, d1) = self.as_slices();
        ret.push_all(d0, d1);
        ret
    }

    fn clone_from(&mut self, other: &Soa2<A, B>) {
        // TODO: cleanup

        if self.len() > other.len() {
            self.truncate(other.len());
        }

        let (od0, od1) = other.as_slices();

        let (s0, s1) = {
            let (sd0, sd1) = self.as_mut_slices();

            for (place, thing) in sd0.iter_mut().zip(od0.iter()) {
                place.clone_from(thing);
            }

            for (place, thing) in sd1.iter_mut().zip(od1.iter()) {
                place.clone_from(thing);
            }

            let s0 = &od0[sd0.len()..];
            let s1 = &od1[sd1.len()..];

            (s0, s1)
        };

        self.push_all(s0, s1);
    }
}

impl<S: hash::Writer + hash::Hasher, A: Hash<S>, B: Hash<S>> Hash<S> for Soa2<A, B> {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slices().hash(state)
    }
}

#[unsafe_destructor]
impl<A, B> Drop for Soa2<A, B> {
    #[inline]
    fn drop(&mut self) {
        if self.e.cap != 0 {
            unsafe {
                self.d0.drop(&self.e);
                self.d1.drop(&self.e);
            }
        }
    }
}
<commit_msg>added from_iters<commit_after>#![feature(alloc)]
#![feature(collections)]
#![feature(core)]
#![feature(hash)]

#![feature(unsafe_destructor)]

extern crate alloc;
extern crate collections;
extern crate core;

use collections::vec;
use core::hash::{self, Hash};
use core::iter::{self, repeat};
use core::mem;
use core::num::Int;
use core::ptr;
use core::slice;

use unadorned::{Unadorned, Extent};

mod unadorned;

#[unsafe_no_drop_flag]
pub struct Soa2<A, B> {
    d0: Unadorned<A>,
    d1: Unadorned<B>,
    e:  Extent,
}

impl<A, B> Soa2<A, B> {
    pub fn new() -> Soa2<A, B> {
        unsafe {
            let (d0, d0u) = Unadorned::new();
            let (d1, d1u) = Unadorned::new();

            let e = unadorned::new_update(&[d0u, d1u]);

            Soa2 { d0: d0, d1: d1, e: e }
        }
    }

    #[inline]
    fn is_boring(&self) -> bool {
        self.d0.is_boring() && self.d1.is_boring()
    }

    pub fn with_capacity(capacity: usize) -> Soa2<A, B> {
        unsafe {
            let (d0, d0u) = Unadorned::with_capacity(capacity);
            let (d1, d1u) = Unadorned::with_capacity(capacity);

            let is_boring = mem::size_of::<A>() == 0 && mem::size_of::<B>() == 0;

            let e = unadorned::with_capacity_update(&[d0u, d1u], is_boring, capacity);

            Soa2 { d0: d0, d1: d1, e: e }
        }
    }

    pub unsafe fn from_raw_parts(
        ptra: *mut A, ptrb: *mut B, len: usize, cap: usize) -> Soa2<A, B> {
        let (d0, d0u) = Unadorned::from_raw_parts(ptra);
        let (d1, d1u) = Unadorned::from_raw_parts(ptrb);

        let e = unadorned::from_raw_parts_update(&[d0u, d1u], len, cap);

        Soa2 { d0: d0, d1: d1, e: e }
    }

    #[inline]
    pub unsafe fn from_raw_bufs(ptra: *const A, ptrb: *const B, elts: usize) -> Soa2<A, B> {
        let (d0, d0u) = Unadorned::from_raw_bufs(ptra, elts);
        let (d1, d1u) = Unadorned::from_raw_bufs(ptrb, elts);

        let e = unadorned::from_raw_bufs_update(&[d0u, d1u], elts);

        Soa2 { d0: d0, d1: d1, e: e }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.e.len
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    #[inline]
    pub unsafe fn set_len(&mut self, len: usize) {
        self.e.len = len;
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.e.cap
    }

    pub fn reserve(&mut self, additional: usize) {
        let space =
            match unadorned::calc_reserve_space(&self.e, additional) {
                None        => return,
                Some(space) => space,
            };

        unsafe {
            let d0u = self.d0.reserve(&self.e, &space);
            let d1u = self.d1.reserve(&self.e, &space);

            unadorned::reserve_update(&[d0u, d1u], space, &mut self.e);
        }
    }

    pub fn reserve_exact(&mut self, additional: usize) {
        let space =
            match unadorned::calc_reserve_exact_space(&self.e, additional) {
                None        => return,
                Some(space) => space,
            };

        unsafe {
            let d0u = self.d0.reserve(&self.e, &space);
            let d1u = self.d1.reserve(&self.e, &space);

            unadorned::reserve_update(&[d0u, d1u], space, &mut self.e);
        }
    }

    pub fn shrink_to_fit(&mut self) {
        if self.is_boring() { return }

        unsafe {
            let d0u = self.d0.shrink_to_fit(&self.e);
            let d1u = self.d1.shrink_to_fit(&self.e);

            unadorned::shrink_to_fit_update(&[d0u, d1u], &mut self.e);
        }
    }

    pub fn truncate(&mut self, len: usize) {
        if self.is_boring() { return }

        unsafe {
            let d0u = self.d0.truncate(len, &self.e);
            let d1u = self.d1.truncate(len, &self.e);

            unadorned::truncate_update(&[d0u, d1u], len, &mut self.e);
        }
    }

    #[inline]
    pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [A], &'a mut [B]) {
        unsafe {
            let len = self.e.len;
            (self.d0.as_mut_slice(len), self.d1.as_mut_slice(len))
        }
    }

    #[inline]
    pub fn as_slices<'a>(&'a self) -> (&'a [A], &'a [B]) {
        unsafe {
            let len = self.e.len;
            (self.d0.as_slice(len), self.d1.as_slice(len))
        }
    }

    #[inline]
    pub fn iter(&self) -> iter::Zip<slice::Iter<A>, slice::Iter<B>> {
        let (d0, d1) = self.as_slices();
        d0.iter().zip(d1.iter())
    }

    #[inline]
    pub fn iter_mut(&mut self) -> iter::Zip<slice::IterMut<A>, slice::IterMut<B>> {
        let (d0, d1) = self.as_mut_slices();
        d0.iter_mut().zip(d1.iter_mut())
    }

    #[inline]
    pub fn into_iter(mut self) -> iter::Zip<vec::IntoIter<A>, vec::IntoIter<B>> {
        unsafe {
            let e_copy = self.e;
            self.e.cap = 0; // Will skip the drop. into_iter will handle it.
            self.d0.shallow_copy().into_iter(&e_copy).zip(self.d1.shallow_copy().into_iter(&e_copy))
        }
    }

    #[inline]
    pub fn swap_remove(&mut self, index: usize) -> (A, B) {
        let length = self.e.len;
        {
            let (d0, d1) = self.as_mut_slices();
            d0.swap(index, length - 1);
            d1.swap(index, length - 1);
        }
        self.pop().unwrap()
    }

    pub fn insert(&mut self, index: usize, element: (A, B)) {
        unsafe {
            assert!(index < self.e.len);

            let space = unadorned::calc_reserve_space(&self.e, 1);

            let d0u = self.d0.insert(index, element.0, &self.e, &space);
            let d1u = self.d1.insert(index, element.1, &self.e, &space);

            unadorned::insert_update(&[d0u, d1u], space, &mut self.e);
        }
    }

    pub fn remove(&mut self, index: usize) -> (A, B) {
        unsafe {
            let (x0, d0u) = self.d0.remove(index, &self.e);
            let (x1, d1u) = self.d1.remove(index, &self.e);

            unadorned::remove_update(&[d0u, d1u], &mut self.e);
            (x0, x1)
        }
    }

    pub fn retain<F>(&mut self, mut f: F) where F: FnMut((&A, &B)) -> bool {
        let len = self.len();
        let mut del = 0us;

        {
            let (d0, d1) = self.as_mut_slices();

            for i in range(0us, len) {
                if !f((&d0[i], &d1[i])) {
                    del += 1;
                } else if del > 0 {
                    d0.swap(i-del, i);
                    d1.swap(i-del, i);
                }
            }
        }

        self.truncate(len - del);
    }

    #[inline]
    pub fn push(&mut self, value: (A, B)) {
        if self.is_boring() {
            // zero-size types consume no memory, so we can't rely on the
            // address space running out
            self.e.len = self.e.len.checked_add(1).expect("length overflow");
            unsafe { mem::forget(value) }
            return
        }

        unsafe {
            let d0u = self.d0.push(value.0, &self.e);
            let d1u = self.d1.push(value.1, &self.e);

            unadorned::push_update(&[d0u, d1u], &mut self.e);
        }
    }

    #[inline]
    pub fn pop(&mut self) -> Option<(A, B)> {
        if self.e.len == 0 {
            None
        } else {
            unsafe {
                self.e.len -= 1;
                let len = self.e.len;

                let (d0, d1) = self.as_mut_slices();

                Some((ptr::read(d0.get_unchecked(len)),
                      ptr::read(d1.get_unchecked(len))))
            }
        }
    }

    #[inline]
    pub fn append(&mut self, other: &mut Self) {
        if self.is_boring() {
            // zero-size types consume no memory, so we can't rely on the address
            // space running out
            self.e.len = self.e.len.checked_add(other.len()).expect("length overflow");
            other.e.len = 0;
            return;
        }

        unsafe {
            let space = unadorned::calc_reserve_space(&self.e, 1);

            let d0u = self.d0.append(&self.e, &other.d0, &other.e, &space);
            let d1u = self.d1.append(&self.e, &other.d1, &other.e, &space);

            unadorned::append_update(&[d0u, d1u], &mut self.e, &mut other.e, space);
        }
    }

    // TODO: drain

    #[inline]
    pub fn clear(&mut self) {
        self.truncate(0);
    }

    // TODO: map_in_place

    pub fn extend<I0, I1>(&mut self, i0: I0, i1: I1)
        where I0: Iterator<Item=A>, I1: Iterator<Item=B> {
        unsafe {
            let d0u = self.d0.extend(&self.e, i0);
            let d1u = self.d1.extend(&self.e, i1);

            unadorned::extend_update(&[d0u, d1u], &mut self.e);
        }
    }

    pub fn from_iters<I0, I1>(i0: I0, i1: I1) -> Soa2<A, B>
        where I0: Iterator<Item=A>, I1: Iterator<Item=B> {
        let mut v = Soa2::new();
        v.extend(i0, i1);
        v
    }

    // TODO: dedup
}

impl<A: Clone, B: Clone> Soa2<A, B> {
    #[inline]
    pub fn resize(&mut self, new_len: usize, value: (A, B)) {
        let len = self.len();

        if new_len > len {
            self.extend(repeat(value.0).take(new_len - len), repeat(value.1).take(new_len - len));
        } else {
            self.truncate(new_len);
        }
    }

    #[inline]
    pub fn push_all(&mut self, x0: &[A], x1: &[B]) {
        unsafe {
            assert_eq!(x0.len(), x1.len());

            let space = unadorned::calc_reserve_space(&self.e, x0.len());

            let d0u = self.d0.push_all(x0, &self.e, &space);
            let d1u = self.d1.push_all(x1, &self.e, &space);

            unadorned::push_all_update(&[d0u, d1u], &mut self.e, x0.len(), space);
        }
    }
}

impl<A: Clone, B: Clone> Clone for Soa2<A, B> {
    #[inline]
    fn clone(&self) -> Soa2<A, B> {
        let mut ret = Soa2::new();
        let (d0, d1) = self.as_slices();
        ret.push_all(d0, d1);
        ret
    }

    fn clone_from(&mut self, other: &Soa2<A, B>) {
        // TODO: cleanup

        if self.len() > other.len() {
            self.truncate(other.len());
        }

        let (od0, od1) = other.as_slices();

        let (s0, s1) = {
            let (sd0, sd1) = self.as_mut_slices();

            for (place, thing) in sd0.iter_mut().zip(od0.iter()) {
                place.clone_from(thing);
            }

            for (place, thing) in sd1.iter_mut().zip(od1.iter()) {
                place.clone_from(thing);
            }

            let s0 = &od0[sd0.len()..];
            let s1 = &od1[sd1.len()..];

            (s0, s1)
        };

        self.push_all(s0, s1);
    }
}

impl<S: hash::Writer + hash::Hasher, A: Hash<S>, B: Hash<S>> Hash<S> for Soa2<A, B> {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slices().hash(state)
    }
}

#[unsafe_destructor]
impl<A, B> Drop for Soa2<A, B> {
    #[inline]
    fn drop(&mut self) {
        if self.e.cap != 0 {
            unsafe {
                self.d0.drop(&self.e);
                self.d1.drop(&self.e);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Postgres support for the `r2d2` connection pool.
#![doc(html_root_url="https://sfackler.github.io/r2d2-postgres/doc/v0.10.1")]
#![warn(missing_docs)]
extern crate r2d2;
extern crate postgres;

use std::error;
use std::error::Error as _StdError;
use std::fmt;
use postgres::IntoConnectParams;
use postgres::io::NegotiateSsl;

/// Like `postgres::SslMode` except that it owns its `NegotiateSsl` instance.
#[derive(Debug)]
pub enum SslMode {
    /// Like `postgres::SslMode::None`.
    None,
    /// Like `postgres::SslMode::Prefer`.
    Prefer(Box<NegotiateSsl + Sync + Send>),
    /// Like `postgres::SslMode::Require`.
    Require(Box<NegotiateSsl + Sync + Send>),
}

/// A unified enum of errors returned by postgres::Connection
#[derive(Debug)]
pub enum Error {
    /// A postgres::error::ConnectError
    Connect(postgres::error::ConnectError),
    /// An postgres::error::Error
    Other(postgres::error::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}: {}", self.description(), self.cause().unwrap())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Connect(_) => "Error opening a connection",
            Error::Other(_) => "Error communicating with server",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Connect(ref err) => Some(err as &error::Error),
            Error::Other(ref err) => Some(err as &error::Error),
        }
    }
}

/// An `r2d2::ManageConnection` for `postgres::Connection`s.
///
/// ## Example
///
/// ```rust,no_run
/// extern crate r2d2;
/// extern crate r2d2_postgres;
/// extern crate postgres;
///
/// use std::thread;
/// use r2d2_postgres::{SslMode, PostgresConnectionManager};
///
/// fn main() {
///     let config = r2d2::Config::default();
///     let manager = PostgresConnectionManager::new("postgres://postgres@localhost",
///                                                  SslMode::None).unwrap();
///     let pool = r2d2::Pool::new(config, manager).unwrap();
///
///     for i in 0..10i32 {
///         let pool = pool.clone();
///         thread::spawn(move || {
///             let conn = pool.get().unwrap();
///             conn.execute("INSERT INTO foo (bar) VALUES ($1)", &[&i]).unwrap();
///         });
///     }
/// }
/// ```
#[derive(Debug)]
pub struct PostgresConnectionManager {
    params: postgres::ConnectParams,
    ssl_mode: SslMode,
}

impl PostgresConnectionManager {
    /// Creates a new `PostgresConnectionManager`.
    ///
    /// See `postgres::Connection::connect` for a description of the parameter
    /// types.
    pub fn new<T>(params: T,
                  ssl_mode: SslMode)
                  -> Result<PostgresConnectionManager, postgres::error::ConnectError>
        where T: IntoConnectParams
    {
        let params = match params.into_connect_params() {
            Ok(params) => params,
            Err(err) => return Err(postgres::error::ConnectError::ConnectParams(err)),
        };

        Ok(PostgresConnectionManager {
            params: params,
            ssl_mode: ssl_mode,
        })
    }
}

impl r2d2::ManageConnection for PostgresConnectionManager {
    type Connection = postgres::Connection;
    type Error = Error;

    fn connect(&self) -> Result<postgres::Connection, Error> {
        let mode = match self.ssl_mode {
            SslMode::None => postgres::SslMode::None,
            SslMode::Prefer(ref n) => postgres::SslMode::Prefer(&**n),
            SslMode::Require(ref n) => postgres::SslMode::Require(&**n),
        };
        postgres::Connection::connect(self.params.clone(), mode).map_err(Error::Connect)
    }

    fn is_valid(&self, conn: &mut postgres::Connection) -> Result<(), Error> {
        conn.batch_execute("").map_err(Error::Other)
    }

    fn has_broken(&self, conn: &mut postgres::Connection) -> bool {
        conn.is_desynchronized()
    }
}
<commit_msg>Pub crates types are used<commit_after>//! Postgres support for the `r2d2` connection pool.
#![doc(html_root_url="https://sfackler.github.io/r2d2-postgres/doc/v0.10.1")]
#![warn(missing_docs)]
pub extern crate r2d2;
pub extern crate postgres;

use std::error;
use std::error::Error as _StdError;
use std::fmt;
use postgres::IntoConnectParams;
use postgres::io::NegotiateSsl;

/// Like `postgres::SslMode` except that it owns its `NegotiateSsl` instance.
#[derive(Debug)]
pub enum SslMode {
    /// Like `postgres::SslMode::None`.
    None,
    /// Like `postgres::SslMode::Prefer`.
    Prefer(Box<NegotiateSsl + Sync + Send>),
    /// Like `postgres::SslMode::Require`.
    Require(Box<NegotiateSsl + Sync + Send>),
}

/// A unified enum of errors returned by postgres::Connection
#[derive(Debug)]
pub enum Error {
    /// A postgres::error::ConnectError
    Connect(postgres::error::ConnectError),
    /// An postgres::error::Error
    Other(postgres::error::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}: {}", self.description(), self.cause().unwrap())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Connect(_) => "Error opening a connection",
            Error::Other(_) => "Error communicating with server",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Connect(ref err) => Some(err as &error::Error),
            Error::Other(ref err) => Some(err as &error::Error),
        }
    }
}

/// An `r2d2::ManageConnection` for `postgres::Connection`s.
///
/// ## Example
///
/// ```rust,no_run
/// extern crate r2d2;
/// extern crate r2d2_postgres;
/// extern crate postgres;
///
/// use std::thread;
/// use r2d2_postgres::{SslMode, PostgresConnectionManager};
///
/// fn main() {
///     let config = r2d2::Config::default();
///     let manager = PostgresConnectionManager::new("postgres://postgres@localhost",
///                                                  SslMode::None).unwrap();
///     let pool = r2d2::Pool::new(config, manager).unwrap();
///
///     for i in 0..10i32 {
///         let pool = pool.clone();
///         thread::spawn(move || {
///             let conn = pool.get().unwrap();
///             conn.execute("INSERT INTO foo (bar) VALUES ($1)", &[&i]).unwrap();
///         });
///     }
/// }
/// ```
#[derive(Debug)]
pub struct PostgresConnectionManager {
    params: postgres::ConnectParams,
    ssl_mode: SslMode,
}

impl PostgresConnectionManager {
    /// Creates a new `PostgresConnectionManager`.
    ///
    /// See `postgres::Connection::connect` for a description of the parameter
    /// types.
    pub fn new<T>(params: T,
                  ssl_mode: SslMode)
                  -> Result<PostgresConnectionManager, postgres::error::ConnectError>
        where T: IntoConnectParams
    {
        let params = match params.into_connect_params() {
            Ok(params) => params,
            Err(err) => return Err(postgres::error::ConnectError::ConnectParams(err)),
        };

        Ok(PostgresConnectionManager {
            params: params,
            ssl_mode: ssl_mode,
        })
    }
}

impl r2d2::ManageConnection for PostgresConnectionManager {
    type Connection = postgres::Connection;
    type Error = Error;

    fn connect(&self) -> Result<postgres::Connection, Error> {
        let mode = match self.ssl_mode {
            SslMode::None => postgres::SslMode::None,
            SslMode::Prefer(ref n) => postgres::SslMode::Prefer(&**n),
            SslMode::Require(ref n) => postgres::SslMode::Require(&**n),
        };
        postgres::Connection::connect(self.params.clone(), mode).map_err(Error::Connect)
    }

    fn is_valid(&self, conn: &mut postgres::Connection) -> Result<(), Error> {
        conn.batch_execute("").map_err(Error::Other)
    }

    fn has_broken(&self, conn: &mut postgres::Connection) -> bool {
        conn.is_desynchronized()
    }
}
<|endoftext|>