<commit_before>use std::cmp::PartialEq;
use std::fmt::Debug;

#[derive(Debug)]
pub struct Spec<'s, S: 's> {
    subject: &'s S,
}

pub fn assert_that<'s, S>(subject: &'s S) -> Spec<'s, S> {
    Spec { subject: subject }
}

impl<'s, S> Spec<'s, S> where S: Debug + PartialEq {
    pub fn is_equal_to(&self, expected: &S) {
        if !self.subject.eq(expected) {
            panic!(format!("expected <{:?}> but was <{:?}>", expected, self.subject));
        }
    }
}

impl<'s, T> Spec<'s, Vec<T>> where T: Debug + PartialEq {
    pub fn has_length(&self, expected: usize) {
        let length = self.subject.len();
        if length != expected {
            panic!(format!("expected vec with length of <{:?}> but was <{:?}>", expected, length));
        }
    }

    pub fn contains(&self, expected_value: &T) {
        if !self.subject.contains(expected_value) {
            Self::panic_unmatched(expected_value, self.subject);
        }
    }

    pub fn mapped_contains<F, M: 's>(&self, mapping_function: F, expected_value: &M)
        where M: Debug + PartialEq, F: Fn(&'s T) -> &M {
            let mapped_vec: Vec<&M> = self.subject.iter().map(mapping_function).collect();
            if !mapped_vec.contains(&expected_value) {
                Self::panic_unmatched(expected_value, mapped_vec);
            }
        }

    fn panic_unmatched<E: Debug, A: Debug>(expected: E, actual: A) {
        panic!(format!("expected vec to contain <{:?}> but contains <{:?}>", expected, actual));
    }
}

impl<'s, T> Spec<'s, Option<T>> where T: Debug + PartialEq {
    pub fn contains_value(&self, expected_value: &T) {
        match self.subject {
            &Some(ref val) => {
                if !val.eq(expected_value) {
                    panic!(build_failure_string(&format!("<{:?}>", expected_value), &format!("<{:?}>", val)));
                }
            },
            &None => panic!(build_failure_string(&format!("<{:?}>", expected_value), "empty"))
        };

        fn build_failure_string(containing: &str, actual: &str) -> String {
            format!("expected option containing {} but was {}", containing, actual)
        }
    }

    pub fn is_some(&self) {
        match self.subject {
            &Some(_) => (),
            &None => panic!(format!("expected non-empty option but was empty")),
        };
    }

    pub fn is_none(&self) {
        match self.subject {
            &None => (),
            &Some(ref val) => panic!(format!("expected empty option but contained <{:?}>", val))
        };
    }
}

impl<'s, T, E> Spec<'s, Result<T, E>> where T: Debug, E: Debug {
    pub fn is_ok(&self) {
        match self.subject {
            &Ok(_) => (),
            &Err(ref err) => panic!(format!("expected ok result but was error result of <{:?}>", err)),
        };
    }

    pub fn is_error(&self) {
        match self.subject {
            &Err(_) => (),
            &Ok(ref val) => panic!(format!("expected error result but was ok result of <{:?}>", val)),
        };
    }
}

impl<'s, S> Spec<'s, S> {
    pub fn map<F, T>(self, mapping_function: F) -> Spec<'s, T>
        where F: Fn(&'s S) -> &'s T {
            Spec { subject: mapping_function(self.subject) }
        }
}
<commit_msg>Formatting changes thanks to rustfmt<commit_after>use std::cmp::PartialEq;
use std::fmt::Debug;

#[derive(Debug)]
pub struct Spec<'s, S: 's> {
    subject: &'s S,
}

pub fn assert_that<'s, S>(subject: &'s S) -> Spec<'s, S> {
    Spec { subject: subject }
}

impl<'s, S> Spec<'s, S>
    where S: Debug + PartialEq
{
    pub fn is_equal_to(&self, expected: &S) {
        if !self.subject.eq(expected) {
            panic!(format!("expected <{:?}> but was <{:?}>", expected, self.subject));
        }
    }
}

impl<'s, T> Spec<'s, Vec<T>>
    where T: Debug + PartialEq
{
    pub fn has_length(&self, expected: usize) {
        let length = self.subject.len();
        if length != expected {
            panic!(format!("expected vec with length of <{:?}> but was <{:?}>",
                           expected,
                           length));
        }
    }

    pub fn contains(&self, expected_value: &T) {
        if !self.subject.contains(expected_value) {
            Self::panic_unmatched(expected_value, self.subject);
        }
    }

    pub fn mapped_contains<F, M: 's>(&self, mapping_function: F, expected_value: &M)
        where M: Debug + PartialEq,
              F: Fn(&'s T) -> &M
    {
        let mapped_vec: Vec<&M> = self.subject.iter().map(mapping_function).collect();
        if !mapped_vec.contains(&expected_value) {
            Self::panic_unmatched(expected_value, mapped_vec);
        }
    }

    fn panic_unmatched<E: Debug, A: Debug>(expected: E, actual: A) {
        panic!(format!("expected vec to contain <{:?}> but contains <{:?}>",
                       expected,
                       actual));
    }
}

impl<'s, T> Spec<'s, Option<T>>
    where T: Debug + PartialEq
{
    pub fn contains_value(&self, expected_value: &T) {
        match self.subject {
            &Some(ref val) => {
                if !val.eq(expected_value) {
                    panic!(build_failure_string(&format!("<{:?}>", expected_value),
                                                &format!("<{:?}>", val)));
                }
            }
            &None => panic!(build_failure_string(&format!("<{:?}>", expected_value), "empty")),
        };

        fn build_failure_string(containing: &str, actual: &str) -> String {
            format!("expected option containing {} but was {}",
                    containing,
                    actual)
        }
    }

    pub fn is_some(&self) {
        match self.subject {
            &Some(_) => (),
            &None => panic!(format!("expected non-empty option but was empty")),
        };
    }

    pub fn is_none(&self) {
        match self.subject {
            &None => (),
            &Some(ref val) => panic!(format!("expected empty option but contained <{:?}>", val)),
        };
    }
}

impl<'s, T, E> Spec<'s, Result<T, E>>
    where T: Debug,
          E: Debug
{
    pub fn is_ok(&self) {
        match self.subject {
            &Ok(_) => (),
            &Err(ref err) => {
                panic!(format!("expected ok result but was error result of <{:?}>", err))
            }
        };
    }

    pub fn is_error(&self) {
        match self.subject {
            &Err(_) => (),
            &Ok(ref val) => {
                panic!(format!("expected error result but was ok result of <{:?}>", val))
            }
        };
    }
}

impl<'s, S> Spec<'s, S> {
    pub fn map<F, T>(self, mapping_function: F) -> Spec<'s, T>
        where F: Fn(&'s S) -> &'s T
    {
        Spec { subject: mapping_function(self.subject) }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Kai Strempel
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_type = "lib"]
#![crate_name = "docker"]

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate curl;

#[macro_use]
mod common;
mod error;

pub mod images;
pub mod networks;
pub mod containers;

use std::str::*;
use std::cell::RefCell;

use curl::easy::Easy;

use error::DockerError;
use images::ImagesClient;
use containers::ContainersClient;
use networks::NetworksClient;

use std::error::Error;

pub struct Client {
    api_url: String,
    curl : RefCell<Easy>
}

impl Client {

    pub fn new(api_url: &str) -> Client {
        let client = Client {
            api_url : String::from_str(api_url).unwrap(),
            curl : RefCell::new(Easy::new())
        };
        client.set_curl_client();

        client
    }

    pub fn from_env() -> Client {
        Client::new("http://v1.26/")
    }

    fn set_curl_client(&self) -> ()  {
        let mut curl = self.curl.borrow_mut();
        let _ = curl.unix_socket("/var/run/docker.sock");
    }

    fn get(&self, url: &str) -> Result<String, DockerError> {
        let mut result = Vec::new();
        let real_url = format!("{}{}", self.api_url, url);
        let mut curl = self.curl.borrow_mut();
        match curl.url(real_url.as_str()) {
            Ok(_) => {
                let mut transfer = curl.transfer();
                transfer.write_function(|data| {
                    result.extend_from_slice(data);
                    Ok(data.len())
                }).unwrap();
                transfer.perform().unwrap();
            },
            Err(err) => {
                print!("Mein Text {}", err.description());
            }
        };

        Ok(String::from_utf8(result).unwrap())
    }

    pub fn images(&self) -> ImagesClient {
        ImagesClient::new(self)
    }
    pub fn containers(&self) -> ContainersClient {
        ContainersClient::new(self)
    }

    pub fn networks(&self) -> NetworksClient {
        NetworksClient::new(self)
    }
}
<commit_msg>moves lib to docker api v1.27<commit_after>// Copyright 2017 Kai Strempel
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_type = "lib"]
#![crate_name = "docker"]

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate curl;

#[macro_use]
mod common;
mod error;

pub mod images;
pub mod networks;
pub mod containers;

use std::str::*;
use std::cell::RefCell;

use curl::easy::Easy;

use error::DockerError;
use images::ImagesClient;
use containers::ContainersClient;
use networks::NetworksClient;

use std::error::Error;

pub struct Client {
    api_url: String,
    curl : RefCell<Easy>
}

impl Client {

    pub fn new(api_url: &str) -> Client {
        let client = Client {
            api_url : String::from_str(api_url).unwrap(),
            curl : RefCell::new(Easy::new())
        };
        client.set_curl_client();

        client
    }

    pub fn from_env() -> Client {
        Client::new("http://v1.27/")
    }

    fn set_curl_client(&self) -> ()  {
        let mut curl = self.curl.borrow_mut();
        let _ = curl.unix_socket("/var/run/docker.sock");
    }

    fn get(&self, url: &str) -> Result<String, DockerError> {
        let mut result = Vec::new();
        let real_url = format!("{}{}", self.api_url, url);
        let mut curl = self.curl.borrow_mut();
        match curl.url(real_url.as_str()) {
            Ok(_) => {
                let mut transfer = curl.transfer();
                transfer.write_function(|data| {
                    result.extend_from_slice(data);
                    Ok(data.len())
                }).unwrap();
                transfer.perform().unwrap();
            },
            Err(err) => {
                print!("Mein Text {}", err.description());
            }
        };

        Ok(String::from_utf8(result).unwrap())
    }

    pub fn images(&self) -> ImagesClient {
        ImagesClient::new(self)
    }
    pub fn containers(&self) -> ContainersClient {
        ContainersClient::new(self)
    }

    pub fn networks(&self) -> NetworksClient {
        NetworksClient::new(self)
    }
}
<|endoftext|>


<commit_before>//! A safe wrapper for the [`c-ares`](http://c-ares.haxx.se) library.
//!
//! Usage is as follows:
//!
//! -  Create a `Channel`.
//!
//! -  Make queries on the channel.  Queries all take callbacks, which will be
//!    called when the query completes.
//!
//! -  Have `c-ares` tell you what file descriptors to listen on for read and /
//!    or write events.  You can do this either by providing a callback, which
//!    is called whenever the set of interesting file descriptors changes, or
//!    by querying the `Channel` directly with `get_sock()`.
//!
//! -  Do as `c-ares` asks!  That it, listen for the events that it requests,
//!    on the file descriptors that it cares about.
//!
//! -  When a file descriptor becomes readable or writable, call `process_fd()`
//!    on the channel to tell `c-ares` what has happened.
//!
//! -  `c-ares` doesn't create any threads of its own.  So if you have queries
//!    pending and don't see events happening, you still need to call
//!    `process_fd()` at some point anyway - to give `c-ares` an opportunity to
//!    process any requests that have timed out.
//!
//! Complete examples showing how to use the library can be found
//! [here](https://github.com/dimbleby/rust-c-ares/tree/master/examples).
#[macro_use] extern crate bitflags;
mod a;
mod aaaa;
mod srv;
mod channel;
mod cname;
pub mod flags;
mod host;
mod mx;
mod nameinfo;
mod naptr;
pub mod ni_flags;
mod ns;
mod ptr;
mod types;
mod txt;
mod soa;
mod utils;

// Re-export public interfaces.
pub use a::{
    AResult,
    AResults,
};
pub use aaaa::{
    AAAAResult,
    AAAAResults,
};
pub use srv::{
    SRVResult,
    SRVResults,
};
pub use channel::{
    Channel,
    GetSock,
    GetSockIterator,
    Options,
};
pub use cname::CNameResult;
pub use host::{
    HostAddressResult,
    HostAliasResult,
    HostResults,
};
pub use mx::{
    MXResult,
    MXResults,
};
pub use nameinfo::{
    NameInfoResult,
};
pub use naptr::{
    NAPTRResult,
    NAPTRResults,
};
pub use ns::{
    NSResult,
    NSResults,
};
pub use ptr::{
    PTRResult,
    PTRResults,
};
pub use types::{
    AddressFamily,
    AresError,
    INVALID_FD,
    IpAddr,
};
pub use txt::{
    TXTResult,
    TXTResults,
};
pub use soa::SOAResult;
pub use utils::str_error;
<commit_msg>Docs consistency<commit_after>//! A safe wrapper for the [`c-ares`](http://c-ares.haxx.se) library.
//!
//! Usage is as follows:
//!
//! -  Create a `Channel`.
//!
//! -  Make queries on the `Channel`.  Queries all take callbacks, which will
//!    be called when the query completes.
//!
//! -  Have `c-ares` tell you what file descriptors to listen on for read and /
//!    or write events.  You can do this either by providing a callback, which
//!    is called whenever the set of interesting file descriptors changes, or
//!    by querying the `Channel` directly with `get_sock()`.
//!
//! -  Do as `c-ares` asks!  That it, listen for the events that it requests,
//!    on the file descriptors that it cares about.
//!
//! -  When a file descriptor becomes readable or writable, call `process_fd()`
//!    on the `Channel` to tell `c-ares` what has happened.
//!
//! -  `c-ares` doesn't create any threads of its own.  So if you have queries
//!    pending and don't see events happening, you still need to call
//!    `process_fd()` at some point anyway - to give `c-ares` an opportunity to
//!    process any requests that have timed out.
//!
//! Complete examples showing how to use the library can be found
//! [here](https://github.com/dimbleby/rust-c-ares/tree/master/examples).
#[macro_use] extern crate bitflags;
mod a;
mod aaaa;
mod srv;
mod channel;
mod cname;
pub mod flags;
mod host;
mod mx;
mod nameinfo;
mod naptr;
pub mod ni_flags;
mod ns;
mod ptr;
mod types;
mod txt;
mod soa;
mod utils;

// Re-export public interfaces.
pub use a::{
    AResult,
    AResults,
};
pub use aaaa::{
    AAAAResult,
    AAAAResults,
};
pub use srv::{
    SRVResult,
    SRVResults,
};
pub use channel::{
    Channel,
    GetSock,
    GetSockIterator,
    Options,
};
pub use cname::CNameResult;
pub use host::{
    HostAddressResult,
    HostAliasResult,
    HostResults,
};
pub use mx::{
    MXResult,
    MXResults,
};
pub use nameinfo::{
    NameInfoResult,
};
pub use naptr::{
    NAPTRResult,
    NAPTRResults,
};
pub use ns::{
    NSResult,
    NSResults,
};
pub use ptr::{
    PTRResult,
    PTRResults,
};
pub use types::{
    AddressFamily,
    AresError,
    INVALID_FD,
    IpAddr,
};
pub use txt::{
    TXTResult,
    TXTResults,
};
pub use soa::SOAResult;
pub use utils::str_error;
<|endoftext|>


<commit_before>//! The couchdb crate provides low-level access to individual HTTP actions—e.g.,
//! PUT database, GET document, etc. It handles the menial task of sending
//! requests and receiving responses, thereby allowing application programmers
//! to focus on their business logic.
//!
//! This documentation has been written assuming the application programmer is
//! familiar with the CouchDB API. Descriptions of types, methods, etc. in the
//! couchdb crate should provide just enough information for the programmer to
//! map the crate's concepts onto the CouchDB API and then use the CouchDB
//! documentation as needed to fill in remaining details. Most names in the
//! crate API are identical to the names used in the CouchDB API so as to make
//! this mapping straightforward. There's also a table, below, that [shows the
//! mapping at a high level](#couchdb-api-coverage).
//!
//! One key difference between the couchdb crate's API and the CouchDB API is
//! the crate provides stronger type-safety beyond working with raw strings. For
//! example, applications get and put documents using structured types, and
//! other types, such as revisions and views, are strongly typed as well.
//!
//! To deal with JSON, the couchdb crate relies on Serde and its traits
//! `serde::Serialize` and `serde::Deserialize`. These traits are fundamental to
//! the crate's API—they are not mere implementation details. As such,
//! applications must use these traits when working with documents, views, or
//! any type that is JSON-encoded in the CouchDB API.
//!
//! ## Example: Create a document, read a document
//!
//! This example shows how the couchdb crates thinly wraps the CouchDB API.
//!
//! The following program (1) constructs a `Client` with which to connect to the
//! CouchDB server, (2) creates a database (via the `put_database` method), (3)
//! creates a document within that database (via the `post_database` method),
//! and (4) reads the new document (via the `get_document` method).
//!
//! ```no_run
//! extern crate couchdb;
//! extern crate serde_json;
//!
//! // The `Client` type is the entry point for sending all HTTP requests to the
//! // CouchDB server.
//! let client = couchdb::Client::new("http://couchdb-server:5984/").unwrap();
//!
//! // PUT http://couchdb-server:5984/baseball
//! client.put_database("/baseball").run().unwrap();
//!
//! // POST http://couchdb-server:5984/baseball
//! let content = serde_json::builder::ObjectBuilder::new()
//!                   .insert("name", "Babe Ruth")
//!                   .insert("career_hr", 714)
//!                   .unwrap();
//! let (id, rev) = client.post_database("/baseball", &content)
//!                       .run()
//!                       .unwrap();
//!
//! // GET http://couchdb-server:5984/baseball/<doc_id>
//! let doc = client.get_document(("/baseball", id.clone()))
//!                 .run()
//!                 .unwrap()
//!                 .unwrap();
//! assert_eq!(id, doc.id);
//! assert_eq!(rev, doc.rev);
//! assert_eq!(content, doc.into_content().unwrap());
//! ```
//!
//! ## CouchDB API coverage
//!
//! In the couchdb crate, the `Client` type is the principal type for
//! communicating with a CouchDB server. All HTTP requests to the CouchDB server
//! go through a `Client` instance.
//!
//! This table maps each CouchDB API resource to the `Client` method that accesses
//! that resource.
//!
//!

//!
//!

//!

//!    CouchDB URI
//!    HTTP method
//!    Client method
//!    Description
//!

//!

//!
//!

//!

//!
//!

/

//!
//!    GET
//!    get_root
//!    Get server version and other meta-information.
//!

//!
//!

//!
//!

/_all_dbs

//!
//!    GET
//!    get_all_databases
//!    Get list of all databases.
//!

//!
//!

//!
//!

/db

//!
//!    HEAD
//!    head_database
//!    Test whether a database exists.
//!

//!
//!

//!    GET
//!    get_database
//!    Get meta-information about a database.
//!

//!
//!

//!    PUT
//!    put_database
//!    Create a database.
//!

//!
//!

//!    DELETE
//!    delete_database
//!    Delete a database.
//!

//!
//!

//!    POST
//!    post_database
//!    Create a document.
//!

//!
//!

//!
//!

//!
/db/_changes

//!

//!
//!    GET
//!    get_changes
//!    Get changes made to documents in a database.
//!

//!
//!

//!
//!

//!
/db/doc

//!
/db/_design/design-doc

//!
/db/_local/id

//!

//!
//!    HEAD
//!    head_document
//!    Test whether a document exists.
//!

//!
//!

//!    GET
//!    get_document
//!    Get meta-information and application-defined content for a
//!    document.
//!

//!
//!

//!    PUT
//!    put_document
//!    Create or update a document.
//!

//!
//!

//!    DELETE
//!    delete_document
//!    Delete a document.
//!

//!
//!

//!
//!

/db/_design/design-doc/_view/view

//!
//!    GET
//!    get_view
//!    Execute a view.
//!

//!
//!

//!

extern crate hyper;
extern crate regex;
extern crate serde;
extern crate serde_json;
extern crate semver;
extern crate tempdir;
extern crate url;

pub mod action;
pub mod testing;

mod client;
mod dbtype;
mod error;
mod path;

pub use client::{Client, IntoUrl};
pub use dbtype::{Database, ChangeItem, ChangeItemBuilder, ChangeResult, ChangeResultBuilder,
                 Changes, ChangesBuilder, DatabaseName, Design, DesignBuilder, DesignDocumentName,
                 Document, DocumentId, DocumentName, ErrorResponse, Revision, Root, Uuid, Vendor,
                 ViewFunction, ViewFunctionBuilder, ViewFunctionMap, ViewName, ViewResult, ViewRow};
pub use path::{IntoDatabasePath, IntoDesignDocumentPath, IntoDocumentPath, IntoViewPath,
               DatabasePath, DesignDocumentPath, DocumentPath, ViewPath};
pub use error::Error;
<commit_msg>Add hyperlinks to front-page API table<commit_after>//! The couchdb crate provides low-level access to individual HTTP actions—e.g.,
//! PUT database, GET document, etc. It handles the menial task of sending
//! requests and receiving responses, thereby allowing application programmers
//! to focus on their business logic.
//!
//! This documentation has been written assuming the application programmer is
//! familiar with the CouchDB API. Descriptions of types, methods, etc. in the
//! couchdb crate should provide just enough information for the programmer to
//! map the crate's concepts onto the CouchDB API and then use the CouchDB
//! documentation as needed to fill in remaining details. Most names in the
//! crate API are identical to the names used in the CouchDB API so as to make
//! this mapping straightforward. There's also a table, below, that [shows the
//! mapping at a high level](#couchdb-api-coverage).
//!
//! One key difference between the couchdb crate's API and the CouchDB API is
//! the crate provides stronger type-safety beyond working with raw strings. For
//! example, applications get and put documents using structured types, and
//! other types, such as revisions and views, are strongly typed as well.
//!
//! To deal with JSON, the couchdb crate relies on Serde and its traits
//! `serde::Serialize` and `serde::Deserialize`. These traits are fundamental to
//! the crate's API—they are not mere implementation details. As such,
//! applications must use these traits when working with documents, views, or
//! any type that is JSON-encoded in the CouchDB API.
//!
//! ## Example: Create a document, read a document
//!
//! This example shows how the couchdb crates thinly wraps the CouchDB API.
//!
//! The following program (1) constructs a `Client` with which to connect to the
//! CouchDB server, (2) creates a database (via the `put_database` method), (3)
//! creates a document within that database (via the `post_database` method),
//! and (4) reads the new document (via the `get_document` method).
//!
//! ```no_run
//! extern crate couchdb;
//! extern crate serde_json;
//!
//! // The `Client` type is the entry point for sending all HTTP requests to the
//! // CouchDB server.
//! let client = couchdb::Client::new("http://couchdb-server:5984/").unwrap();
//!
//! // PUT http://couchdb-server:5984/baseball
//! client.put_database("/baseball").run().unwrap();
//!
//! // POST http://couchdb-server:5984/baseball
//! let content = serde_json::builder::ObjectBuilder::new()
//!                   .insert("name", "Babe Ruth")
//!                   .insert("career_hr", 714)
//!                   .unwrap();
//! let (id, rev) = client.post_database("/baseball", &content)
//!                       .run()
//!                       .unwrap();
//!
//! // GET http://couchdb-server:5984/baseball/<doc_id>
//! let doc = client.get_document(("/baseball", id.clone()))
//!                 .run()
//!                 .unwrap()
//!                 .unwrap();
//! assert_eq!(id, doc.id);
//! assert_eq!(rev, doc.rev);
//! assert_eq!(content, doc.into_content().unwrap());
//! ```
//!
//! ## CouchDB API coverage
//!
//! In the couchdb crate, the `Client` type is the principal type for
//! communicating with a CouchDB server. All HTTP requests to the CouchDB server
//! go through a `Client` instance.
//!
//! This table maps each CouchDB API resource to the `Client` method that accesses
//! that resource.
//!
//!

//!
//!

//!

//!    CouchDB URI
//!    HTTP method
//!    Client method
//!    Description
//!

//!

//!
//!

//!

//!
//!

/

//!
//!    GET
//!    get_root
//!    Get server version and other meta-information.
//!

//!
//!

//!
//!

/_all_dbs

//!
//!    GET
//!    get_all_databases
//!    Get list of all databases.
//!

//!
//!

//!
//!

/db

//!
//!    HEAD
//!    head_database
//!    Test whether a database exists.
//!

//!
//!

//!    GET
//!    get_database
//!    Get meta-information about a database.
//!

//!
//!

//!    PUT
//!    put_database
//!    Create a database.
//!

//!
//!

//!    DELETE
//!    delete_database
//!    Delete a database.
//!

//!
//!

//!    POST
//!    post_database
//!    Create a document.
//!

//!
//!

//!
//!

//!
/db/_changes

//!

//!
//!    GET
//!    get_changes
//!    Get changes made to documents in a database.
//!

//!
//!

//!
//!

//!
/db/doc

//!
/db/_design/design-doc

//!
/db/_local/id

//!

//!
//!    HEAD
//!    head_document
//!    Test whether a document exists.
//!

//!
//!

//!    GET
//!    get_document
//!    Get meta-information and application-defined content for a
//!    document.
//!

//!
//!

//!    PUT
//!    put_document
//!    Create or update a document.
//!

//!
//!

//!    DELETE
//!    delete_document
//!    Delete a document.
//!

//!
//!

//!
//!

/db/_design/design-doc/_view/view

//!
//!    GET
//!    get_view
//!    Execute a view.
//!

//!
//!

//!

extern crate hyper;
extern crate regex;
extern crate serde;
extern crate serde_json;
extern crate semver;
extern crate tempdir;
extern crate url;

pub mod action;
pub mod testing;

mod client;
mod dbtype;
mod error;
mod path;

pub use client::{Client, IntoUrl};
pub use dbtype::{Database, ChangeItem, ChangeItemBuilder, ChangeResult, ChangeResultBuilder,
                 Changes, ChangesBuilder, DatabaseName, Design, DesignBuilder, DesignDocumentName,
                 Document, DocumentId, DocumentName, ErrorResponse, Revision, Root, Uuid, Vendor,
                 ViewFunction, ViewFunctionBuilder, ViewFunctionMap, ViewName, ViewResult, ViewRow};
pub use path::{IntoDatabasePath, IntoDesignDocumentPath, IntoDocumentPath, IntoViewPath,
               DatabasePath, DesignDocumentPath, DocumentPath, ViewPath};
pub use error::Error;
<|endoftext|>


<commit_before>extern crate serialize;

use std::io::Writer;
use std::io::IoError;
use serialize::Encoder;

type EwResult = Result<(), IoError>;

struct EncoderWriter<W> {
    writer: W
}

impl <W> EncoderWriter<W> {
    fn new(w: W) -> EncoderWriter<W> {
        EncoderWriter{ writer: w }
    }

    fn unwrap(self) -> W {
        self.writer
    }
}

impl <W: Writer> Encoder<IoError> for EncoderWriter<W> {
    fn emit_nil(&mut self) -> EwResult { Ok(()) }
    fn emit_uint(&mut self, v: uint) -> EwResult {
        Ok(())
    }
    fn emit_u64(&mut self, v: u64) -> EwResult { Ok(()) }
    fn emit_u32(&mut self, v: u32) -> EwResult { Ok(()) }
    fn emit_u16(&mut self, v: u16) -> EwResult { Ok(()) }
    fn emit_u8(&mut self, v: u8) -> EwResult { Ok(()) }
    fn emit_int(&mut self, v: int) -> EwResult { Ok(()) }
    fn emit_i64(&mut self, v: i64) -> EwResult { Ok(()) }
    fn emit_i32(&mut self, v: i32) -> EwResult { Ok(()) }
    fn emit_i16(&mut self, v: i16) -> EwResult { Ok(()) }
    fn emit_i8(&mut self, v: i8) -> EwResult { Ok(()) }
    fn emit_bool(&mut self, v: bool) -> EwResult { Ok(()) }
    fn emit_f64(&mut self, v: f64) -> EwResult { Ok(()) }
    fn emit_f32(&mut self, v: f32) -> EwResult { Ok(()) }
    fn emit_char(&mut self, v: char) -> EwResult { Ok(()) }
    fn emit_str(&mut self, v: &str) -> EwResult { Ok(()) }
    fn emit_enum(&mut self, name: &str,
                 f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_enum_variant(&mut self, v_name: &str, v_id: uint, len: uint,
                         f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_enum_variant_arg(&mut self, a_idx: uint,
                             f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_enum_struct_variant(&mut self, v_name: &str, v_id: uint,
                                len: uint, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_enum_struct_variant_field(&mut self, f_name: &str,
                                      f_idx: uint, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_struct(&mut self, name: &str, len: uint,
                   f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_struct_field(&mut self, f_name: &str, f_idx: uint,
                         f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_tuple(&mut self, len: uint,
                  f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_tuple_arg(&mut self, idx: uint,
                      f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_tuple_struct(&mut self, name: &str, len: uint,
                         f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_tuple_struct_arg(&mut self, f_idx: uint,
                             f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_option(&mut self, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_option_none(&mut self) -> EwResult { Ok(()) }
    fn emit_option_some(&mut self, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_seq(&mut self, len: uint, f: |this: &mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_seq_elt(&mut self, idx: uint, f: |this: &mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_map(&mut self, len: uint, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_map_elt_key(&mut self, idx: uint, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
    fn emit_map_elt_val(&mut self, idx: uint, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult { Ok(()) }
}
<commit_msg>better formatting<commit_after>extern crate serialize;

use std::io::Writer;
use std::io::IoError;
use serialize::Encoder;

type EwResult = Result<(), IoError>;

struct EncoderWriter<W> {
    writer: W
}

impl <W> EncoderWriter<W> {
    fn new(w: W) -> EncoderWriter<W> {
        EncoderWriter{ writer: w }
    }

    fn unwrap(self) -> W {
        self.writer
    }
}

impl <W: Writer> Encoder<IoError> for EncoderWriter<W> {
    fn emit_nil(&mut self) -> EwResult { Ok(()) }
    fn emit_uint(&mut self, v: uint) -> EwResult {
        Ok(())
    }
    fn emit_u64(&mut self, v: u64) -> EwResult {
        Ok(())
    }
    fn emit_u32(&mut self, v: u32) -> EwResult {
        Ok(())
    }
    fn emit_u16(&mut self, v: u16) -> EwResult {
        Ok(())
    }
    fn emit_u8(&mut self, v: u8) -> EwResult {
        Ok(())
    }
    fn emit_int(&mut self, v: int) -> EwResult {
        Ok(())
    }
    fn emit_i64(&mut self, v: i64) -> EwResult {
        Ok(())
    }
    fn emit_i32(&mut self, v: i32) -> EwResult {
        Ok(())
    }
    fn emit_i16(&mut self, v: i16) -> EwResult {
        Ok(())
    }
    fn emit_i8(&mut self, v: i8) -> EwResult {
        Ok(())
    }
    fn emit_bool(&mut self, v: bool) -> EwResult {
        Ok(())
    }
    fn emit_f64(&mut self, v: f64) -> EwResult {
        Ok(())
    }
    fn emit_f32(&mut self, v: f32) -> EwResult {
        Ok(())
    }
    fn emit_char(&mut self, v: char) -> EwResult {
        Ok(())
    }
    fn emit_str(&mut self, v: &str) -> EwResult {
        Ok(())
    }
    fn emit_enum(&mut self, name: &str,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_enum_variant(&mut self,
            v_name: &str, v_id: uint, len: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_enum_variant_arg(&mut self, a_idx: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_enum_struct_variant(&mut self, v_name: &str, v_id: uint,
            len: uint, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_enum_struct_variant_field(&mut self, f_name: &str,
            f_idx: uint, f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_struct(&mut self, name: &str, len: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_struct_field(&mut self, f_name: &str, f_idx: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_tuple(&mut self, len: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_tuple_arg(&mut self, idx: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_tuple_struct(&mut self, name: &str, len: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_tuple_struct_arg(&mut self, f_idx: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_option(&mut self,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_option_none(&mut self) -> EwResult {
        Ok(())
    }
    fn emit_option_some(&mut self,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_seq(&mut self, len: uint,
            f: |this: &mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_seq_elt(&mut self, idx: uint,
            f: |this: &mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_map(&mut self, len: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_map_elt_key(&mut self, idx: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
    fn emit_map_elt_val(&mut self, idx: uint,
            f: |&mut EncoderWriter<W>| -> EwResult) -> EwResult {
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! ByteSize is an utility that easily makes bytes size representation
//! and helps its arithmetic operations.
//!
//! ## Example
//!
//! ```ignore
//! extern crate bytesize;
//!
//! use bytesize::ByteSize;
//!
//! fn byte_arithmetic_operator() {
//!   let x = ByteSize::mb(1);
//!   let y = ByteSize::kb(100);
//!
//!   let plus = x + y;
//!   print!("{} bytes", plus.as_u64());
//!
//!   let minus = ByteSize::tb(100) - ByteSize::gb(4);
//!   print!("{} bytes", minus.as_u64());
//! }
//! ```
//!
//! It also provides its human readable string as follows:
//!
//! ```ignore=
//!  assert_eq!("482 GiB".to_string(), ByteSize::gb(518).to_string(true));
//!  assert_eq!("518 GB".to_string(), ByteSize::gb(518).to_string(false));
//! ```

use std::fmt::{Display, Formatter, Result};
use std::ops::{Add, Mul};

/// byte size for 1 byte
pub static B: u64 = 1;
/// bytes size for 1 kilobyte
pub static KB: u64 = 1_000;
/// bytes size for 1 megabyte
pub static MB: u64 = 1_000_000;
/// bytes size for 1 gigabyte
pub static GB: u64 = 1_000_000_000;
/// bytes size for 1 terabyte
pub static TB: u64 = 1_000_000_000_000;
/// bytes size for 1 petabyte
pub static PB: u64 = 1_000_000_000_000_000;

/// bytes size for 1 kibibyte
pub static KIB: u64 = 1_024;
/// bytes size for 1 mebibyte
pub static MIB: u64 = 1_048_576;
/// bytes size for 1 gibibyte
pub static GIB: u64 = 1_073_741_824;
/// bytes size for 1 tebibyte
pub static TIB: u64 = 1_099_511_627_776;
/// bytes size for 1 pebibyte
pub static PIB: u64 = 1_125_899_906_842_624;

static UNITS: &'static str = "KMGTPE";
static UNITS_SI: &'static str = "kMGTPE";
static LN_KB: f64 = 6.931471806; // ln 1024
static LN_KIB: f64 = 6.907755279; // ln 1000

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)]
/// Byte size representation
pub struct ByteSize {
    size: u64,
}

impl ByteSize {
    #[inline(always)]
    pub fn b(size: u64) -> ByteSize {
        ByteSize { size: size }
    }

    #[inline(always)]
    pub fn kb(size: u64) -> ByteSize {
        ByteSize { size: size * KB }
    }

    #[inline(always)]
    pub fn kib(size: u64) -> ByteSize {
        ByteSize { size: size * KIB }
    }

    #[inline(always)]
    pub fn mb(size: u64) -> ByteSize {
        ByteSize { size: size * MB }
    }

    #[inline(always)]
    pub fn mib(size: u64) -> ByteSize {
        ByteSize { size: size * MIB }
    }

    #[inline(always)]
    pub fn gb(size: u64) -> ByteSize {
        ByteSize { size: size * GB }
    }

    #[inline(always)]
    pub fn gib(size: u64) -> ByteSize {
        ByteSize { size: size * GIB }
    }

    #[inline(always)]
    pub fn tb(size: u64) -> ByteSize {
        ByteSize { size: size * TB }
    }

    #[inline(always)]
    pub fn tib(size: u64) -> ByteSize {
        ByteSize { size: size * TIB }
    }

    #[inline(always)]
    pub fn pb(size: u64) -> ByteSize {
        ByteSize { size: size * PB }
    }

    #[inline(always)]
    pub fn pib(size: u64) -> ByteSize {
        ByteSize { size: size * PIB }
    }

    #[inline(always)]
    pub fn as_u64(&self) -> u64 {
        self.size
    }

    pub fn to_string(&self, si: bool) -> String {

        let unit = if si { KIB } else { KB };
        let unit_base = if si { LN_KIB } else { LN_KB };
        let unit_prefix = if si {
            UNITS_SI.as_bytes()
        } else {
            UNITS.as_bytes()
        };
        let unit_suffix = if si { "iB" } else { "B" };

        if self.size < unit {
            format!("{} B", self.size)

        } else {
            let size = self.size as f64;
            let exp = match (size.ln() / unit_base) as usize {
                e if e == 0 => 1,
                e => e,
            };

            format!(
                "{:.1} {}{}",
                (size / unit.pow(exp as u32) as f64),
                unit_prefix[exp - 1] as char,
                unit_suffix
            )
        }
    }
}

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

macro_rules! commutative_op {
    ($t:ty) => {
        impl Add<$t> for ByteSize {
            type Output = ByteSize;
            #[inline(always)]
            fn add(self, rhs: $t) -> ByteSize {
                ByteSize {size: (self.size + (rhs as u64))}
            }
        }

        impl Add<ByteSize> for $t {
            type Output = ByteSize;
            #[inline(always)]
            fn add(self, rhs: ByteSize) -> ByteSize {
                ByteSize {size: (rhs.size + (self as u64))}
            }
        }

        impl Mul<$t> for ByteSize {
            type Output = ByteSize;
            #[inline(always)]
            fn mul(self, rhs: $t) -> ByteSize {
                ByteSize {size: (self.size * (rhs as u64))}
            }
        }

        impl Mul<ByteSize> for $t {
            type Output = ByteSize;
            #[inline(always)]
            fn mul(self, rhs: ByteSize) -> ByteSize {
                ByteSize {size: (rhs.size * (self as u64))}
            }
        }
    };
}

commutative_op!(u64);
commutative_op!(u32);
commutative_op!(u16);
commutative_op!(u8);

impl Add<ByteSize> for ByteSize {
    type Output = ByteSize;

    #[inline(always)]
    fn add(self, rhs: ByteSize) -> ByteSize {
        ByteSize { size: (self.size + rhs.size) }
    }
}

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

    #[test]
    fn test_arithmetic_op() {
        let x = ByteSize::mb(1);
        let y = ByteSize::kb(100);

        assert_eq!((x + y).as_u64(), 1_100_000u64);

        assert_eq!((x + (100 * 1000) as u64).as_u64(), 1_100_000);

        assert_eq!((x * 2u64).as_u64(), 2_000_000);
    }

    #[test]
    fn test_arithmetic_primitives() {
        let x = ByteSize::mb(1);

        assert_eq!((x + MB as u64).as_u64(), 2_000_000);

        assert_eq!((x + MB as u32).as_u64(), 2_000_000);

        assert_eq!((x + KB as u16).as_u64(), 1_001_000);

        assert_eq!((x + B as u8).as_u64(), 1_000_001);
    }

    #[test]
    fn test_comparison() {
        assert!(ByteSize::mb(1) == ByteSize::kb(1000));
        assert!(ByteSize::mib(1) == ByteSize::kib(1024));
        assert!(ByteSize::mb(1) != ByteSize::kib(1024));
        assert!(ByteSize::mb(1) < ByteSize::kib(1024));
        assert!(ByteSize::b(0) < ByteSize::tib(1));
    }

    fn assert_display(expected: &str, b: ByteSize) {
        assert_eq!(expected, format!("{}", b));
    }

    #[test]
    fn test_display() {
        assert_display("215 B", ByteSize::b(215));
        assert_display("1.0 KB", ByteSize::kb(1));
        assert_display("301.0 KB", ByteSize::kb(301));
        assert_display("419.0 MB", ByteSize::mb(419));
        assert_display("518.0 GB", ByteSize::gb(518));
        assert_display("815.0 TB", ByteSize::tb(815));
        assert_display("609.0 PB", ByteSize::pb(609));
    }

    fn assert_to_string(expected: &str, b: ByteSize, si: bool) {
        assert_eq!(expected.to_string(), b.to_string(si));
    }

    #[test]
    fn test_to_string() {
        assert_to_string("215 B", ByteSize::b(215), true);
        assert_to_string("215 B", ByteSize::b(215), false);

        assert_to_string("1.0 kiB", ByteSize::kib(1), true);
        assert_to_string("1.0 KB", ByteSize::kib(1), false);

        assert_to_string("293.9 kiB", ByteSize::kb(301), true);
        assert_to_string("301.0 KB", ByteSize::kb(301), false);

        assert_to_string("1.0 MiB", ByteSize::mib(1), true);
        assert_to_string("1048.6 KB", ByteSize::mib(1), false);

        // a bug case: https://github.com/flang-project/bytesize/issues/8
        assert_to_string("1.9 GiB", ByteSize::mib(1907), true);
        assert_to_string("2.0 GB", ByteSize::mib(1908), false);

        assert_to_string("399.6 MiB", ByteSize::mb(419), true);
        assert_to_string("419.0 MB", ByteSize::mb(419), false);

        assert_to_string("482.4 GiB", ByteSize::gb(518), true);
        assert_to_string("518.0 GB", ByteSize::gb(518), false);

        assert_to_string("741.2 TiB", ByteSize::tb(815), true);
        assert_to_string("815.0 TB", ByteSize::tb(815), false);

        assert_to_string("540.9 PiB", ByteSize::pb(609), true);
        assert_to_string("609.0 PB", ByteSize::pb(609), false);
    }

    #[test]
    fn test_default() {
        assert_eq!(ByteSize::b(0), ByteSize::default());
    }
}
<commit_msg>reformat lib.rs by rustfmt-preview<commit_after>//! ByteSize is an utility that easily makes bytes size representation
//! and helps its arithmetic operations.
//!
//! ## Example
//!
//! ```ignore
//! extern crate bytesize;
//!
//! use bytesize::ByteSize;
//!
//! fn byte_arithmetic_operator() {
//!   let x = ByteSize::mb(1);
//!   let y = ByteSize::kb(100);
//!
//!   let plus = x + y;
//!   print!("{} bytes", plus.as_u64());
//!
//!   let minus = ByteSize::tb(100) - ByteSize::gb(4);
//!   print!("{} bytes", minus.as_u64());
//! }
//! ```
//!
//! It also provides its human readable string as follows:
//!
//! ```ignore=
//!  assert_eq!("482 GiB".to_string(), ByteSize::gb(518).to_string(true));
//!  assert_eq!("518 GB".to_string(), ByteSize::gb(518).to_string(false));
//! ```

use std::fmt::{Display, Formatter, Result};
use std::ops::{Add, Mul};

/// byte size for 1 byte
pub static B: u64 = 1;
/// bytes size for 1 kilobyte
pub static KB: u64 = 1_000;
/// bytes size for 1 megabyte
pub static MB: u64 = 1_000_000;
/// bytes size for 1 gigabyte
pub static GB: u64 = 1_000_000_000;
/// bytes size for 1 terabyte
pub static TB: u64 = 1_000_000_000_000;
/// bytes size for 1 petabyte
pub static PB: u64 = 1_000_000_000_000_000;

/// bytes size for 1 kibibyte
pub static KIB: u64 = 1_024;
/// bytes size for 1 mebibyte
pub static MIB: u64 = 1_048_576;
/// bytes size for 1 gibibyte
pub static GIB: u64 = 1_073_741_824;
/// bytes size for 1 tebibyte
pub static TIB: u64 = 1_099_511_627_776;
/// bytes size for 1 pebibyte
pub static PIB: u64 = 1_125_899_906_842_624;

static UNITS: &'static str = "KMGTPE";
static UNITS_SI: &'static str = "kMGTPE";
static LN_KB: f64 = 6.931471806; // ln 1024
static LN_KIB: f64 = 6.907755279; // ln 1000

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)]
/// Byte size representation
pub struct ByteSize {
    size: u64,
}

impl ByteSize {
    #[inline(always)]
    pub fn b(size: u64) -> ByteSize {
        ByteSize { size: size }
    }

    #[inline(always)]
    pub fn kb(size: u64) -> ByteSize {
        ByteSize { size: size * KB }
    }

    #[inline(always)]
    pub fn kib(size: u64) -> ByteSize {
        ByteSize { size: size * KIB }
    }

    #[inline(always)]
    pub fn mb(size: u64) -> ByteSize {
        ByteSize { size: size * MB }
    }

    #[inline(always)]
    pub fn mib(size: u64) -> ByteSize {
        ByteSize { size: size * MIB }
    }

    #[inline(always)]
    pub fn gb(size: u64) -> ByteSize {
        ByteSize { size: size * GB }
    }

    #[inline(always)]
    pub fn gib(size: u64) -> ByteSize {
        ByteSize { size: size * GIB }
    }

    #[inline(always)]
    pub fn tb(size: u64) -> ByteSize {
        ByteSize { size: size * TB }
    }

    #[inline(always)]
    pub fn tib(size: u64) -> ByteSize {
        ByteSize { size: size * TIB }
    }

    #[inline(always)]
    pub fn pb(size: u64) -> ByteSize {
        ByteSize { size: size * PB }
    }

    #[inline(always)]
    pub fn pib(size: u64) -> ByteSize {
        ByteSize { size: size * PIB }
    }

    #[inline(always)]
    pub fn as_u64(&self) -> u64 {
        self.size
    }

    pub fn to_string(&self, si: bool) -> String {
        let unit = if si { KIB } else { KB };
        let unit_base = if si { LN_KIB } else { LN_KB };
        let unit_prefix = if si {
            UNITS_SI.as_bytes()
        } else {
            UNITS.as_bytes()
        };
        let unit_suffix = if si { "iB" } else { "B" };

        if self.size < unit {
            format!("{} B", self.size)
        } else {
            let size = self.size as f64;
            let exp = match (size.ln() / unit_base) as usize {
                e if e == 0 => 1,
                e => e,
            };

            format!(
                "{:.1} {}{}",
                (size / unit.pow(exp as u32) as f64),
                unit_prefix[exp - 1] as char,
                unit_suffix
            )
        }
    }
}

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

macro_rules! commutative_op {
    ($t:ty) => {
        impl Add<$t> for ByteSize {
            type Output = ByteSize;
            #[inline(always)]
            fn add(self, rhs: $t) -> ByteSize {
                ByteSize {size: (self.size + (rhs as u64))}
            }
        }

        impl Add<ByteSize> for $t {
            type Output = ByteSize;
            #[inline(always)]
            fn add(self, rhs: ByteSize) -> ByteSize {
                ByteSize {size: (rhs.size + (self as u64))}
            }
        }

        impl Mul<$t> for ByteSize {
            type Output = ByteSize;
            #[inline(always)]
            fn mul(self, rhs: $t) -> ByteSize {
                ByteSize {size: (self.size * (rhs as u64))}
            }
        }

        impl Mul<ByteSize> for $t {
            type Output = ByteSize;
            #[inline(always)]
            fn mul(self, rhs: ByteSize) -> ByteSize {
                ByteSize {size: (rhs.size * (self as u64))}
            }
        }
    };
}

commutative_op!(u64);
commutative_op!(u32);
commutative_op!(u16);
commutative_op!(u8);

impl Add<ByteSize> for ByteSize {
    type Output = ByteSize;

    #[inline(always)]
    fn add(self, rhs: ByteSize) -> ByteSize {
        ByteSize {
            size: (self.size + rhs.size),
        }
    }
}

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

    #[test]
    fn test_arithmetic_op() {
        let x = ByteSize::mb(1);
        let y = ByteSize::kb(100);

        assert_eq!((x + y).as_u64(), 1_100_000u64);

        assert_eq!((x + (100 * 1000) as u64).as_u64(), 1_100_000);

        assert_eq!((x * 2u64).as_u64(), 2_000_000);
    }

    #[test]
    fn test_arithmetic_primitives() {
        let x = ByteSize::mb(1);

        assert_eq!((x + MB as u64).as_u64(), 2_000_000);

        assert_eq!((x + MB as u32).as_u64(), 2_000_000);

        assert_eq!((x + KB as u16).as_u64(), 1_001_000);

        assert_eq!((x + B as u8).as_u64(), 1_000_001);
    }

    #[test]
    fn test_comparison() {
        assert!(ByteSize::mb(1) == ByteSize::kb(1000));
        assert!(ByteSize::mib(1) == ByteSize::kib(1024));
        assert!(ByteSize::mb(1) != ByteSize::kib(1024));
        assert!(ByteSize::mb(1) < ByteSize::kib(1024));
        assert!(ByteSize::b(0) < ByteSize::tib(1));
    }

    fn assert_display(expected: &str, b: ByteSize) {
        assert_eq!(expected, format!("{}", b));
    }

    #[test]
    fn test_display() {
        assert_display("215 B", ByteSize::b(215));
        assert_display("1.0 KB", ByteSize::kb(1));
        assert_display("301.0 KB", ByteSize::kb(301));
        assert_display("419.0 MB", ByteSize::mb(419));
        assert_display("518.0 GB", ByteSize::gb(518));
        assert_display("815.0 TB", ByteSize::tb(815));
        assert_display("609.0 PB", ByteSize::pb(609));
    }

    fn assert_to_string(expected: &str, b: ByteSize, si: bool) {
        assert_eq!(expected.to_string(), b.to_string(si));
    }

    #[test]
    fn test_to_string() {
        assert_to_string("215 B", ByteSize::b(215), true);
        assert_to_string("215 B", ByteSize::b(215), false);

        assert_to_string("1.0 kiB", ByteSize::kib(1), true);
        assert_to_string("1.0 KB", ByteSize::kib(1), false);

        assert_to_string("293.9 kiB", ByteSize::kb(301), true);
        assert_to_string("301.0 KB", ByteSize::kb(301), false);

        assert_to_string("1.0 MiB", ByteSize::mib(1), true);
        assert_to_string("1048.6 KB", ByteSize::mib(1), false);

        // a bug case: https://github.com/flang-project/bytesize/issues/8
        assert_to_string("1.9 GiB", ByteSize::mib(1907), true);
        assert_to_string("2.0 GB", ByteSize::mib(1908), false);

        assert_to_string("399.6 MiB", ByteSize::mb(419), true);
        assert_to_string("419.0 MB", ByteSize::mb(419), false);

        assert_to_string("482.4 GiB", ByteSize::gb(518), true);
        assert_to_string("518.0 GB", ByteSize::gb(518), false);

        assert_to_string("741.2 TiB", ByteSize::tb(815), true);
        assert_to_string("815.0 TB", ByteSize::tb(815), false);

        assert_to_string("540.9 PiB", ByteSize::pb(609), true);
        assert_to_string("609.0 PB", ByteSize::pb(609), false);
    }

    #[test]
    fn test_default() {
        assert_eq!(ByteSize::b(0), ByteSize::default());
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Rust wrapper for RocksDB.
//!
//! # Examples
//!
//! ```
//!  use rocksdb::DB;
//!  // NB: db is automatically closed at end of lifetime
//!  let db = DB::open_default("path/for/rocksdb/storage").unwrap();
//!  db.put(b"my key", b"my value");
//!  match db.get(b"my key") {
//!     Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()),
//!     Ok(None) => println!("value not found"),
//!     Err(e) => println!("operational problem encountered: {}", e),
//!  }
//!  db.delete(b"my key").unwrap();
//! ```
//!

extern crate libc;
extern crate librocksdb_sys as ffi;

#[macro_use]
mod ffi_util;

pub mod backup;
mod comparator;
pub mod merge_operator;
pub mod compaction_filter;
mod db;
mod db_options;

pub use db::{DBCompactionStyle, DBCompressionType, DBIterator, DBRawIterator, DBRecoveryMode, DBVector,
             ReadOptions, Direction, IteratorMode, Snapshot, WriteBatch, new_bloom_filter};

pub use merge_operator::MergeOperands;
pub use compaction_filter::Decision as CompactionDecision;
use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::path::PathBuf;

/// A RocksDB database.
///
/// See crate level documentation for a simple usage example.
pub struct DB {
    inner: *mut ffi::rocksdb_t,
    cfs: BTreeMap<String, ColumnFamily>,
    path: PathBuf,
}

/// A simple wrapper round a string, used for errors reported from
/// ffi calls.
#[derive(Debug, PartialEq)]
pub struct Error {
    message: String,
}

impl Error {
    fn new(message: String) -> Error {
        Error { message: message }
    }

    pub fn to_string(self) -> String {
        self.into()
    }
}

impl From<Error> for String {
    fn from(e: Error) -> String {
        e.message
    }
}

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

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.message.fmt(formatter)
    }
}

/// For configuring block-based file storage.
pub struct BlockBasedOptions {
    inner: *mut ffi::rocksdb_block_based_table_options_t,
}

/// Database-wide options around performance and behavior.
///
/// Please read [the official tuning guide](https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide), and most importantly, measure performance under realistic workloads with realistic hardware.
///
/// # Examples
///
/// ```
/// use rocksdb::{Options, DB};
/// use rocksdb::DBCompactionStyle;
///
/// fn badly_tuned_for_somebody_elses_disk() -> DB {
///    let path = "path/for/rocksdb/storageX";
///    let mut opts = Options::default();
///    opts.create_if_missing(true);
///    opts.set_max_open_files(10000);
///    opts.set_use_fsync(false);
///    opts.set_bytes_per_sync(8388608);
///    opts.set_disable_data_sync(false);
///    opts.optimize_for_point_lookup(1024);
///    opts.set_table_cache_num_shard_bits(6);
///    opts.set_max_write_buffer_number(32);
///    opts.set_write_buffer_size(536870912);
///    opts.set_target_file_size_base(1073741824);
///    opts.set_min_write_buffer_number_to_merge(4);
///    opts.set_level_zero_stop_writes_trigger(2000);
///    opts.set_level_zero_slowdown_writes_trigger(0);
///    opts.set_compaction_style(DBCompactionStyle::Universal);
///    opts.set_max_background_compactions(4);
///    opts.set_max_background_flushes(4);
///    opts.set_disable_auto_compactions(true);
///
///    DB::open(&opts, path).unwrap()
/// }
/// ```
pub struct Options {
    inner: *mut ffi::rocksdb_options_t,
}

/// Optionally disable WAL or sync for this write.
///
/// # Examples
///
/// Making an unsafe write of a batch:
///
/// ```
/// use rocksdb::{DB, WriteBatch, WriteOptions};
///
/// let db = DB::open_default("path/for/rocksdb/storageY").unwrap();
///
/// let mut batch = WriteBatch::default();
/// batch.put(b"my key", b"my value");
/// batch.put(b"key2", b"value2");
/// batch.put(b"key3", b"value3");
///
/// let mut write_options = WriteOptions::default();
/// write_options.set_sync(false);
/// write_options.disable_wal(true);
///
/// db.write_opt(batch, &write_options);
/// ```
pub struct WriteOptions {
    inner: *mut ffi::rocksdb_writeoptions_t,
}

/// An opaque type used to represent a column family. Returned from some functions, and used
/// in others
#[derive(Copy, Clone)]
pub struct ColumnFamily {
    inner: *mut ffi::rocksdb_column_family_handle_t,
}
<commit_msg>Implement Clone and AsRef<str> for Error.<commit_after>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Rust wrapper for RocksDB.
//!
//! # Examples
//!
//! ```
//!  use rocksdb::DB;
//!  // NB: db is automatically closed at end of lifetime
//!  let db = DB::open_default("path/for/rocksdb/storage").unwrap();
//!  db.put(b"my key", b"my value");
//!  match db.get(b"my key") {
//!     Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()),
//!     Ok(None) => println!("value not found"),
//!     Err(e) => println!("operational problem encountered: {}", e),
//!  }
//!  db.delete(b"my key").unwrap();
//! ```
//!

extern crate libc;
extern crate librocksdb_sys as ffi;

#[macro_use]
mod ffi_util;

pub mod backup;
mod comparator;
pub mod merge_operator;
pub mod compaction_filter;
mod db;
mod db_options;

pub use db::{DBCompactionStyle, DBCompressionType, DBIterator, DBRawIterator, DBRecoveryMode, DBVector,
             ReadOptions, Direction, IteratorMode, Snapshot, WriteBatch, new_bloom_filter};

pub use merge_operator::MergeOperands;
pub use compaction_filter::Decision as CompactionDecision;
use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::path::PathBuf;

/// A RocksDB database.
///
/// See crate level documentation for a simple usage example.
pub struct DB {
    inner: *mut ffi::rocksdb_t,
    cfs: BTreeMap<String, ColumnFamily>,
    path: PathBuf,
}

/// A simple wrapper round a string, used for errors reported from
/// ffi calls.
#[derive(Debug, Clone, PartialEq)]
pub struct Error {
    message: String,
}

impl Error {
    fn new(message: String) -> Error {
        Error { message: message }
    }

    pub fn to_string(self) -> String {
        self.into()
    }
}

impl AsRef<str> for Error {
    fn as_ref(&self) -> &str {
        &self.message
    }
}

impl From<Error> for String {
    fn from(e: Error) -> String {
        e.message
    }
}

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

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.message.fmt(formatter)
    }
}

/// For configuring block-based file storage.
pub struct BlockBasedOptions {
    inner: *mut ffi::rocksdb_block_based_table_options_t,
}

/// Database-wide options around performance and behavior.
///
/// Please read [the official tuning guide](https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide), and most importantly, measure performance under realistic workloads with realistic hardware.
///
/// # Examples
///
/// ```
/// use rocksdb::{Options, DB};
/// use rocksdb::DBCompactionStyle;
///
/// fn badly_tuned_for_somebody_elses_disk() -> DB {
///    let path = "path/for/rocksdb/storageX";
///    let mut opts = Options::default();
///    opts.create_if_missing(true);
///    opts.set_max_open_files(10000);
///    opts.set_use_fsync(false);
///    opts.set_bytes_per_sync(8388608);
///    opts.set_disable_data_sync(false);
///    opts.optimize_for_point_lookup(1024);
///    opts.set_table_cache_num_shard_bits(6);
///    opts.set_max_write_buffer_number(32);
///    opts.set_write_buffer_size(536870912);
///    opts.set_target_file_size_base(1073741824);
///    opts.set_min_write_buffer_number_to_merge(4);
///    opts.set_level_zero_stop_writes_trigger(2000);
///    opts.set_level_zero_slowdown_writes_trigger(0);
///    opts.set_compaction_style(DBCompactionStyle::Universal);
///    opts.set_max_background_compactions(4);
///    opts.set_max_background_flushes(4);
///    opts.set_disable_auto_compactions(true);
///
///    DB::open(&opts, path).unwrap()
/// }
/// ```
pub struct Options {
    inner: *mut ffi::rocksdb_options_t,
}

/// Optionally disable WAL or sync for this write.
///
/// # Examples
///
/// Making an unsafe write of a batch:
///
/// ```
/// use rocksdb::{DB, WriteBatch, WriteOptions};
///
/// let db = DB::open_default("path/for/rocksdb/storageY").unwrap();
///
/// let mut batch = WriteBatch::default();
/// batch.put(b"my key", b"my value");
/// batch.put(b"key2", b"value2");
/// batch.put(b"key3", b"value3");
///
/// let mut write_options = WriteOptions::default();
/// write_options.set_sync(false);
/// write_options.disable_wal(true);
///
/// db.write_opt(batch, &write_options);
/// ```
pub struct WriteOptions {
    inner: *mut ffi::rocksdb_writeoptions_t,
}

/// An opaque type used to represent a column family. Returned from some functions, and used
/// in others
#[derive(Copy, Clone)]
pub struct ColumnFamily {
    inner: *mut ffi::rocksdb_column_family_handle_t,
}
<|endoftext|>


<commit_before>//! This library provides [`anyhow::Error`][Error], a trait object based error
//! type for easy idiomatic error handling in Rust applications.
//!
//!

//!
//! # Details
//!
//! - Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as
//!   the return type of any fallible function.
//!
//!   Within the function, use `?` to easily propagate any error that implements
//!   the `std::error::Error` trait.
//!
//!   ```
//!   # pub trait Deserialize {}
//!   #
//!   # mod serde_json {
//!   #     use super::Deserialize;
//!   #     use std::io;
//!   #
//!   #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # struct ClusterMap;
//!   #
//!   # impl Deserialize for ClusterMap {}
//!   #
//!   use anyhow::Result;
//!
//!   fn get_cluster_info() -> Result<ClusterMap> {
//!       let config = std::fs::read_to_string("cluster.json")?;
//!       let map: ClusterMap = serde_json::from_str(&config)?;
//!       Ok(map)
//!   }
//!   #
//!   # fn main() {}
//!   ```
//!
//! - Attach context to help the person troubleshooting the error understand
//!   where things went wrong. A low-level error like "No such file or
//!   directory" can be annoying to debug without more context about what higher
//!   level step the application was in the middle of.
//!
//!   ```
//!   # struct It;
//!   #
//!   # impl It {
//!   #     fn detach(&self) -> Result<()> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   use anyhow::{Context, Result};
//!
//!   fn main() -> Result<()> {
//!       # return Ok(());
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # let it = It;
//!       # let path = "./path/to/instrs.jsox";
//!       #
//!       it.detach().context("failed to detach the important thing")?;
//!
//!       let content = std::fs::read(path)
//!           .with_context(|| format!("failed to read instrs from {}", path))?;
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # Ok(())
//!   }
//!   ```
//!
//!   ```console
//!   Error: failed to read instrs from ./path/to/instrs.jsox
//!
//!   caused by:
//!       0: No such file or directory (os error 2)
//!   ```
//!
//! - Downcasting is supported and can be by value, by shared reference, or by
//!   mutable reference as needed.
//!
//!   ```
//!   # use anyhow::anyhow;
//!   # use std::fmt::{self, Display};
//!   # use std::task::Poll;
//!   #
//!   # #[derive(Debug)]
//!   # enum DataStoreError {
//!   #     Censored(()),
//!   # }
//!   #
//!   # impl Display for DataStoreError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # impl std::error::Error for DataStoreError {}
//!   #
//!   # const REDACTED_CONTENT: () = ();
//!   #
//!   # let error = anyhow!("...");
//!   # let root_cause = &error;
//!   #
//!   # let ret =
//!   // If the error was caused by redaction, then return a
//!   // tombstone instead of the content.
//!   match root_cause.downcast_ref::<DataStoreError>() {
//!       Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
//!       None => Err(error),
//!   }
//!   # ;
//!   ```
//!
//! - A backtrace is captured and printed with the error if the underlying error
//!   type does not already provide its own. In order to see backtraces, the
//!   `RUST_LIB_BACKTRACE=1` environment variable must be defined.
//!
//! - Anyhow works with any error type that has an impl of `std::error::Error`,
//!   including ones defined in your crate. We do not bundle a `derive(Error)`
//!   macro but you can write the impls yourself or use a standalone macro like
//!   [err-derive].
//!
//!   [err-derive]: https://crates.io/crates/err-derive
//!
//!   ```
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum FormatError {
//!       #[error(display = "invalid header (expected {:?}, got {:?})", expected, found)]
//!       InvalidHeader {
//!           expected: String,
//!           found: String,
//!       },
//!       #[error(display = "missing attribute: {}", _0)]
//!       MissingAttribute(String),
//!   }
//!   # };
//!   ```
//!
//! - One-off error messages can be constructed using the `anyhow!` macro, which
//!   supports string interpolation and produces an `anyhow::Error`.
//!
//!   ```
//!   # use anyhow::{anyhow, Result};
//!   #
//!   # fn demo() -> Result<()> {
//!   #     let missing = "...";
//!   return Err(anyhow!("missing attribute: {}", missing));
//!   #     Ok(())
//!   # }
//!   ```
//!
//!

//!
//! # Acknowledgements
//!
//! The implementation of the `anyhow::Error` type is forked from
//! `fehler::Exception` ([https://github.com/withoutboats/fehler][fehler]). This
//! library just exposes it under the more standard `Error` / `Result`
//! terminology rather than the `throw!` / `#[throws]` / `Exception` language of
//! exceptions.
//!
//! [fehler]: https://github.com/withoutboats/fehler

#![cfg_attr(backtrace, feature(backtrace))]

mod context;
mod error;

#[cfg(not(feature = "std"))]
compile_error!("no_std support is not implemented yet");

pub use crate::context::Context;
pub use crate::error::{Chain, Error};

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

/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
#[macro_export]
macro_rules! bail {
    ($err:expr $(,)?) => {
        return std::result::Result::Err(std::convert::From::from($err));
    };
}

/// Construct an ad-hoc error from a string.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
#[macro_export]
macro_rules! anyhow {
    ($msg:expr $(,)?) => {
        $crate::private::new_adhoc($msg)
    };
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}

// Not public API.
#[doc(hidden)]
pub mod private {
    use crate::Error;
    use std::fmt::{Debug, Display};

    #[cfg(backtrace)]
    use std::backtrace::Backtrace;

    pub fn new_adhoc<M>(message: M) -> Error
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        #[cfg(backtrace)]
        let backtrace = Some(Backtrace::capture());

        #[cfg(not(backtrace))]
        let backtrace = None;

        Error::new_adhoc(message, backtrace)
    }
}
<commit_msg>Set html_root_url<commit_after>//! This library provides [`anyhow::Error`][Error], a trait object based error
//! type for easy idiomatic error handling in Rust applications.
//!
//!

//!
//! # Details
//!
//! - Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as
//!   the return type of any fallible function.
//!
//!   Within the function, use `?` to easily propagate any error that implements
//!   the `std::error::Error` trait.
//!
//!   ```
//!   # pub trait Deserialize {}
//!   #
//!   # mod serde_json {
//!   #     use super::Deserialize;
//!   #     use std::io;
//!   #
//!   #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # struct ClusterMap;
//!   #
//!   # impl Deserialize for ClusterMap {}
//!   #
//!   use anyhow::Result;
//!
//!   fn get_cluster_info() -> Result<ClusterMap> {
//!       let config = std::fs::read_to_string("cluster.json")?;
//!       let map: ClusterMap = serde_json::from_str(&config)?;
//!       Ok(map)
//!   }
//!   #
//!   # fn main() {}
//!   ```
//!
//! - Attach context to help the person troubleshooting the error understand
//!   where things went wrong. A low-level error like "No such file or
//!   directory" can be annoying to debug without more context about what higher
//!   level step the application was in the middle of.
//!
//!   ```
//!   # struct It;
//!   #
//!   # impl It {
//!   #     fn detach(&self) -> Result<()> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   use anyhow::{Context, Result};
//!
//!   fn main() -> Result<()> {
//!       # return Ok(());
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # let it = It;
//!       # let path = "./path/to/instrs.jsox";
//!       #
//!       it.detach().context("failed to detach the important thing")?;
//!
//!       let content = std::fs::read(path)
//!           .with_context(|| format!("failed to read instrs from {}", path))?;
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # Ok(())
//!   }
//!   ```
//!
//!   ```console
//!   Error: failed to read instrs from ./path/to/instrs.jsox
//!
//!   caused by:
//!       0: No such file or directory (os error 2)
//!   ```
//!
//! - Downcasting is supported and can be by value, by shared reference, or by
//!   mutable reference as needed.
//!
//!   ```
//!   # use anyhow::anyhow;
//!   # use std::fmt::{self, Display};
//!   # use std::task::Poll;
//!   #
//!   # #[derive(Debug)]
//!   # enum DataStoreError {
//!   #     Censored(()),
//!   # }
//!   #
//!   # impl Display for DataStoreError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # impl std::error::Error for DataStoreError {}
//!   #
//!   # const REDACTED_CONTENT: () = ();
//!   #
//!   # let error = anyhow!("...");
//!   # let root_cause = &error;
//!   #
//!   # let ret =
//!   // If the error was caused by redaction, then return a
//!   // tombstone instead of the content.
//!   match root_cause.downcast_ref::<DataStoreError>() {
//!       Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
//!       None => Err(error),
//!   }
//!   # ;
//!   ```
//!
//! - A backtrace is captured and printed with the error if the underlying error
//!   type does not already provide its own. In order to see backtraces, the
//!   `RUST_LIB_BACKTRACE=1` environment variable must be defined.
//!
//! - Anyhow works with any error type that has an impl of `std::error::Error`,
//!   including ones defined in your crate. We do not bundle a `derive(Error)`
//!   macro but you can write the impls yourself or use a standalone macro like
//!   [err-derive].
//!
//!   [err-derive]: https://crates.io/crates/err-derive
//!
//!   ```
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum FormatError {
//!       #[error(display = "invalid header (expected {:?}, got {:?})", expected, found)]
//!       InvalidHeader {
//!           expected: String,
//!           found: String,
//!       },
//!       #[error(display = "missing attribute: {}", _0)]
//!       MissingAttribute(String),
//!   }
//!   # };
//!   ```
//!
//! - One-off error messages can be constructed using the `anyhow!` macro, which
//!   supports string interpolation and produces an `anyhow::Error`.
//!
//!   ```
//!   # use anyhow::{anyhow, Result};
//!   #
//!   # fn demo() -> Result<()> {
//!   #     let missing = "...";
//!   return Err(anyhow!("missing attribute: {}", missing));
//!   #     Ok(())
//!   # }
//!   ```
//!
//!

//!
//! # Acknowledgements
//!
//! The implementation of the `anyhow::Error` type is forked from
//! `fehler::Exception` ([https://github.com/withoutboats/fehler][fehler]). This
//! library just exposes it under the more standard `Error` / `Result`
//! terminology rather than the `throw!` / `#[throws]` / `Exception` language of
//! exceptions.
//!
//! [fehler]: https://github.com/withoutboats/fehler

#![doc(html_root_url = "https://docs.rs/anyhow/1.0.0-alpha.1")]
#![cfg_attr(backtrace, feature(backtrace))]

mod context;
mod error;

#[cfg(not(feature = "std"))]
compile_error!("no_std support is not implemented yet");

pub use crate::context::Context;
pub use crate::error::{Chain, Error};

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

/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
#[macro_export]
macro_rules! bail {
    ($err:expr $(,)?) => {
        return std::result::Result::Err(std::convert::From::from($err));
    };
}

/// Construct an ad-hoc error from a string.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
#[macro_export]
macro_rules! anyhow {
    ($msg:expr $(,)?) => {
        $crate::private::new_adhoc($msg)
    };
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}

// Not public API.
#[doc(hidden)]
pub mod private {
    use crate::Error;
    use std::fmt::{Debug, Display};

    #[cfg(backtrace)]
    use std::backtrace::Backtrace;

    pub fn new_adhoc<M>(message: M) -> Error
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        #[cfg(backtrace)]
        let backtrace = Some(Backtrace::capture());

        #[cfg(not(backtrace))]
        let backtrace = None;

        Error::new_adhoc(message, backtrace)
    }
}
<|endoftext|>


<commit_before>#![feature(rustc_private, decl_macro, type_alias_impl_trait, associated_type_bounds, never_type)]
#![allow(intra_doc_link_resolution_failure)]

extern crate flate2;
extern crate libc;
extern crate tempfile;
extern crate rustc_middle;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_incremental;
extern crate rustc_index;
extern crate rustc_mir;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target;
extern crate rustc_ast;

use std::any::Any;

use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc_session::config::OutputFilenames;
use rustc_middle::ty::query::Providers;
use rustc_middle::util::common::ErrorReported;
use rustc_codegen_ssa::traits::CodegenBackend;

use cranelift_codegen::settings;

use crate::constant::ConstantCx;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod atomic_shim;
mod base;
mod backend;
mod cast;
mod codegen_i128;
mod common;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod intrinsics;
mod linkage;
mod main_shim;
mod metadata;
mod num;
mod optimize;
mod pointer;
mod pretty_clif;
mod target_features_whitelist;
mod trap;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub(crate) use std::collections::HashMap;
    pub(crate) use std::convert::{TryFrom, TryInto};

    pub(crate) use rustc_ast::ast::{FloatTy, IntTy, UintTy};
    pub(crate) use rustc_span::Span;

    pub(crate) use rustc_middle::bug;
    pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
    pub(crate) use rustc_middle::mir::{self, *};
    pub(crate) use rustc_session::Session;
    pub(crate) use rustc_middle::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyAndLayout, VariantIdx};
    pub(crate) use rustc_middle::ty::{
        self, FnSig, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable,
    };

    pub(crate) use rustc_data_structures::fx::FxHashMap;

    pub(crate) use rustc_index::vec::Idx;

    pub(crate) use rustc_codegen_ssa::traits::*;
    pub(crate) use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};

    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_codegen::entity::EntitySet;
    pub(crate) use cranelift_codegen::ir::{AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value};
    pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
    pub(crate) use cranelift_codegen::ir::function::Function;
    pub(crate) use cranelift_codegen::ir::types;
    pub(crate) use cranelift_codegen::isa::{self, CallConv};
    pub(crate) use cranelift_codegen::settings::{self, Configurable};
    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
    pub(crate) use cranelift_module::{
        self, Backend, DataContext, DataId, FuncId, Linkage, Module,
    };

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{trans_operand, trans_place};
    pub(crate) use crate::cast::*;
    pub(crate) use crate::common::*;
    pub(crate) use crate::debuginfo::{DebugContext, FunctionDebugContext};
    pub(crate) use crate::pointer::Pointer;
    pub(crate) use crate::trap::*;
    pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue};
    pub(crate) use crate::CodegenCx;

    pub(crate) struct PrintOnPanic<F: Fn() -> String>(pub F);
    impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
        fn drop(&mut self) {
            if ::std::thread::panicking() {
                println!("{}", (self.0)());
            }
        }
    }

    pub(crate) macro unimpl_fatal($tcx:expr, $span:expr, $($tt:tt)*) {
        $tcx.sess.span_fatal($span, &format!($($tt)*));
    }
}

pub(crate) struct CodegenCx<'clif, 'tcx, B: Backend + 'static> {
    tcx: TyCtxt<'tcx>,
    module: &'clif mut Module<B>,
    constants_cx: ConstantCx,
    cached_context: Context,
    vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
    debug_context: Option<&'clif mut DebugContext<'tcx>>,
}

impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> {
    fn new(
        tcx: TyCtxt<'tcx>,
        module: &'clif mut Module<B>,
        debug_context: Option<&'clif mut DebugContext<'tcx>>,
    ) -> Self {
        CodegenCx {
            tcx,
            module,
            constants_cx: ConstantCx::default(),
            cached_context: Context::new(),
            vtables: HashMap::new(),
            debug_context,
        }
    }

    fn finalize(self) {
        self.constants_cx.finalize(self.tcx, self.module);
    }
}

struct CraneliftCodegenBackend;

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, sess: &Session) {
        if sess.lto() != rustc_session::config::Lto::No {
            sess.warn("LTO is not supported. You may get a linker error.");
        }
    }

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, providers: &mut Providers) {
        providers.target_features_whitelist = |tcx, cnum| {
            assert_eq!(cnum, LOCAL_CRATE);
            if tcx.sess.opts.actually_rustdoc {
                // rustdoc needs to be able to document functions that use all the features, so
                // whitelist them all
                tcx.arena.alloc(
                    target_features_whitelist::all_known_features()
                        .map(|(a, b)| (a.to_string(), b))
                        .collect(),
                )
            } else {
                tcx.arena.alloc(
                    target_features_whitelist::target_feature_whitelist(tcx.sess)
                        .iter()
                        .map(|&(a, b)| (a.to_string(), b))
                        .collect(),
                )
            }
        };
    }
    fn provide_extern(&self, _providers: &mut Providers) {}

    fn codegen_crate<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
    ) -> Box<dyn Any> {
        let res = driver::codegen_crate(tcx, metadata, need_metadata_module);

        rustc_incremental::assert_module_sources::assert_module_sources(tcx);
        rustc_symbol_mangling::test::report_symbol_names(tcx);

        res
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        sess: &Session,
        dep_graph: &DepGraph,
    ) -> Result<Box<dyn Any>, ErrorReported> {
        let (codegen_results, work_products) = *ongoing_codegen.downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>().unwrap();

        sess.time("serialize_work_products", move || {
            rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
        });

        Ok(Box::new(codegen_results))
    }

    fn link(
        &self,
        sess: &Session,
        res: Box<dyn Any>,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        let codegen_results = *res
            .downcast::<CodegenResults>()
            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");

        let _timer = sess.prof.generic_activity("link_crate");

        sess.time("linking", || {
            let target_cpu = crate::target_triple(sess).to_string();
            link_binary::<crate::archive::ArArchiveBuilder<'_>>(
                sess,
                &codegen_results,
                outputs,
                &codegen_results.crate_name.as_str(),
                &target_cpu,
            );
        });

        rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    sess.target.target.llvm_target.parse().unwrap()
}

fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
    use target_lexicon::BinaryFormat;

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    if enable_pic {
        flags_builder.enable("is_pic").unwrap();
    } else {
        flags_builder.set("is_pic", "false").unwrap();
    }
    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
    flags_builder
        .set(
            "enable_verifier",
            if cfg!(debug_assertions) {
                "true"
            } else {
                "false"
            },
        )
        .unwrap();

    let tls_model = match target_triple.binary_format {
        BinaryFormat::Elf => "elf_gd",
        BinaryFormat::Macho => "macho",
        BinaryFormat::Coff => "coff",
        _ => "none",
    };
    flags_builder.set("tls_model", tls_model).unwrap();

    // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
    /*
    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "fastest").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Aggressive => {
            flags_builder.set("opt_level", "best").unwrap();
        }
        OptLevel::Size | OptLevel::SizeMin => {
            sess.warn("Optimizing for size is not supported. Just ignoring the request");
        }
    }*/

    let flags = settings::Flags::new(flags_builder);
    cranelift_codegen::isa::lookup(target_triple)
        .unwrap()
        .finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend)
}
<commit_msg>Fix opt level names<commit_after>#![feature(rustc_private, decl_macro, type_alias_impl_trait, associated_type_bounds, never_type)]
#![allow(intra_doc_link_resolution_failure)]

extern crate flate2;
extern crate libc;
extern crate tempfile;
extern crate rustc_middle;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_incremental;
extern crate rustc_index;
extern crate rustc_mir;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target;
extern crate rustc_ast;

use std::any::Any;

use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc_session::config::OutputFilenames;
use rustc_middle::ty::query::Providers;
use rustc_middle::util::common::ErrorReported;
use rustc_codegen_ssa::traits::CodegenBackend;

use cranelift_codegen::settings;

use crate::constant::ConstantCx;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod atomic_shim;
mod base;
mod backend;
mod cast;
mod codegen_i128;
mod common;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod intrinsics;
mod linkage;
mod main_shim;
mod metadata;
mod num;
mod optimize;
mod pointer;
mod pretty_clif;
mod target_features_whitelist;
mod trap;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub(crate) use std::collections::HashMap;
    pub(crate) use std::convert::{TryFrom, TryInto};

    pub(crate) use rustc_ast::ast::{FloatTy, IntTy, UintTy};
    pub(crate) use rustc_span::Span;

    pub(crate) use rustc_middle::bug;
    pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
    pub(crate) use rustc_middle::mir::{self, *};
    pub(crate) use rustc_session::Session;
    pub(crate) use rustc_middle::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyAndLayout, VariantIdx};
    pub(crate) use rustc_middle::ty::{
        self, FnSig, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable,
    };

    pub(crate) use rustc_data_structures::fx::FxHashMap;

    pub(crate) use rustc_index::vec::Idx;

    pub(crate) use rustc_codegen_ssa::traits::*;
    pub(crate) use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};

    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_codegen::entity::EntitySet;
    pub(crate) use cranelift_codegen::ir::{AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value};
    pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
    pub(crate) use cranelift_codegen::ir::function::Function;
    pub(crate) use cranelift_codegen::ir::types;
    pub(crate) use cranelift_codegen::isa::{self, CallConv};
    pub(crate) use cranelift_codegen::settings::{self, Configurable};
    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
    pub(crate) use cranelift_module::{
        self, Backend, DataContext, DataId, FuncId, Linkage, Module,
    };

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{trans_operand, trans_place};
    pub(crate) use crate::cast::*;
    pub(crate) use crate::common::*;
    pub(crate) use crate::debuginfo::{DebugContext, FunctionDebugContext};
    pub(crate) use crate::pointer::Pointer;
    pub(crate) use crate::trap::*;
    pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue};
    pub(crate) use crate::CodegenCx;

    pub(crate) struct PrintOnPanic<F: Fn() -> String>(pub F);
    impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
        fn drop(&mut self) {
            if ::std::thread::panicking() {
                println!("{}", (self.0)());
            }
        }
    }

    pub(crate) macro unimpl_fatal($tcx:expr, $span:expr, $($tt:tt)*) {
        $tcx.sess.span_fatal($span, &format!($($tt)*));
    }
}

pub(crate) struct CodegenCx<'clif, 'tcx, B: Backend + 'static> {
    tcx: TyCtxt<'tcx>,
    module: &'clif mut Module<B>,
    constants_cx: ConstantCx,
    cached_context: Context,
    vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
    debug_context: Option<&'clif mut DebugContext<'tcx>>,
}

impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> {
    fn new(
        tcx: TyCtxt<'tcx>,
        module: &'clif mut Module<B>,
        debug_context: Option<&'clif mut DebugContext<'tcx>>,
    ) -> Self {
        CodegenCx {
            tcx,
            module,
            constants_cx: ConstantCx::default(),
            cached_context: Context::new(),
            vtables: HashMap::new(),
            debug_context,
        }
    }

    fn finalize(self) {
        self.constants_cx.finalize(self.tcx, self.module);
    }
}

struct CraneliftCodegenBackend;

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, sess: &Session) {
        if sess.lto() != rustc_session::config::Lto::No {
            sess.warn("LTO is not supported. You may get a linker error.");
        }
    }

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, providers: &mut Providers) {
        providers.target_features_whitelist = |tcx, cnum| {
            assert_eq!(cnum, LOCAL_CRATE);
            if tcx.sess.opts.actually_rustdoc {
                // rustdoc needs to be able to document functions that use all the features, so
                // whitelist them all
                tcx.arena.alloc(
                    target_features_whitelist::all_known_features()
                        .map(|(a, b)| (a.to_string(), b))
                        .collect(),
                )
            } else {
                tcx.arena.alloc(
                    target_features_whitelist::target_feature_whitelist(tcx.sess)
                        .iter()
                        .map(|&(a, b)| (a.to_string(), b))
                        .collect(),
                )
            }
        };
    }
    fn provide_extern(&self, _providers: &mut Providers) {}

    fn codegen_crate<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
    ) -> Box<dyn Any> {
        let res = driver::codegen_crate(tcx, metadata, need_metadata_module);

        rustc_incremental::assert_module_sources::assert_module_sources(tcx);
        rustc_symbol_mangling::test::report_symbol_names(tcx);

        res
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        sess: &Session,
        dep_graph: &DepGraph,
    ) -> Result<Box<dyn Any>, ErrorReported> {
        let (codegen_results, work_products) = *ongoing_codegen.downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>().unwrap();

        sess.time("serialize_work_products", move || {
            rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
        });

        Ok(Box::new(codegen_results))
    }

    fn link(
        &self,
        sess: &Session,
        res: Box<dyn Any>,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        let codegen_results = *res
            .downcast::<CodegenResults>()
            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");

        let _timer = sess.prof.generic_activity("link_crate");

        sess.time("linking", || {
            let target_cpu = crate::target_triple(sess).to_string();
            link_binary::<crate::archive::ArArchiveBuilder<'_>>(
                sess,
                &codegen_results,
                outputs,
                &codegen_results.crate_name.as_str(),
                &target_cpu,
            );
        });

        rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    sess.target.target.llvm_target.parse().unwrap()
}

fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
    use target_lexicon::BinaryFormat;

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    if enable_pic {
        flags_builder.enable("is_pic").unwrap();
    } else {
        flags_builder.set("is_pic", "false").unwrap();
    }
    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
    flags_builder
        .set(
            "enable_verifier",
            if cfg!(debug_assertions) {
                "true"
            } else {
                "false"
            },
        )
        .unwrap();

    let tls_model = match target_triple.binary_format {
        BinaryFormat::Elf => "elf_gd",
        BinaryFormat::Macho => "macho",
        BinaryFormat::Coff => "coff",
        _ => "none",
    };
    flags_builder.set("tls_model", tls_model).unwrap();

    // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
    /*
    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "none").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Aggressive => {
            flags_builder.set("opt_level", "speed_and_size").unwrap();
        }
        OptLevel::Size | OptLevel::SizeMin => {
            sess.warn("Optimizing for size is not supported. Just ignoring the request");
        }
    }*/

    let flags = settings::Flags::new(flags_builder);
    cranelift_codegen::isa::lookup(target_triple)
        .unwrap()
        .finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend)
}
<|endoftext|>