<commit_before>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("src/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=src/demo.cc");
//!     println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the *demo*
//! directory of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::drop_copy,
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg
)]

mod cfg;
mod deps;
mod error;
mod gen;
mod intern;
mod out;
mod paths;
mod syntax;
mod target;
mod vec;

use crate::deps::Crate;
use crate::error::{Error, Result};
use crate::gen::error::report;
use crate::gen::Opt;
use crate::paths::PathExt;
use crate::target::TargetDir;
use cc::Build;
use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
use std::process;

pub use crate::cfg::{Cfg, CFG};

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("src/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
#[must_use]
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

struct Project {
    include_prefix: PathBuf,
    manifest_dir: PathBuf,
    // Output directory as received from Cargo.
    out_dir: PathBuf,
    // Directory into which to symlink all generated code.
    //
    // This is *not* used for an #include path, only as a debugging convenience.
    // Normally available at target/cxxbridge/ if we are able to know where the
    // target dir is, otherwise under a common scratch dir.
    //
    // The reason this isn't the #include dir is that we do not want builds to
    // have access to headers from arbitrary other parts of the dependency
    // graph. Using a global directory for all builds would be both a race
    // condition depending on what order Cargo randomly executes the build
    // scripts, as well as semantically undesirable for builds not to have to
    // declare their real dependencies.
    shared_dir: PathBuf,
}

impl Project {
    fn init() -> Result<Self> {
        let include_prefix = Path::new(CFG.include_prefix);
        assert!(include_prefix.is_relative());
        let include_prefix = include_prefix.components().collect();

        let manifest_dir = paths::manifest_dir()?;
        let out_dir = paths::out_dir()?;

        let shared_dir = match target::find_target_dir(&out_dir) {
            TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
            TargetDir::Unknown => scratch::path("cxxbridge"),
        };

        Ok(Project {
            include_prefix,
            manifest_dir,
            out_dir,
            shared_dir,
        })
    }
}

// We lay out the OUT_DIR as follows. Everything is namespaced under a cxxbridge
// subdirectory to avoid stomping on other things that the caller's build script
// might be doing inside OUT_DIR.
//
//     $OUT_DIR/
//        cxxbridge/
//           crate/
//              $CARGO_PKG_NAME -> $CARGO_MANIFEST_DIR
//           include/
//              rust/
//                 cxx.h
//              $CARGO_PKG_NAME/
//                 .../
//                    lib.rs.h
//           sources/
//              $CARGO_PKG_NAME/
//                 .../
//                    lib.rs.cc
//
// The crate/ and include/ directories are placed on the #include path for the
// current build as well as for downstream builds that have a direct dependency
// on the current crate.
fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let ref prj = Project::init()?;

    let crate_dir = make_crate_dir(prj);
    let include_dir = make_include_dir(prj)?;
    let mut this_crate = Crate {
        include_prefix: Some(prj.include_prefix.clone()),
        links: env::var_os("CARGO_MANIFEST_LINKS"),
        exported_header_dirs: Vec::new(),
    };

    // The crate_dir is placed after the generated code directory (include_dir)
    // on the include line so that `#include "path/to/file.rs"` from C++
    // "magically" works and refers to the API generated from that Rust source
    // file.
    this_crate.exported_header_dirs.push(include_dir);
    this_crate.exported_header_dirs.extend(crate_dir);
    this_crate.print_to_cargo();

    let mut build = Build::new();
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate

    for path in rust_source_files {
        generate_bridge(prj, &mut build, path.as_ref())?;
    }

    let mut crates = deps::direct_dependencies();
    crates.insert(0, this_crate);

    eprintln!("\nCXX include path:");
    for krate in crates {
        for header_dir in &krate.exported_header_dirs {
            build.include(header_dir);
            eprintln!("  {}", header_dir.display());
        }
    }

    Ok(build)
}

fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
    if prj.include_prefix.as_os_str().is_empty() {
        return Some(prj.manifest_dir.clone());
    }
    let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
    let link = crate_dir.join(&prj.include_prefix);
    if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
        Some(crate_dir)
    } else {
        None
    }
}

fn make_include_dir(prj: &Project) -> Result<PathBuf> {
    let include_dir = prj.out_dir.join("cxxbridge").join("include");
    let cxx_h = include_dir.join("rust").join("cxx.h");
    let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h");
    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE05_HEADER") {
        out::symlink_file(original, cxx_h)?;
        out::symlink_file(original, shared_cxx_h)?;
    } else {
        out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?;
        out::symlink_file(shared_cxx_h, cxx_h)?;
    }
    Ok(include_dir)
}

fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
    let opt = Opt {
        allow_dot_includes: false,
        ..Opt::default()
    };
    let generated = gen::generate_from_path(rust_source_file, &opt);
    let ref rel_path = paths::local_relative_path(rust_source_file);

    let cxxbridge = prj.out_dir.join("cxxbridge");
    let include_dir = cxxbridge.join("include").join(&prj.include_prefix);
    let sources_dir = cxxbridge.join("sources").join(&prj.include_prefix);

    let ref rel_path_h = rel_path.with_appended_extension(".h");
    let ref header_path = include_dir.join(rel_path_h);
    out::write(header_path, &generated.header)?;

    let ref link_path = include_dir.join(rel_path);
    let _ = out::symlink_file(header_path, link_path);

    let ref rel_path_cc = rel_path.with_appended_extension(".cc");
    let ref implementation_path = sources_dir.join(rel_path_cc);
    out::write(implementation_path, &generated.implementation)?;
    build.file(implementation_path);

    let shared_h = prj.shared_dir.join(&prj.include_prefix).join(rel_path_h);
    let shared_cc = prj.shared_dir.join(&prj.include_prefix).join(rel_path_cc);
    let _ = out::symlink_file(header_path, shared_h);
    let _ = out::symlink_file(implementation_path, shared_cc);
    Ok(())
}

fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
    let key = key.as_ref();
    env::var_os(key).ok_or_else(|| Error::NoEnv(key.to_owned()))
}
<commit_msg>Clean up wording of include_dir vs crate_dir sort comment<commit_after>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("src/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=src/demo.cc");
//!     println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the *demo*
//! directory of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::drop_copy,
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg
)]

mod cfg;
mod deps;
mod error;
mod gen;
mod intern;
mod out;
mod paths;
mod syntax;
mod target;
mod vec;

use crate::deps::Crate;
use crate::error::{Error, Result};
use crate::gen::error::report;
use crate::gen::Opt;
use crate::paths::PathExt;
use crate::target::TargetDir;
use cc::Build;
use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
use std::process;

pub use crate::cfg::{Cfg, CFG};

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("src/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
#[must_use]
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

struct Project {
    include_prefix: PathBuf,
    manifest_dir: PathBuf,
    // Output directory as received from Cargo.
    out_dir: PathBuf,
    // Directory into which to symlink all generated code.
    //
    // This is *not* used for an #include path, only as a debugging convenience.
    // Normally available at target/cxxbridge/ if we are able to know where the
    // target dir is, otherwise under a common scratch dir.
    //
    // The reason this isn't the #include dir is that we do not want builds to
    // have access to headers from arbitrary other parts of the dependency
    // graph. Using a global directory for all builds would be both a race
    // condition depending on what order Cargo randomly executes the build
    // scripts, as well as semantically undesirable for builds not to have to
    // declare their real dependencies.
    shared_dir: PathBuf,
}

impl Project {
    fn init() -> Result<Self> {
        let include_prefix = Path::new(CFG.include_prefix);
        assert!(include_prefix.is_relative());
        let include_prefix = include_prefix.components().collect();

        let manifest_dir = paths::manifest_dir()?;
        let out_dir = paths::out_dir()?;

        let shared_dir = match target::find_target_dir(&out_dir) {
            TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
            TargetDir::Unknown => scratch::path("cxxbridge"),
        };

        Ok(Project {
            include_prefix,
            manifest_dir,
            out_dir,
            shared_dir,
        })
    }
}

// We lay out the OUT_DIR as follows. Everything is namespaced under a cxxbridge
// subdirectory to avoid stomping on other things that the caller's build script
// might be doing inside OUT_DIR.
//
//     $OUT_DIR/
//        cxxbridge/
//           crate/
//              $CARGO_PKG_NAME -> $CARGO_MANIFEST_DIR
//           include/
//              rust/
//                 cxx.h
//              $CARGO_PKG_NAME/
//                 .../
//                    lib.rs.h
//           sources/
//              $CARGO_PKG_NAME/
//                 .../
//                    lib.rs.cc
//
// The crate/ and include/ directories are placed on the #include path for the
// current build as well as for downstream builds that have a direct dependency
// on the current crate.
fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let ref prj = Project::init()?;

    let crate_dir = make_crate_dir(prj);
    let include_dir = make_include_dir(prj)?;
    let mut this_crate = Crate {
        include_prefix: Some(prj.include_prefix.clone()),
        links: env::var_os("CARGO_MANIFEST_LINKS"),
        exported_header_dirs: Vec::new(),
    };

    // The generated code directory (include_dir) is placed in front of
    // crate_dir on the include line so that `#include "path/to/file.rs"` from
    // C++ "magically" works and refers to the API generated from that Rust
    // source file.
    this_crate.exported_header_dirs.push(include_dir);
    this_crate.exported_header_dirs.extend(crate_dir);
    this_crate.print_to_cargo();

    let mut build = Build::new();
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate

    for path in rust_source_files {
        generate_bridge(prj, &mut build, path.as_ref())?;
    }

    let mut crates = deps::direct_dependencies();
    crates.insert(0, this_crate);

    eprintln!("\nCXX include path:");
    for krate in crates {
        for header_dir in &krate.exported_header_dirs {
            build.include(header_dir);
            eprintln!("  {}", header_dir.display());
        }
    }

    Ok(build)
}

fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
    if prj.include_prefix.as_os_str().is_empty() {
        return Some(prj.manifest_dir.clone());
    }
    let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
    let link = crate_dir.join(&prj.include_prefix);
    if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
        Some(crate_dir)
    } else {
        None
    }
}

fn make_include_dir(prj: &Project) -> Result<PathBuf> {
    let include_dir = prj.out_dir.join("cxxbridge").join("include");
    let cxx_h = include_dir.join("rust").join("cxx.h");
    let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h");
    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE05_HEADER") {
        out::symlink_file(original, cxx_h)?;
        out::symlink_file(original, shared_cxx_h)?;
    } else {
        out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?;
        out::symlink_file(shared_cxx_h, cxx_h)?;
    }
    Ok(include_dir)
}

fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
    let opt = Opt {
        allow_dot_includes: false,
        ..Opt::default()
    };
    let generated = gen::generate_from_path(rust_source_file, &opt);
    let ref rel_path = paths::local_relative_path(rust_source_file);

    let cxxbridge = prj.out_dir.join("cxxbridge");
    let include_dir = cxxbridge.join("include").join(&prj.include_prefix);
    let sources_dir = cxxbridge.join("sources").join(&prj.include_prefix);

    let ref rel_path_h = rel_path.with_appended_extension(".h");
    let ref header_path = include_dir.join(rel_path_h);
    out::write(header_path, &generated.header)?;

    let ref link_path = include_dir.join(rel_path);
    let _ = out::symlink_file(header_path, link_path);

    let ref rel_path_cc = rel_path.with_appended_extension(".cc");
    let ref implementation_path = sources_dir.join(rel_path_cc);
    out::write(implementation_path, &generated.implementation)?;
    build.file(implementation_path);

    let shared_h = prj.shared_dir.join(&prj.include_prefix).join(rel_path_h);
    let shared_cc = prj.shared_dir.join(&prj.include_prefix).join(rel_path_cc);
    let _ = out::symlink_file(header_path, shared_h);
    let _ = out::symlink_file(implementation_path, shared_cc);
    Ok(())
}

fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
    let key = key.as_ref();
    env::var_os(key).ok_or_else(|| Error::NoEnv(key.to_owned()))
}
<|endoftext|>


<commit_before>const PACKAGE_LIST: &str = "package.list";
const NAME: &str = "wiz";
const VERSION: &str = "0.0.1";<commit_msg>Marking the &str with static<commit_after>pub const PACKAGE_LIST: &'static str = "package.list";
pub const NAME: &'static str = "wiz";
pub const VERSION: &'static str = "0.0.1";<|endoftext|>


<commit_before>use std::iter;
use std::fmt;
use super::{QueueOfStrings, Queue};

const INITIAL_QUEUE_CAPACITY: usize = 2;

pub struct ResizingArrayQueueOfStrings {
    q: Vec<Option<String>>,
    head: usize,
    tail: usize
}

impl ResizingArrayQueueOfStrings {
    pub fn with_capacity(capacity: usize) -> ResizingArrayQueueOfStrings {
        let storage = iter::repeat(None).take(capacity).collect();

        ResizingArrayQueueOfStrings {
            q: storage,
            head: 0,
            tail: 0
        }
    }

    fn resize(&mut self, capacity: usize) {
        let cap = self.q.len();
        let mut new_storage: Vec<Option<String>> = iter::repeat(None).take(capacity).collect();
        let tail = if self.tail > self.head {
            self.tail
        } else {
            self.tail + cap
        };
        for i in self.head .. tail{
            new_storage[i] = self.q[i % cap].take();
        }
        self.q = new_storage;
        // self.head = self.head
        self.tail = tail
    }
}

impl QueueOfStrings for ResizingArrayQueueOfStrings {
    fn new() -> ResizingArrayQueueOfStrings {
        let storage = iter::repeat(None).take(INITIAL_QUEUE_CAPACITY).collect();

        ResizingArrayQueueOfStrings {
            q: storage,
            head: 0,
            tail: 0
        }
    }

    fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    fn enqueue(&mut self, item: String) {
        let mut cap = self.q.len();
        self.q[self.tail % cap] = Some(item);
        self.tail = (self.tail + 1) % cap;
        if self.q[self.tail % cap].is_some() {
            cap = 2 * cap;
            self.resize(cap);
        }
    }

    fn dequeue(&mut self) -> String {
        let cap = self.q.len();
        let item = self.q[self.head % cap].take();
        self.head = (self.head + 1) % cap;
        item.unwrap()
    }

    fn size(&self) -> usize {
        let cap = self.q.len();
        let tail = if self.tail > self.head {
            self.tail
        } else {
            self.tail + cap
        };
        tail - self.head
    }
}

// generic ResizingArrayQueue
pub struct ResizingArrayQueue<T> {
    q: Vec<Option<T>>,
    head: usize,
    tail: usize
}

impl<T> ResizingArrayQueue<T> {
    pub fn with_capacity(capacity: usize) -> ResizingArrayQueue<T> {
        let mut storage = Vec::with_capacity(capacity);
        for _ in 0 .. capacity {
            storage.push(None);
        }

        ResizingArrayQueue {
            q: storage,
            head: 0,
            tail: 0
        }
    }

    fn resize(&mut self, capacity: usize) {
        let cap = self.q.len();
        let mut new_storage: Vec<Option<T>> = Vec::with_capacity(capacity);

        let tail = if self.tail > self.head {
            self.tail
        } else {
            self.tail + cap
        };
        for i in 0 .. capacity {
            if i >= self.head && i < tail {
                new_storage.push(self.q[i % cap].take());
            } else {
                new_storage.push(None);
            }

        }
        self.q = new_storage;
        self.tail = tail
    }
}

impl<T> Queue<T> for ResizingArrayQueue<T> {
    fn new() -> ResizingArrayQueue<T> {
        ResizingArrayQueue::with_capacity(INITIAL_QUEUE_CAPACITY)
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    fn enqueue(&mut self, item: T) {
        let mut cap = self.q.len();
        self.q[self.tail % cap] = Some(item);
        self.tail = (self.tail + 1) % cap;
        // if resize before enqueue, is_empty() will fail.
        if self.q[self.tail % cap].is_some() {
            cap = 2 * cap;
            self.resize(cap);
        }
    }

    fn dequeue(&mut self) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        let cap = self.q.len();
        let item = self.q[self.head % cap].take();
        self.head = (self.head + 1) % cap;
        item
    }

    fn size(&self) -> usize {
        let cap = self.q.len();
        let tail = if self.tail > self.head {
            self.tail
        } else {
            self.tail + cap
        };
        tail - self.head
    }
}

impl<T: fmt::Debug> fmt::Debug for ResizingArrayQueue<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.head < self.tail {
            for item in self.q[self.head .. self.tail].iter() {
                try!(write!(f, "{:?}, ", item.as_ref().unwrap()));
            }
        } else {
            for item in self.q[self.head ..].iter() {
                try!(write!(f, "{:?}, ", item));
            }
            for item in self.q[.. self.tail].iter() {
                try!(write!(f, "{:?}, ", item));
            }
        }
        Ok(())
    }
}

pub struct IntoIter<T> {
    queue: ResizingArrayQueue<T>
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.queue.dequeue()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.size(), Some(self.size()))
    }
}

impl<T> IntoIterator for ResizingArrayQueue<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter { queue: self }
    }
}

#[test]
fn test_resizing_array_queue_of_strings() {
    let mut queue: ResizingArrayQueueOfStrings = QueueOfStrings::new();

    assert!(queue.is_empty());
    let mut result = "to be or not to be".split(' ');

    for s in "to be or not to - be - - that - - - is".split(' ') {
        if s == "-" {
            assert_eq!(&queue.dequeue(), result.next().unwrap())
        } else {
            queue.enqueue(s.into())
        }
    }
    assert!(!queue.is_empty());
    assert_eq!(2, queue.size());
}

#[test]
fn test_resizing_array_queue() {
    let mut queue: ResizingArrayQueue<String> = Queue::new();

    assert!(queue.is_empty());
    let mut result = "to be or not to be".split(' ');

    for s in "to be or not to - be - - that - - - is".split(' ') {
        if s == "-" {
            assert_eq!(queue.dequeue(), result.next().map(|s| s.into()))
        } else {
            queue.enqueue(s.into())
        }
    }
    assert!(!queue.is_empty());
    assert_eq!(2, queue.size());
}
<commit_msg>stacks_and_queues/resizing_array_queue: impl Clone for ResizingArrayQueue<commit_after>use std::iter;
use std::fmt;
use super::{QueueOfStrings, Queue};

const INITIAL_QUEUE_CAPACITY: usize = 2;

pub struct ResizingArrayQueueOfStrings {
    q: Vec<Option<String>>,
    head: usize,
    tail: usize
}

impl ResizingArrayQueueOfStrings {
    pub fn with_capacity(capacity: usize) -> ResizingArrayQueueOfStrings {
        let storage = iter::repeat(None).take(capacity).collect();

        ResizingArrayQueueOfStrings {
            q: storage,
            head: 0,
            tail: 0
        }
    }

    fn resize(&mut self, capacity: usize) {
        let cap = self.q.len();
        let mut new_storage: Vec<Option<String>> = iter::repeat(None).take(capacity).collect();
        let tail = if self.tail > self.head {
            self.tail
        } else {
            self.tail + cap
        };
        for i in self.head .. tail{
            new_storage[i] = self.q[i % cap].take();
        }
        self.q = new_storage;
        // self.head = self.head
        self.tail = tail
    }
}

impl QueueOfStrings for ResizingArrayQueueOfStrings {
    fn new() -> ResizingArrayQueueOfStrings {
        let storage = iter::repeat(None).take(INITIAL_QUEUE_CAPACITY).collect();

        ResizingArrayQueueOfStrings {
            q: storage,
            head: 0,
            tail: 0
        }
    }

    fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    fn enqueue(&mut self, item: String) {
        let mut cap = self.q.len();
        self.q[self.tail % cap] = Some(item);
        self.tail = (self.tail + 1) % cap;
        if self.q[self.tail % cap].is_some() {
            cap = 2 * cap;
            self.resize(cap);
        }
    }

    fn dequeue(&mut self) -> String {
        let cap = self.q.len();
        let item = self.q[self.head % cap].take();
        self.head = (self.head + 1) % cap;
        item.unwrap()
    }

    fn size(&self) -> usize {
        let cap = self.q.len();
        let tail = if self.tail > self.head {
            self.tail
        } else {
            self.tail + cap
        };
        tail - self.head
    }
}

// generic ResizingArrayQueue
pub struct ResizingArrayQueue<T> {
    q: Vec<Option<T>>,
    head: usize,
    tail: usize
}

impl<T: Clone> Clone for ResizingArrayQueue<T> {
    fn clone(&self) -> Self {
        ResizingArrayQueue {
            q: self.q.clone(),
            head: self.head,
            tail: self.tail
        }
    }
}

impl<T> ResizingArrayQueue<T> {
    pub fn with_capacity(capacity: usize) -> ResizingArrayQueue<T> {
        let mut storage = Vec::with_capacity(capacity);
        for _ in 0 .. capacity {
            storage.push(None);
        }

        ResizingArrayQueue {
            q: storage,
            head: 0,
            tail: 0
        }
    }

    fn resize(&mut self, capacity: usize) {
        let cap = self.q.len();
        let mut new_storage: Vec<Option<T>> = Vec::with_capacity(capacity);

        let tail = if self.tail > self.head {
            self.tail
        } else {
            self.tail + cap
        };
        for i in 0 .. capacity {
            if i >= self.head && i < tail {
                new_storage.push(self.q[i % cap].take());
            } else {
                new_storage.push(None);
            }

        }
        self.q = new_storage;
        self.tail = tail
    }
}

impl<T> Queue<T> for ResizingArrayQueue<T> {
    fn new() -> ResizingArrayQueue<T> {
        ResizingArrayQueue::with_capacity(INITIAL_QUEUE_CAPACITY)
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    fn enqueue(&mut self, item: T) {
        let mut cap = self.q.len();
        self.q[self.tail % cap] = Some(item);
        self.tail = (self.tail + 1) % cap;
        // if resize before enqueue, is_empty() will fail.
        if self.q[self.tail % cap].is_some() {
            cap = 2 * cap;
            self.resize(cap);
        }
    }

    fn dequeue(&mut self) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        let cap = self.q.len();
        let item = self.q[self.head % cap].take();
        self.head = (self.head + 1) % cap;
        item
    }

    fn size(&self) -> usize {
        let cap = self.q.len();
        let tail = if self.tail > self.head {
            self.tail
        } else {
            self.tail + cap
        };
        tail - self.head
    }
}

impl<T: fmt::Debug> fmt::Debug for ResizingArrayQueue<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.head < self.tail {
            for item in self.q[self.head .. self.tail].iter() {
                try!(write!(f, "{:?}, ", item.as_ref().unwrap()));
            }
        } else {
            for item in self.q[self.head ..].iter() {
                try!(write!(f, "{:?}, ", item));
            }
            for item in self.q[.. self.tail].iter() {
                try!(write!(f, "{:?}, ", item));
            }
        }
        Ok(())
    }
}

pub struct IntoIter<T> {
    queue: ResizingArrayQueue<T>
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.queue.dequeue()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.queue.size(), Some(self.queue.size()))
    }
}

impl<T> IntoIterator for ResizingArrayQueue<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter { queue: self }
    }
}

#[test]
fn test_resizing_array_queue_of_strings() {
    let mut queue: ResizingArrayQueueOfStrings = QueueOfStrings::new();

    assert!(queue.is_empty());
    let mut result = "to be or not to be".split(' ');

    for s in "to be or not to - be - - that - - - is".split(' ') {
        if s == "-" {
            assert_eq!(&queue.dequeue(), result.next().unwrap())
        } else {
            queue.enqueue(s.into())
        }
    }
    assert!(!queue.is_empty());
    assert_eq!(2, queue.size());
}

#[test]
fn test_resizing_array_queue() {
    let mut queue: ResizingArrayQueue<String> = Queue::new();

    assert!(queue.is_empty());
    let mut result = "to be or not to be".split(' ');

    for s in "to be or not to - be - - that - - - is".split(' ') {
        if s == "-" {
            assert_eq!(queue.dequeue(), result.next().map(|s| s.into()))
        } else {
            queue.enqueue(s.into())
        }
    }
    assert!(!queue.is_empty());
    assert_eq!(2, queue.size());
}
<|endoftext|>


<commit_before>mod aoc_2015_01;
mod aoc_2015_02;

fn main() {
    let days = [
        aoc_2015_01::run,
        aoc_2015_02::run,
    ];
    if let Some(day_arg) = std::env::args().nth(1) {
        // Try to run specific day's solution
        match day_arg.parse::<usize>() {
            // Day is in bounds for solutions in `days` array
            Ok(day) if { day <= days.len() && day > 0 } => {
                println!("{}", days[day - 1]());
            }
            // Day is out of bounds for `days` array
            Ok(_) => {
                println!(
                    "Given day ({}) is out of bounds for currently registered solutions.",
                    day_arg
                );
                std::process::exit(1);
            }
            // Could not parse the day argument given
            Err(e) => {
                println!("Cannot parse argument ({}) as a number. {}", day_arg, e);
                std::process::exit(1);
            }
        }
    } else {
        // Run all days
        days.iter().for_each(|day| println!("{}", day()));
    }
}
<commit_msg>2015 Rust: Add blank line when running all tests<commit_after>mod aoc_2015_01;
mod aoc_2015_02;

fn main() {
    let days = [
        aoc_2015_01::run,
        aoc_2015_02::run,
    ];
    if let Some(day_arg) = std::env::args().nth(1) {
        // Try to run specific day's solution
        match day_arg.parse::<usize>() {
            // Day is in bounds for solutions in `days` array
            Ok(day) if { day <= days.len() && day > 0 } => {
                println!("{}", days[day - 1]());
            }
            // Day is out of bounds for `days` array
            Ok(_) => {
                println!(
                    "Given day ({}) is out of bounds for currently registered solutions.",
                    day_arg
                );
                std::process::exit(1);
            }
            // Could not parse the day argument given
            Err(e) => {
                println!("Cannot parse argument ({}) as a number. {}", day_arg, e);
                std::process::exit(1);
            }
        }
    } else {
        // Run all days
        days.iter().for_each(|day| println!("{}\n", day()));
    }
}
<|endoftext|>


<commit_before>use cpu::coproc::Coprocessor;

pub struct SysControl {

}

impl SysControl {
    pub fn new() -> SysControl {
        SysControl {}
    }
}

impl Coprocessor for SysControl {
    fn move_in(&mut self, cpreg1: usize, cpreg2: usize, op1: usize, op2: usize, val: u32) {
        panic!("Unimplemented CP15 operation to coproc reg {}", cpreg1);
    }

    fn move_out(&mut self, cpreg1: usize, cpreg2: usize, op1: usize, op2: usize) -> u32 {
        panic!("Unimplemented CP15 operation from coproc reg {}", cpreg1);
    }
}<commit_msg>Stubbed a whole lot of CP15 register accesses<commit_after>use cpu::coproc::Coprocessor;

bitfield!(RegControl: u32, {
    use_mpu: 0 => 0,
    align_fault: 1 => 1,
    use_dcache: 2 => 2,
    write_buf: 3 => 3,
    big_endian: 7 => 7,
    sys_protect: 8 => 8,
    rom_protect: 9 => 9,
    f_bit: 10 => 10,
    predict_branches: 11 => 11,
    use_icache: 12 => 12,
    high_vectors: 13 => 13,
    predictable_cache: 14 => 14,
    disable_thumb: 15 => 15,
    low_latency_frq: 21 => 21,
    allow_unaligned: 22 => 22,
    disable_subpage_ap: 23 => 23,
    vectored_interrupts: 24 => 24,
    mixed_endian_exceptions: 25 => 25,
    use_l2cache: 26 => 26
});

pub struct SysControl {
    r1_control: RegControl,
    r2_dcacheability: u32,
    r2_icacheability: u32,
    r3_bufferability: u32,
    r5_daccessperms: u32,
    r5_iaccessperms: u32,
    r6_memregions: [u32; 8],
    r9_dcache_lockdown: u32,
    r9_icache_lockdown: u32,
    r9_dtcm_size: u32,
    r9_itcm_size: u32,
}

impl SysControl {
    pub fn new() -> SysControl {
        SysControl {
            r1_control: RegControl::new(0),
            r2_dcacheability: 0,
            r2_icacheability: 0,
            r3_bufferability: 0,
            r5_daccessperms: 0,
            r5_iaccessperms: 0,
            r6_memregions: [0; 8],
            r9_dcache_lockdown: 0,
            r9_icache_lockdown: 0,
            r9_dtcm_size: 0,
            r9_itcm_size: 0,
        }
    }
}

impl Coprocessor for SysControl {
    fn move_in(&mut self, cpreg1: usize, cpreg2: usize, op1: usize, op2: usize, val: u32) {
        assert_eq!(op1, 0);

        match cpreg1 {
            1 => match op2 {
                0b000 => {
                    warn!("STUBBED: System control register write");
                    self.r1_control.set_raw(val);
                }
                0b001 | 0b010 => unimplemented!(),
                _ => unreachable!()
            },

            2 => match op2 {
                0 => {
                    warn!("STUBBED: DCache cacheability register write");
                    self.r2_dcacheability = val;
                }
                1 => {
                    warn!("STUBBED: ICache cacheability register write");
                    self.r2_icacheability = val;
                }
                _ => unreachable!()
            },

            3 => {
                warn!("STUBBED: Data bufferability register write");
                self.r3_bufferability = val;
            }

            5 => match op2 {
                0 | 1 => unimplemented!(),
                2 => {
                    warn!("STUBBED: Instr access perms register write");
                    self.r5_daccessperms = val;
                }
                3 => {
                    warn!("STUBBED: Data access perms register write");
                    self.r5_iaccessperms = val;
                }
                _ => unreachable!()
            },

            6 => {
                warn!("STUBBED: MPU region {} register write", cpreg2);
                self.r6_memregions[cpreg2] = val
            }

            7 => warn!("STUBBED: Cache control register write; reg2={}, op2={}", cpreg2, op2),

            9 => match (cpreg2, op2) {
                (0, 0) => {
                    warn!("STUBBED: DCache lockdown register write");
                    self.r9_dcache_lockdown = val;
                }
                (0, 1) => {
                    warn!("STUBBED: ICache lockdown register write");
                    self.r9_icache_lockdown = val;
                }
                (1, 0) => {
                    warn!("STUBBED: DTCM size register write");
                    self.r9_dtcm_size = val;
                }
                (1, 1) => {
                    warn!("STUBBED: ITCM size register write");
                    self.r9_itcm_size = val;
                }
                _ => unreachable!()
            },

            _ => panic!("Unimplemented CP15 write to coproc reg {}", cpreg1)
        }

        info!("Write 0x{:08X} to CP15 reg {}; reg2={}, op2={}", val, cpreg1, cpreg2, op2);
    }

    fn move_out(&mut self, cpreg1: usize, cpreg2: usize, op1: usize, op2: usize) -> u32 {
        assert_eq!(op1, 0);

        let res = match cpreg1 {
            1 => match op2 {
                0b000 => {
                    warn!("STUBBED: System control register read");
                    self.r1_control.raw()
                }
                0b001 | 0b010 => unimplemented!(),
                _ => unreachable!()
            },

            2 => match op2 {
                0 => {
                    warn!("STUBBED: DCache cacheability register read");
                    self.r2_dcacheability
                }
                1 => {
                    warn!("STUBBED: ICache cacheability register read");
                    self.r2_icacheability
                }
                _ => unreachable!()
            },

            3 => {
                warn!("STUBBED: Data bufferability register read");
                self.r3_bufferability
            }

            5 => match op2 {
                0 | 1 => unimplemented!(),
                2 => {
                    warn!("STUBBED: Instr access perms register read");
                    self.r5_daccessperms
                }
                3 => {
                    warn!("STUBBED: Data access perms register read");
                    self.r5_iaccessperms
                }
                _ => unreachable!()
            },

            6 => {
                warn!("STUBBED: MPU region {} register read", cpreg2);
                self.r6_memregions[cpreg2]
            }

            7 => panic!("Cannot read from cache control register!"),

            9 => match (cpreg2, op2) {
                (0, 0) => {
                    warn!("STUBBED: DCache lockdown register read");
                    self.r9_dcache_lockdown
                }
                (0, 1) => {
                    warn!("STUBBED: ICache lockdown register read");
                    self.r9_icache_lockdown
                }
                (1, 0) => {
                    warn!("STUBBED: DTCM size register read");
                    self.r9_dtcm_size
                }
                (1, 1) => {
                    warn!("STUBBED: ITCM size register read");
                    self.r9_itcm_size
                }
                _ => unreachable!()
            },

            _ => panic!("Unimplemented CP15 read from coproc reg {}", cpreg1)
        };

        info!("Read from CP15 reg {}; reg2={}, op2={}", cpreg1, cpreg2, op2);
        res
    }
}<|endoftext|>


<commit_before><commit_msg>add impl for String for v4<commit_after><|endoftext|>


<commit_before>//! Implementation of intrusive doubly linked list

use core::ptr::Unique;
use core::marker::PhantomData;

use link::Link;

pub trait Node: Sized {
    fn prev(&self) -> &Link<Self>;
    fn next(&self) -> &Link<Self>;

    fn prev_mut(&mut self) -> &mut Link<Self>;
    fn next_mut(&mut self) -> &mut Link<Self>;
}

pub trait Owner<T> where T: Node {
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;

    fn take(self);

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self;
}

pub struct List<T, U> where T: Owner<U>, U: Node {
    head: Link<U>,
    tail: Link<U>,
    _phantom1: PhantomData<T>,
}

impl<T, U> List<T, U> where T: Owner<U>, U: Node {
    pub fn new() -> Self {
        List {
            head: Link::none(),
            tail: Link::none(),
            _phantom1: PhantomData,
        }
    }

    pub fn front(&self) -> Option<&U> {
        self.head.as_ref()
    }

    pub fn back(&self) -> Option<&U> {
        self.tail.as_ref()
    }

    pub fn front_mut(&mut self) -> Option<&mut U> {
        self.head.as_mut()
    }

    pub fn back_mut(&mut self) -> Option<&mut U> {
        self.tail.as_mut()
    }

    pub fn is_empty(&mut self) -> bool {
        self.head == Link::none()
    }

    pub fn push_front(&mut self, mut elem: T) {
        match self.head.as_mut() {
            None => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::none();

                self.tail = Link::some(elem.get_mut());
            }
            Some(h) => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::some(h);

                *h.prev_mut() = Link::some(elem.get_mut());
            },
        }

        self.head = Link::some(elem.get_mut());

        elem.take();
    }

    pub fn push_back(&mut self, mut elem: T) {
        match self.tail.as_mut() {
            None => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::none();

                self.head = Link::some(elem.get_mut());
            }
            Some(t) => {
                *elem.get_mut().prev_mut() = Link::some(t);
                *elem.get_mut().next_mut() = Link::none();

                *t.next_mut() = Link::some(elem.get_mut());
            }
        }

        self.tail = Link::some(elem.get_mut());

        elem.take();
    }

    pub fn pop_front(&mut self) -> Option<T> {
        self.head.take().as_mut().and_then(|h| {
            match h.next_mut().as_mut() {
                None => self.tail = Link::none(),
                Some(n) => {
                    *n.prev_mut() = Link::none();

                    self.head = Link::some(n);
                }
            }

            Some(unsafe { T::from_raw_ptr(h) })
        })
    }

    pub fn pop_back(&mut self) -> Option<T> {
        self.tail.take().as_mut().and_then(|t| {
            match t.prev_mut().as_mut() {
                None => self.head = Link::none(),
                Some(p) => {
                    *p.next_mut() = Link::none();

                    self.tail = Link::some(p);
                }
            }

            Some(unsafe { T::from_raw_ptr(t) })
        })
    }
}

impl<T> Owner<T> for Unique<T> where T: Node {
    #[inline]
    fn get(&self) -> &T {
        unsafe { self.get() }
    }

    #[inline]
    fn get_mut(&mut self) -> &mut T {
        unsafe { self.get_mut() }
    }

    #[inline]
    fn take(self) {}

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(test)]
impl<T> Owner<T> for ::std::boxed::Box<T> where T: Node {
    #[inline]
    fn get(&self) -> &T {
        &**self
    }

    #[inline]
    fn get_mut(&mut self) -> &mut T {
        &mut **self
    }

    #[inline]
    fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}

#[cfg(test)]
mod test {
    use core::ptr::Unique;

    use std::boxed::Box;

    use list::{List, Node};
    use link::Link;

    #[derive(Debug)]
    struct UsizeNode {
        pub data: usize,
        prev: Link<UsizeNode>,
        next: Link<UsizeNode>,
    }

    impl UsizeNode {
        pub fn new(data: usize) -> Self {
            UsizeNode {
                data: data,
                prev: Link::none(),
                next: Link::none(),
            }
        }
    }

    impl Node for UsizeNode {
        fn prev(&self) -> &Link<Self> {
            &self.prev
        }

        fn next(&self) -> &Link<Self> {
            &self.next
        }

        fn prev_mut(&mut self) -> &mut Link<Self> {
            &mut self.prev
        }

        fn next_mut(&mut self) -> &mut Link<Self> {
            &mut self.next
        }
    }

    impl PartialEq for UsizeNode {
        fn eq(&self, rhs: &Self) -> bool { self.data == rhs.data }
    }

    #[test]
    fn test_unique() {
        let one = Box::new(UsizeNode::new(1));
        let two = Box::new(UsizeNode::new(2));
        let three = Box::new(UsizeNode::new(3));

        let one_ptr = Box::into_raw(one);
        let two_ptr = Box::into_raw(two);
        let three_ptr = Box::into_raw(three);

        let one_unique = unsafe { Unique::new(one_ptr) };
        let two_unique = unsafe { Unique::new(two_ptr) };
        let three_unique = unsafe { Unique::new(three_ptr) };

        let mut list = List::<Unique<UsizeNode>, UsizeNode>::new();

        list.push_front(three_unique);
        list.push_front(two_unique);
        list.push_front(one_unique);

        unsafe {
            assert_eq!(list.pop_back().unwrap().get_mut().data, 3);
            assert_eq!(list.pop_back().unwrap().get_mut().data, 2);
            assert_eq!(list.pop_back().unwrap().get_mut().data, 1);
            assert!(list.pop_back().is_none());
        }

        // Cleanup
        unsafe {
            Box::from_raw(one_ptr);
            Box::from_raw(two_ptr);
            Box::from_raw(three_ptr);
        }
    }

    #[test]
    fn test_basic() {
        let mut list = List::<Box<UsizeNode>, UsizeNode>::new();

        assert_eq!(list.front(), None);
        assert_eq!(list.back(), None);

        assert!(list.is_empty());

        list.push_front(Box::new(UsizeNode::new(2)));

        assert!(!list.is_empty());
        assert_eq!(list.front(), list.back());

        list.push_front(Box::new(UsizeNode::new(1)));
        list.push_front(Box::new(UsizeNode::new(0)));

        assert_eq!(list.front().unwrap().data, 0);
        assert_eq!(list.back().unwrap().data, 2);

        list.push_back(Box::new(UsizeNode::new(3)));
        assert_eq!(list.back().unwrap().data, 3);

        list.push_back(Box::new(UsizeNode::new(4)));
        assert_eq!(list.back().unwrap().data, 4);

        assert!(!list.is_empty());

        assert_eq!(list.pop_front().unwrap().data, 0);
        assert_eq!(list.pop_front().unwrap().data, 1);
        assert_eq!(list.pop_front().unwrap().data, 2);
        assert_eq!(list.pop_back().unwrap().data, 4);
        assert_eq!(list.pop_back().unwrap().data, 3);
        assert_eq!(list.pop_back(), None);

        assert!(list.is_empty());

        list.push_back(Box::new(UsizeNode::new(5)));
        assert_eq!(list.pop_front().unwrap().data, 5);
        assert_eq!(list.pop_front(), None);

        assert!(list.is_empty());

        list.push_back(Box::new(UsizeNode::new(6)));
        list.push_back(Box::new(UsizeNode::new(7)));

        assert!(!list.is_empty());

        list.front_mut().unwrap().data = 6;
        list.back_mut().unwrap().data = 7;

        assert_eq!(list.front().unwrap().data, 6);
        assert_eq!(list.back().unwrap().data, 7);

        assert_eq!(list.pop_back().unwrap().data, 7);

        assert!(!list.is_empty());

        assert_eq!(list.pop_front().unwrap().data, 6);
        assert!(list.pop_front().is_none());
        assert!(list.pop_back().is_none());

        assert!(list.is_empty());
    }
}
<commit_msg>libintrusive: List::is_empty does not need to take &mut self<commit_after>//! Implementation of intrusive doubly linked list

use core::ptr::Unique;
use core::marker::PhantomData;

use link::Link;

pub trait Node: Sized {
    fn prev(&self) -> &Link<Self>;
    fn next(&self) -> &Link<Self>;

    fn prev_mut(&mut self) -> &mut Link<Self>;
    fn next_mut(&mut self) -> &mut Link<Self>;
}

pub trait Owner<T> where T: Node {
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;

    fn take(self);

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self;
}

pub struct List<T, U> where T: Owner<U>, U: Node {
    head: Link<U>,
    tail: Link<U>,
    _phantom1: PhantomData<T>,
}

impl<T, U> List<T, U> where T: Owner<U>, U: Node {
    pub fn new() -> Self {
        List {
            head: Link::none(),
            tail: Link::none(),
            _phantom1: PhantomData,
        }
    }

    pub fn front(&self) -> Option<&U> {
        self.head.as_ref()
    }

    pub fn back(&self) -> Option<&U> {
        self.tail.as_ref()
    }

    pub fn front_mut(&mut self) -> Option<&mut U> {
        self.head.as_mut()
    }

    pub fn back_mut(&mut self) -> Option<&mut U> {
        self.tail.as_mut()
    }

    pub fn is_empty(&self) -> bool {
        self.head == Link::none()
    }

    pub fn push_front(&mut self, mut elem: T) {
        match self.head.as_mut() {
            None => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::none();

                self.tail = Link::some(elem.get_mut());
            }
            Some(h) => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::some(h);

                *h.prev_mut() = Link::some(elem.get_mut());
            },
        }

        self.head = Link::some(elem.get_mut());

        elem.take();
    }

    pub fn push_back(&mut self, mut elem: T) {
        match self.tail.as_mut() {
            None => {
                *elem.get_mut().prev_mut() = Link::none();
                *elem.get_mut().next_mut() = Link::none();

                self.head = Link::some(elem.get_mut());
            }
            Some(t) => {
                *elem.get_mut().prev_mut() = Link::some(t);
                *elem.get_mut().next_mut() = Link::none();

                *t.next_mut() = Link::some(elem.get_mut());
            }
        }

        self.tail = Link::some(elem.get_mut());

        elem.take();
    }

    pub fn pop_front(&mut self) -> Option<T> {
        self.head.take().as_mut().and_then(|h| {
            match h.next_mut().as_mut() {
                None => self.tail = Link::none(),
                Some(n) => {
                    *n.prev_mut() = Link::none();

                    self.head = Link::some(n);
                }
            }

            Some(unsafe { T::from_raw_ptr(h) })
        })
    }

    pub fn pop_back(&mut self) -> Option<T> {
        self.tail.take().as_mut().and_then(|t| {
            match t.prev_mut().as_mut() {
                None => self.head = Link::none(),
                Some(p) => {
                    *p.next_mut() = Link::none();

                    self.tail = Link::some(p);
                }
            }

            Some(unsafe { T::from_raw_ptr(t) })
        })
    }
}

impl<T> Owner<T> for Unique<T> where T: Node {
    #[inline]
    fn get(&self) -> &T {
        unsafe { self.get() }
    }

    #[inline]
    fn get_mut(&mut self) -> &mut T {
        unsafe { self.get_mut() }
    }

    #[inline]
    fn take(self) {}

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(test)]
impl<T> Owner<T> for ::std::boxed::Box<T> where T: Node {
    #[inline]
    fn get(&self) -> &T {
        &**self
    }

    #[inline]
    fn get_mut(&mut self) -> &mut T {
        &mut **self
    }

    #[inline]
    fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw_ptr(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}

#[cfg(test)]
mod test {
    use core::ptr::Unique;

    use std::boxed::Box;

    use list::{List, Node};
    use link::Link;

    #[derive(Debug)]
    struct UsizeNode {
        pub data: usize,
        prev: Link<UsizeNode>,
        next: Link<UsizeNode>,
    }

    impl UsizeNode {
        pub fn new(data: usize) -> Self {
            UsizeNode {
                data: data,
                prev: Link::none(),
                next: Link::none(),
            }
        }
    }

    impl Node for UsizeNode {
        fn prev(&self) -> &Link<Self> {
            &self.prev
        }

        fn next(&self) -> &Link<Self> {
            &self.next
        }

        fn prev_mut(&mut self) -> &mut Link<Self> {
            &mut self.prev
        }

        fn next_mut(&mut self) -> &mut Link<Self> {
            &mut self.next
        }
    }

    impl PartialEq for UsizeNode {
        fn eq(&self, rhs: &Self) -> bool { self.data == rhs.data }
    }

    #[test]
    fn test_unique() {
        let one = Box::new(UsizeNode::new(1));
        let two = Box::new(UsizeNode::new(2));
        let three = Box::new(UsizeNode::new(3));

        let one_ptr = Box::into_raw(one);
        let two_ptr = Box::into_raw(two);
        let three_ptr = Box::into_raw(three);

        let one_unique = unsafe { Unique::new(one_ptr) };
        let two_unique = unsafe { Unique::new(two_ptr) };
        let three_unique = unsafe { Unique::new(three_ptr) };

        let mut list = List::<Unique<UsizeNode>, UsizeNode>::new();

        list.push_front(three_unique);
        list.push_front(two_unique);
        list.push_front(one_unique);

        unsafe {
            assert_eq!(list.pop_back().unwrap().get_mut().data, 3);
            assert_eq!(list.pop_back().unwrap().get_mut().data, 2);
            assert_eq!(list.pop_back().unwrap().get_mut().data, 1);
            assert!(list.pop_back().is_none());
        }

        // Cleanup
        unsafe {
            Box::from_raw(one_ptr);
            Box::from_raw(two_ptr);
            Box::from_raw(three_ptr);
        }
    }

    #[test]
    fn test_basic() {
        let mut list = List::<Box<UsizeNode>, UsizeNode>::new();

        assert_eq!(list.front(), None);
        assert_eq!(list.back(), None);

        assert!(list.is_empty());

        list.push_front(Box::new(UsizeNode::new(2)));

        assert!(!list.is_empty());
        assert_eq!(list.front(), list.back());

        list.push_front(Box::new(UsizeNode::new(1)));
        list.push_front(Box::new(UsizeNode::new(0)));

        assert_eq!(list.front().unwrap().data, 0);
        assert_eq!(list.back().unwrap().data, 2);

        list.push_back(Box::new(UsizeNode::new(3)));
        assert_eq!(list.back().unwrap().data, 3);

        list.push_back(Box::new(UsizeNode::new(4)));
        assert_eq!(list.back().unwrap().data, 4);

        assert!(!list.is_empty());

        assert_eq!(list.pop_front().unwrap().data, 0);
        assert_eq!(list.pop_front().unwrap().data, 1);
        assert_eq!(list.pop_front().unwrap().data, 2);
        assert_eq!(list.pop_back().unwrap().data, 4);
        assert_eq!(list.pop_back().unwrap().data, 3);
        assert_eq!(list.pop_back(), None);

        assert!(list.is_empty());

        list.push_back(Box::new(UsizeNode::new(5)));
        assert_eq!(list.pop_front().unwrap().data, 5);
        assert_eq!(list.pop_front(), None);

        assert!(list.is_empty());

        list.push_back(Box::new(UsizeNode::new(6)));
        list.push_back(Box::new(UsizeNode::new(7)));

        assert!(!list.is_empty());

        list.front_mut().unwrap().data = 6;
        list.back_mut().unwrap().data = 7;

        assert_eq!(list.front().unwrap().data, 6);
        assert_eq!(list.back().unwrap().data, 7);

        assert_eq!(list.pop_back().unwrap().data, 7);

        assert!(!list.is_empty());

        assert_eq!(list.pop_front().unwrap().data, 6);
        assert!(list.pop_front().is_none());
        assert!(list.pop_back().is_none());

        assert!(list.is_empty());
    }
}
<|endoftext|>


<commit_before>//! Error types.

use fallible_iterator::FallibleIterator;
use postgres_protocol::message::backend::ErrorFields;
use std::error;
use std::convert::From;
use std::fmt;
use std::io;
use std::result;

pub use self::sqlstate::SqlState;
use {Result, DbErrorNew};

mod sqlstate;

/// The severity of a Postgres error or notice.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Severity {
    /// PANIC
    Panic,
    /// FATAL
    Fatal,
    /// ERROR
    Error,
    /// WARNING
    Warning,
    /// NOTICE
    Notice,
    /// DEBUG
    Debug,
    /// INFO
    Info,
    /// LOG
    Log,
}

impl fmt::Display for Severity {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            Severity::Panic => "PANIC",
            Severity::Fatal => "FATAL",
            Severity::Error => "ERROR",
            Severity::Warning => "WARNING",
            Severity::Notice => "NOTICE",
            Severity::Debug => "DEBUG",
            Severity::Info => "INFO",
            Severity::Log => "LOG",
        };
        fmt.write_str(s)
    }
}

impl Severity {
    fn from_str(s: &str) -> Option<Severity> {
        match s {
            "PANIC" => Some(Severity::Panic),
            "FATAL" => Some(Severity::Fatal),
            "ERROR" => Some(Severity::Error),
            "WARNING" => Some(Severity::Warning),
            "NOTICE" => Some(Severity::Notice),
            "DEBUG" => Some(Severity::Debug),
            "INFO" => Some(Severity::Info),
            "LOG" => Some(Severity::Log),
            _ => None,
        }
    }
}

/// A Postgres error or notice.
#[derive(Clone, PartialEq, Eq)]
pub struct DbError {
    /// The field contents are ERROR, FATAL, or PANIC (in an error message),
    /// or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a
    /// localized translation of one of these.
    pub severity: String,

    /// A parsed, nonlocalized version of `severity`. (PostgreSQL 9.6+)
    pub parsed_severity: Option<Severity>,

    /// The SQLSTATE code for the error.
    pub code: SqlState,

    /// The primary human-readable error message. This should be accurate but
    /// terse (typically one line).
    pub message: String,

    /// An optional secondary error message carrying more detail about the
    /// problem. Might run to multiple lines.
    pub detail: Option<String>,

    /// An optional suggestion what to do about the problem. This is intended
    /// to differ from Detail in that it offers advice (potentially
    /// inappropriate) rather than hard facts. Might run to multiple lines.
    pub hint: Option<String>,

    /// An optional error cursor position into either the original query string
    /// or an internally generated query.
    pub position: Option<ErrorPosition>,

    /// An indication of the context in which the error occurred. Presently
    /// this includes a call stack traceback of active procedural language
    /// functions and internally-generated queries. The trace is one entry per
    /// line, most recent first.
    pub where_: Option<String>,

    /// If the error was associated with a specific database object, the name
    /// of the schema containing that object, if any. (PostgreSQL 9.3+)
    pub schema: Option<String>,

    /// If the error was associated with a specific table, the name of the
    /// table. (Refer to the schema name field for the name of the table's
    /// schema.) (PostgreSQL 9.3+)
    pub table: Option<String>,

    /// If the error was associated with a specific table column, the name of
    /// the column. (Refer to the schema and table name fields to identify the
    /// table.) (PostgreSQL 9.3+)
    pub column: Option<String>,

    /// If the error was associated with a specific data type, the name of the
    /// data type. (Refer to the schema name field for the name of the data
    /// type's schema.) (PostgreSQL 9.3+)
    pub datatype: Option<String>,

    /// If the error was associated with a specific constraint, the name of the
    /// constraint. Refer to fields listed above for the associated table or
    /// domain. (For this purpose, indexes are treated as constraints, even if
    /// they weren't created with constraint syntax.) (PostgreSQL 9.3+)
    pub constraint: Option<String>,

    /// The file name of the source-code location where the error was reported.
    pub file: Option<String>,

    /// The line number of the source-code location where the error was
    /// reported.
    pub line: Option<u32>,

    /// The name of the source-code routine reporting the error.
    pub routine: Option<String>,

    _p: (),
}

impl DbErrorNew for DbError {
    fn new_raw(fields: &mut ErrorFields) -> io::Result<DbError> {
        let mut severity = None;
        let mut parsed_severity = None;
        let mut code = None;
        let mut message = None;
        let mut detail = None;
        let mut hint = None;
        let mut normal_position = None;
        let mut internal_position = None;
        let mut internal_query = None;
        let mut where_ = None;
        let mut schema = None;
        let mut table = None;
        let mut column = None;
        let mut datatype = None;
        let mut constraint = None;
        let mut file = None;
        let mut line = None;
        let mut routine = None;

        while let Some(field) = try!(fields.next()) {
            match field.type_() {
                b'S' => severity = Some(field.value().to_owned()),
                b'C' => code = Some(SqlState::from_code(field.value())),
                b'M' => message = Some(field.value().to_owned()),
                b'D' => detail = Some(field.value().to_owned()),
                b'H' => hint = Some(field.value().to_owned()),
                b'P' => normal_position = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))),
                b'p' => internal_position = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))),
                b'q' => internal_query = Some(field.value().to_owned()),
                b'W' => where_ = Some(field.value().to_owned()),
                b's' => schema = Some(field.value().to_owned()),
                b't' => table = Some(field.value().to_owned()),
                b'c' => column = Some(field.value().to_owned()),
                b'd' => datatype = Some(field.value().to_owned()),
                b'n' => constraint = Some(field.value().to_owned()),
                b'F' => file = Some(field.value().to_owned()),
                b'L' => line = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))),
                b'R' => routine = Some(field.value().to_owned()),
                b'V' => parsed_severity = Some(try!(Severity::from_str(field.value()).ok_or_else(::bad_response))),
                _ => {},
            }
        }

        Ok(DbError {
            severity: try!(severity.ok_or_else(|| ::bad_response())),
            parsed_severity: parsed_severity,
            code: try!(code.ok_or_else(|| ::bad_response())),
            message: try!(message.ok_or_else(|| ::bad_response())),
            detail: detail,
            hint: hint,
            position: match normal_position {
                Some(position) => Some(ErrorPosition::Normal(position)),
                None => {
                    match internal_position {
                        Some(position) => {
                            Some(ErrorPosition::Internal {
                                position: position,
                                query: try!(internal_query.ok_or_else(|| ::bad_response())),
                            })
                        }
                        None => None,
                    }
                }
            },
            where_: where_,
            schema: schema,
            table: table,
            column: column,
            datatype: datatype,
            constraint: constraint,
            file: file,
            line: line,
            routine: routine,
            _p: (),
        })
    }

    fn new_connect<T>(fields: &mut ErrorFields) -> result::Result<T, ConnectError> {
        match DbError::new_raw(fields) {
            Ok(err) => Err(ConnectError::Db(Box::new(err))),
            Err(e) => Err(ConnectError::Io(e)),
        }
    }

    fn new<T>(fields: &mut ErrorFields) -> Result<T> {
        match DbError::new_raw(fields) {
            Ok(err) => Err(Error::Db(Box::new(err))),
            Err(e) => Err(Error::Io(e)),
        }
    }
}

// manual impl to leave out _p
impl fmt::Debug for DbError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("DbError")
            .field("severity", &self.severity)
            .field("code", &self.code)
            .field("message", &self.message)
            .field("detail", &self.detail)
            .field("hint", &self.hint)
            .field("position", &self.position)
            .field("where_", &self.where_)
            .field("schema", &self.schema)
            .field("table", &self.table)
            .field("column", &self.column)
            .field("datatype", &self.datatype)
            .field("constraint", &self.constraint)
            .field("file", &self.file)
            .field("line", &self.line)
            .field("routine", &self.routine)
            .finish()
    }
}

impl fmt::Display for DbError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}: {}", self.severity, self.message)
    }
}

impl error::Error for DbError {
    fn description(&self) -> &str {
        &self.message
    }
}

/// Reasons a new Postgres connection could fail.
#[derive(Debug)]
pub enum ConnectError {
    /// An error relating to connection parameters.
    ConnectParams(Box<error::Error + Sync + Send>),
    /// An error from the Postgres server itself.
    Db(Box<DbError>),
    /// An error initializing the TLS session.
    Tls(Box<error::Error + Sync + Send>),
    /// An error communicating with the server.
    Io(io::Error),
}

impl fmt::Display for ConnectError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str(error::Error::description(self)));
        match *self {
            ConnectError::ConnectParams(ref msg) => write!(fmt, ": {}", msg),
            ConnectError::Db(ref err) => write!(fmt, ": {}", err),
            ConnectError::Tls(ref err) => write!(fmt, ": {}", err),
            ConnectError::Io(ref err) => write!(fmt, ": {}", err),
        }
    }
}

impl error::Error for ConnectError {
    fn description(&self) -> &str {
        match *self {
            ConnectError::ConnectParams(_) => "Invalid connection parameters",
            ConnectError::Db(_) => "Error reported by Postgres",
            ConnectError::Tls(_) => "Error initiating SSL session",
            ConnectError::Io(_) => "Error communicating with the server",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ConnectError::ConnectParams(ref err) |
            ConnectError::Tls(ref err) => Some(&**err),
            ConnectError::Db(ref err) => Some(&**err),
            ConnectError::Io(ref err) => Some(err),
        }
    }
}

impl From<io::Error> for ConnectError {
    fn from(err: io::Error) -> ConnectError {
        ConnectError::Io(err)
    }
}

impl From<DbError> for ConnectError {
    fn from(err: DbError) -> ConnectError {
        ConnectError::Db(Box::new(err))
    }
}

/// Represents the position of an error in a query.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ErrorPosition {
    /// A position in the original query.
    Normal(u32),
    /// A position in an internally generated query.
    Internal {
        /// The byte position.
        position: u32,
        /// A query generated by the Postgres server.
        query: String,
    },
}

/// An error encountered when communicating with the Postgres server.
#[derive(Debug)]
pub enum Error {
    /// An error reported by the Postgres server.
    Db(Box<DbError>),
    /// An error communicating with the Postgres server.
    Io(io::Error),
    /// An error converting between Postgres and Rust types.
    Conversion(Box<error::Error + Sync + Send>),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str(error::Error::description(self)));
        match *self {
            Error::Db(ref err) => write!(fmt, ": {}", err),
            Error::Io(ref err) => write!(fmt, ": {}", err),
            Error::Conversion(ref err) => write!(fmt, ": {}", err),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Db(_) => "Error reported by Postgres",
            Error::Io(_) => "Error communicating with the server",
            Error::Conversion(_) => "Error converting between Postgres and Rust types",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Db(ref err) => Some(&**err),
            Error::Io(ref err) => Some(err),
            Error::Conversion(ref err) => Some(&**err),
        }
    }
}

impl From<DbError> for Error {
    fn from(err: DbError) -> Error {
        Error::Db(Box::new(err))
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        io::Error::new(io::ErrorKind::Other, err)
    }
}
<commit_msg>Add new field to debug impl<commit_after>//! Error types.

use fallible_iterator::FallibleIterator;
use postgres_protocol::message::backend::ErrorFields;
use std::error;
use std::convert::From;
use std::fmt;
use std::io;
use std::result;

pub use self::sqlstate::SqlState;
use {Result, DbErrorNew};

mod sqlstate;

/// The severity of a Postgres error or notice.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Severity {
    /// PANIC
    Panic,
    /// FATAL
    Fatal,
    /// ERROR
    Error,
    /// WARNING
    Warning,
    /// NOTICE
    Notice,
    /// DEBUG
    Debug,
    /// INFO
    Info,
    /// LOG
    Log,
}

impl fmt::Display for Severity {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            Severity::Panic => "PANIC",
            Severity::Fatal => "FATAL",
            Severity::Error => "ERROR",
            Severity::Warning => "WARNING",
            Severity::Notice => "NOTICE",
            Severity::Debug => "DEBUG",
            Severity::Info => "INFO",
            Severity::Log => "LOG",
        };
        fmt.write_str(s)
    }
}

impl Severity {
    fn from_str(s: &str) -> Option<Severity> {
        match s {
            "PANIC" => Some(Severity::Panic),
            "FATAL" => Some(Severity::Fatal),
            "ERROR" => Some(Severity::Error),
            "WARNING" => Some(Severity::Warning),
            "NOTICE" => Some(Severity::Notice),
            "DEBUG" => Some(Severity::Debug),
            "INFO" => Some(Severity::Info),
            "LOG" => Some(Severity::Log),
            _ => None,
        }
    }
}

/// A Postgres error or notice.
#[derive(Clone, PartialEq, Eq)]
pub struct DbError {
    /// The field contents are ERROR, FATAL, or PANIC (in an error message),
    /// or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a
    /// localized translation of one of these.
    pub severity: String,

    /// A parsed, nonlocalized version of `severity`. (PostgreSQL 9.6+)
    pub parsed_severity: Option<Severity>,

    /// The SQLSTATE code for the error.
    pub code: SqlState,

    /// The primary human-readable error message. This should be accurate but
    /// terse (typically one line).
    pub message: String,

    /// An optional secondary error message carrying more detail about the
    /// problem. Might run to multiple lines.
    pub detail: Option<String>,

    /// An optional suggestion what to do about the problem. This is intended
    /// to differ from Detail in that it offers advice (potentially
    /// inappropriate) rather than hard facts. Might run to multiple lines.
    pub hint: Option<String>,

    /// An optional error cursor position into either the original query string
    /// or an internally generated query.
    pub position: Option<ErrorPosition>,

    /// An indication of the context in which the error occurred. Presently
    /// this includes a call stack traceback of active procedural language
    /// functions and internally-generated queries. The trace is one entry per
    /// line, most recent first.
    pub where_: Option<String>,

    /// If the error was associated with a specific database object, the name
    /// of the schema containing that object, if any. (PostgreSQL 9.3+)
    pub schema: Option<String>,

    /// If the error was associated with a specific table, the name of the
    /// table. (Refer to the schema name field for the name of the table's
    /// schema.) (PostgreSQL 9.3+)
    pub table: Option<String>,

    /// If the error was associated with a specific table column, the name of
    /// the column. (Refer to the schema and table name fields to identify the
    /// table.) (PostgreSQL 9.3+)
    pub column: Option<String>,

    /// If the error was associated with a specific data type, the name of the
    /// data type. (Refer to the schema name field for the name of the data
    /// type's schema.) (PostgreSQL 9.3+)
    pub datatype: Option<String>,

    /// If the error was associated with a specific constraint, the name of the
    /// constraint. Refer to fields listed above for the associated table or
    /// domain. (For this purpose, indexes are treated as constraints, even if
    /// they weren't created with constraint syntax.) (PostgreSQL 9.3+)
    pub constraint: Option<String>,

    /// The file name of the source-code location where the error was reported.
    pub file: Option<String>,

    /// The line number of the source-code location where the error was
    /// reported.
    pub line: Option<u32>,

    /// The name of the source-code routine reporting the error.
    pub routine: Option<String>,

    _p: (),
}

impl DbErrorNew for DbError {
    fn new_raw(fields: &mut ErrorFields) -> io::Result<DbError> {
        let mut severity = None;
        let mut parsed_severity = None;
        let mut code = None;
        let mut message = None;
        let mut detail = None;
        let mut hint = None;
        let mut normal_position = None;
        let mut internal_position = None;
        let mut internal_query = None;
        let mut where_ = None;
        let mut schema = None;
        let mut table = None;
        let mut column = None;
        let mut datatype = None;
        let mut constraint = None;
        let mut file = None;
        let mut line = None;
        let mut routine = None;

        while let Some(field) = try!(fields.next()) {
            match field.type_() {
                b'S' => severity = Some(field.value().to_owned()),
                b'C' => code = Some(SqlState::from_code(field.value())),
                b'M' => message = Some(field.value().to_owned()),
                b'D' => detail = Some(field.value().to_owned()),
                b'H' => hint = Some(field.value().to_owned()),
                b'P' => normal_position = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))),
                b'p' => internal_position = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))),
                b'q' => internal_query = Some(field.value().to_owned()),
                b'W' => where_ = Some(field.value().to_owned()),
                b's' => schema = Some(field.value().to_owned()),
                b't' => table = Some(field.value().to_owned()),
                b'c' => column = Some(field.value().to_owned()),
                b'd' => datatype = Some(field.value().to_owned()),
                b'n' => constraint = Some(field.value().to_owned()),
                b'F' => file = Some(field.value().to_owned()),
                b'L' => line = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))),
                b'R' => routine = Some(field.value().to_owned()),
                b'V' => parsed_severity = Some(try!(Severity::from_str(field.value()).ok_or_else(::bad_response))),
                _ => {},
            }
        }

        Ok(DbError {
            severity: try!(severity.ok_or_else(|| ::bad_response())),
            parsed_severity: parsed_severity,
            code: try!(code.ok_or_else(|| ::bad_response())),
            message: try!(message.ok_or_else(|| ::bad_response())),
            detail: detail,
            hint: hint,
            position: match normal_position {
                Some(position) => Some(ErrorPosition::Normal(position)),
                None => {
                    match internal_position {
                        Some(position) => {
                            Some(ErrorPosition::Internal {
                                position: position,
                                query: try!(internal_query.ok_or_else(|| ::bad_response())),
                            })
                        }
                        None => None,
                    }
                }
            },
            where_: where_,
            schema: schema,
            table: table,
            column: column,
            datatype: datatype,
            constraint: constraint,
            file: file,
            line: line,
            routine: routine,
            _p: (),
        })
    }

    fn new_connect<T>(fields: &mut ErrorFields) -> result::Result<T, ConnectError> {
        match DbError::new_raw(fields) {
            Ok(err) => Err(ConnectError::Db(Box::new(err))),
            Err(e) => Err(ConnectError::Io(e)),
        }
    }

    fn new<T>(fields: &mut ErrorFields) -> Result<T> {
        match DbError::new_raw(fields) {
            Ok(err) => Err(Error::Db(Box::new(err))),
            Err(e) => Err(Error::Io(e)),
        }
    }
}

// manual impl to leave out _p
impl fmt::Debug for DbError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("DbError")
            .field("severity", &self.severity)
            .field("parsed_severity", &self.parsed_severity)
            .field("code", &self.code)
            .field("message", &self.message)
            .field("detail", &self.detail)
            .field("hint", &self.hint)
            .field("position", &self.position)
            .field("where_", &self.where_)
            .field("schema", &self.schema)
            .field("table", &self.table)
            .field("column", &self.column)
            .field("datatype", &self.datatype)
            .field("constraint", &self.constraint)
            .field("file", &self.file)
            .field("line", &self.line)
            .field("routine", &self.routine)
            .finish()
    }
}

impl fmt::Display for DbError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}: {}", self.severity, self.message)
    }
}

impl error::Error for DbError {
    fn description(&self) -> &str {
        &self.message
    }
}

/// Reasons a new Postgres connection could fail.
#[derive(Debug)]
pub enum ConnectError {
    /// An error relating to connection parameters.
    ConnectParams(Box<error::Error + Sync + Send>),
    /// An error from the Postgres server itself.
    Db(Box<DbError>),
    /// An error initializing the TLS session.
    Tls(Box<error::Error + Sync + Send>),
    /// An error communicating with the server.
    Io(io::Error),
}

impl fmt::Display for ConnectError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str(error::Error::description(self)));
        match *self {
            ConnectError::ConnectParams(ref msg) => write!(fmt, ": {}", msg),
            ConnectError::Db(ref err) => write!(fmt, ": {}", err),
            ConnectError::Tls(ref err) => write!(fmt, ": {}", err),
            ConnectError::Io(ref err) => write!(fmt, ": {}", err),
        }
    }
}

impl error::Error for ConnectError {
    fn description(&self) -> &str {
        match *self {
            ConnectError::ConnectParams(_) => "Invalid connection parameters",
            ConnectError::Db(_) => "Error reported by Postgres",
            ConnectError::Tls(_) => "Error initiating SSL session",
            ConnectError::Io(_) => "Error communicating with the server",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ConnectError::ConnectParams(ref err) |
            ConnectError::Tls(ref err) => Some(&**err),
            ConnectError::Db(ref err) => Some(&**err),
            ConnectError::Io(ref err) => Some(err),
        }
    }
}

impl From<io::Error> for ConnectError {
    fn from(err: io::Error) -> ConnectError {
        ConnectError::Io(err)
    }
}

impl From<DbError> for ConnectError {
    fn from(err: DbError) -> ConnectError {
        ConnectError::Db(Box::new(err))
    }
}

/// Represents the position of an error in a query.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ErrorPosition {
    /// A position in the original query.
    Normal(u32),
    /// A position in an internally generated query.
    Internal {
        /// The byte position.
        position: u32,
        /// A query generated by the Postgres server.
        query: String,
    },
}

/// An error encountered when communicating with the Postgres server.
#[derive(Debug)]
pub enum Error {
    /// An error reported by the Postgres server.
    Db(Box<DbError>),
    /// An error communicating with the Postgres server.
    Io(io::Error),
    /// An error converting between Postgres and Rust types.
    Conversion(Box<error::Error + Sync + Send>),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str(error::Error::description(self)));
        match *self {
            Error::Db(ref err) => write!(fmt, ": {}", err),
            Error::Io(ref err) => write!(fmt, ": {}", err),
            Error::Conversion(ref err) => write!(fmt, ": {}", err),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Db(_) => "Error reported by Postgres",
            Error::Io(_) => "Error communicating with the server",
            Error::Conversion(_) => "Error converting between Postgres and Rust types",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Db(ref err) => Some(&**err),
            Error::Io(ref err) => Some(err),
            Error::Conversion(ref err) => Some(&**err),
        }
    }
}

impl From<DbError> for Error {
    fn from(err: DbError) -> Error {
        Error::Db(Box::new(err))
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        io::Error::new(io::ErrorKind::Other, err)
    }
}
<|endoftext|>