<commit_before>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use std::mem;
use std::vec::Vec;
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::Deref;

use {Future, Poll, Async};
use task::{self, Task};
use lock::Lock;

/// A future that is cloneable and can be polled in multiple threads.
/// Use Future::shared() method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F>
    where F: Future
{
    inner: Arc<Inner<F>>,
}

struct Inner<F>
    where F: Future
{
    /// The original future.
    original_future: Lock<F>,
    /// Indicates whether the result is ready, and the state is `State::Done`.
    result_ready: AtomicBool,
    /// The state of the shared future.
    state: RwLock<State<F::Item, F::Error>>,
}

/// The state of the shared future. It can be one of the following:
/// 1. Done - contains the result of the original future.
/// 2. Waiting - contains the waiting tasks.
enum State<T, E> {
    Waiting(Vec<Task>),
    Done(Result<SharedItem<T>, SharedError<E>>),
}

impl<F> Shared<F>
    where F: Future
{
    /// Creates a new `Shared` from another future.
    pub fn new(future: F) -> Self {
        Shared {
            inner: Arc::new(Inner {
                original_future: Lock::new(future),
                result_ready: AtomicBool::new(false),
                state: RwLock::new(State::Waiting(vec![])),
            }),
        }
    }

    /// Clones the result from self.inner.state.
    /// Assumes state is `State::Done`.
    fn read_result(&self) -> Result<Async<SharedItem<F::Item>>, SharedError<F::Error>> {
        match *self.inner.state.read().unwrap() {
            State::Done(ref result) => result.clone().map(Async::Ready),
            State::Waiting(_) => panic!("read_result() was called but State is not Done"),
        }
    }

    /// Stores the result in self.inner.state, unparks the waiting tasks,
    /// and returns the result.
    fn store_result(&self,
                    result: Result<SharedItem<F::Item>, SharedError<F::Error>>)
                    -> Result<Async<SharedItem<F::Item>>, SharedError<F::Error>> {
        let ref mut state = *self.inner.state.write().unwrap();

        match mem::replace(state, State::Done(result.clone())) {
            State::Waiting(waiters) => {
                self.inner.result_ready.store(true, Ordering::Relaxed);
                for task in waiters {
                    task.unpark();
                }
            }
            State::Done(_) => panic!("store_result() was called twice"),
        }

        result.clone().map(Async::Ready)
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // The logic is as follows:
        // 1. Check if the result is ready (with result_ready)
        //  - If the result is ready, return it.
        //  - Otherwise:
        // 2. Try lock the self.inner.original_future:
        //    - If successfully locked, check again if the result is ready.
        //      If it's ready, just return it.
        //      Otherwise, poll the original future.
        //      If the future is ready, unpark the waiting tasks from
        //      self.inner.state and return the result.
        //    - If the future is not ready, or if the lock failed:
        // 3. Lock the state for write.
        // 4. If the state is `State::Done`, return the result. Otherwise:
        // 5. Create a task, push it to the waiters vector, and return `Ok(Async::NotReady)`.

        // If the result is ready, just return it
        if self.inner.result_ready.load(Ordering::Relaxed) {
            return self.read_result();
        }

        // The result was not ready.
        // Try lock the original future.
        match self.inner.original_future.try_lock() {
            Some(mut original_future) => {
                // Other thread could already poll the result, so we check if result_ready.
                if self.inner.result_ready.load(Ordering::Relaxed) {
                    return self.read_result();
                }

                match original_future.poll() {
                    Ok(Async::Ready(item)) => {
                        return self.store_result(Ok(SharedItem::new(item)));
                    }
                    Err(error) => {
                        return self.store_result(Err(SharedError::new(error)));
                    }
                    Ok(Async::NotReady) => {} // A task will be parked
                }
            }
            None => {} // A task will be parked
        }

        let ref mut state = *self.inner.state.write().unwrap();
        match state {
            &mut State::Done(ref result) => return result.clone().map(Async::Ready),
            &mut State::Waiting(ref mut waiters) => {
                waiters.push(task::park());
            }
        }

        Ok(Async::NotReady)
    }
}

impl<F> Clone for Shared<F>
    where F: Future
{
    fn clone(&self) -> Self {
        Shared { inner: self.inner.clone() }
    }
}

/// A wrapped item of the original future.
/// It is clonable and implements Deref for ease of use.
#[derive(Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> SharedItem<T> {
    fn new(item: T) -> Self {
        SharedItem { item: Arc::new(item) }
    }
}

impl<T> Clone for SharedItem<T> {
    fn clone(&self) -> Self {
        SharedItem { item: self.item.clone() }
    }
}

impl<T> Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future.
/// It is clonable and implements Deref for ease of use.
#[derive(Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> SharedError<E> {
    fn new(error: E) -> Self {
        SharedError { error: Arc::new(error) }
    }
}

impl<T> Clone for SharedError<T> {
    fn clone(&self) -> Self {
        SharedError { error: self.error.clone() }
    }
}

impl<E> Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}
<commit_msg>Removed redundant clone to result<commit_after>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use std::mem;
use std::vec::Vec;
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::Deref;

use {Future, Poll, Async};
use task::{self, Task};
use lock::Lock;

/// A future that is cloneable and can be polled in multiple threads.
/// Use Future::shared() method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F>
    where F: Future
{
    inner: Arc<Inner<F>>,
}

struct Inner<F>
    where F: Future
{
    /// The original future.
    original_future: Lock<F>,
    /// Indicates whether the result is ready, and the state is `State::Done`.
    result_ready: AtomicBool,
    /// The state of the shared future.
    state: RwLock<State<F::Item, F::Error>>,
}

/// The state of the shared future. It can be one of the following:
/// 1. Done - contains the result of the original future.
/// 2. Waiting - contains the waiting tasks.
enum State<T, E> {
    Waiting(Vec<Task>),
    Done(Result<SharedItem<T>, SharedError<E>>),
}

impl<F> Shared<F>
    where F: Future
{
    /// Creates a new `Shared` from another future.
    pub fn new(future: F) -> Self {
        Shared {
            inner: Arc::new(Inner {
                original_future: Lock::new(future),
                result_ready: AtomicBool::new(false),
                state: RwLock::new(State::Waiting(vec![])),
            }),
        }
    }

    /// Clones the result from self.inner.state.
    /// Assumes state is `State::Done`.
    fn read_result(&self) -> Result<Async<SharedItem<F::Item>>, SharedError<F::Error>> {
        match *self.inner.state.read().unwrap() {
            State::Done(ref result) => result.clone().map(Async::Ready),
            State::Waiting(_) => panic!("read_result() was called but State is not Done"),
        }
    }

    /// Stores the result in self.inner.state, unparks the waiting tasks,
    /// and returns the result.
    fn store_result(&self,
                    result: Result<SharedItem<F::Item>, SharedError<F::Error>>)
                    -> Result<Async<SharedItem<F::Item>>, SharedError<F::Error>> {
        let ref mut state = *self.inner.state.write().unwrap();

        match mem::replace(state, State::Done(result.clone())) {
            State::Waiting(waiters) => {
                self.inner.result_ready.store(true, Ordering::Relaxed);
                for task in waiters {
                    task.unpark();
                }
            }
            State::Done(_) => panic!("store_result() was called twice"),
        }

        result.map(Async::Ready)
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // The logic is as follows:
        // 1. Check if the result is ready (with result_ready)
        //  - If the result is ready, return it.
        //  - Otherwise:
        // 2. Try lock the self.inner.original_future:
        //    - If successfully locked, check again if the result is ready.
        //      If it's ready, just return it.
        //      Otherwise, poll the original future.
        //      If the future is ready, unpark the waiting tasks from
        //      self.inner.state and return the result.
        //    - If the future is not ready, or if the lock failed:
        // 3. Lock the state for write.
        // 4. If the state is `State::Done`, return the result. Otherwise:
        // 5. Create a task, push it to the waiters vector, and return `Ok(Async::NotReady)`.

        // If the result is ready, just return it
        if self.inner.result_ready.load(Ordering::Relaxed) {
            return self.read_result();
        }

        // The result was not ready.
        // Try lock the original future.
        match self.inner.original_future.try_lock() {
            Some(mut original_future) => {
                // Other thread could already poll the result, so we check if result_ready.
                if self.inner.result_ready.load(Ordering::Relaxed) {
                    return self.read_result();
                }

                match original_future.poll() {
                    Ok(Async::Ready(item)) => {
                        return self.store_result(Ok(SharedItem::new(item)));
                    }
                    Err(error) => {
                        return self.store_result(Err(SharedError::new(error)));
                    }
                    Ok(Async::NotReady) => {} // A task will be parked
                }
            }
            None => {} // A task will be parked
        }

        let ref mut state = *self.inner.state.write().unwrap();
        match state {
            &mut State::Done(ref result) => return result.clone().map(Async::Ready),
            &mut State::Waiting(ref mut waiters) => {
                waiters.push(task::park());
            }
        }

        Ok(Async::NotReady)
    }
}

impl<F> Clone for Shared<F>
    where F: Future
{
    fn clone(&self) -> Self {
        Shared { inner: self.inner.clone() }
    }
}

/// A wrapped item of the original future.
/// It is clonable and implements Deref for ease of use.
#[derive(Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> SharedItem<T> {
    fn new(item: T) -> Self {
        SharedItem { item: Arc::new(item) }
    }
}

impl<T> Clone for SharedItem<T> {
    fn clone(&self) -> Self {
        SharedItem { item: self.item.clone() }
    }
}

impl<T> Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future.
/// It is clonable and implements Deref for ease of use.
#[derive(Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> SharedError<E> {
    fn new(error: E) -> Self {
        SharedError { error: Arc::new(error) }
    }
}

impl<T> Clone for SharedError<T> {
    fn clone(&self) -> Self {
        SharedError { error: self.error.clone() }
    }
}

impl<E> Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}
<|endoftext|>


<commit_before>use irc::client::prelude::*;

use plugin::*;

use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::ResultExt;

#[derive(PluginName, Default, Debug)]
pub struct Help;

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

impl Plugin for Help {
    fn execute(&self, _: &IrcClient, _: &Message) -> ExecutionStatus {
        ExecutionStatus::Done
    }

    fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
        panic!("Help should not use threading")
    }

    fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
        Ok(client
            .send_notice(&command.source, "Help has not been added yet.")
            .context(FrippyErrorKind::Connection)?)
    }

    fn evaluate(&self, _: &IrcClient, _: PluginCommand) -> Result<String, String> {
        Err(String::from("Help has not been added yet."))
    }
}
<commit_msg>Help: Send a static list of available commands<commit_after>use irc::client::prelude::*;

use plugin::*;

use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::ResultExt;

#[derive(PluginName, Default, Debug)]
pub struct Help;

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

impl Plugin for Help {
    fn execute(&self, _: &IrcClient, _: &Message) -> ExecutionStatus {
        ExecutionStatus::Done
    }

    fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
        panic!("Help should not use threading")
    }

    fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
        Ok(client
            .send_notice(&command.source, "Available commands: help, currency, tell, factoids\r\n\
                For more detailed help call help on the specific command.\r\n\
                Example: 'currency help'")
            .context(FrippyErrorKind::Connection)?)
    }

    fn evaluate(&self, _: &IrcClient, _: PluginCommand) -> Result<String, String> {
        Err(String::from("Help has not been added yet."))
    }
}
<|endoftext|>


<commit_before>//! List projects
//!
//! https://docs.gitlab.com/ce/api/projects.html
//!
//! # List projects
//!
//! Get a list of projects for which the authenticated user is a member.
//!
//! ```text
//! GET /projects
//! ```
//!
//! Parameters:
//!
//! | Attribute | Type | Required | Description |
//! | --------- | ---- | -------- | ----------- |
//! | `archived` | boolean | no | Limit by archived status |
//! | `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
//! | `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
//! | `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
//! | `search` | string | no | Return list of authorized projects matching the search criteria |
//! | `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
//!

use serde_urlencoded;

use BuildQuery;
use Project;
use Projects;

pub mod all;
pub mod id_branches;
pub mod id_branch;
pub mod id_events;
pub mod id_hooks_id;
pub mod id_hooks;
pub mod id;
pub mod owned;
pub mod search;
pub mod starred;
pub mod visible;

use ::errors::*;

#[cfg(feature = "serde_derive")]
include!("serde_types.in.rs");

#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/projects/serde_types.rs"));

#[derive(Debug, Clone)]
pub struct ProjectsLister<'a> {
    gl: &'a ::GitLab,
    internal: ProjectListerInternal,
}

impl<'a> ProjectsLister<'a> {
    pub fn new(gl: &'a ::GitLab) -> ProjectsLister {
        ProjectsLister {
            gl: gl,
            internal: ProjectListerInternal {
                archived: None,
                visibility: None,
                order_by: None,
                sort: None,
                search: None,
                simple: None,
            },
        }
    }

    pub fn all(self) -> all::ProjectsLister<'a> {
        // assert_eq!(self, ProjectsLister::new(self.gl));
        all::ProjectsLister::new(self.gl)
    }

    pub fn owned(self) -> owned::ProjectsLister<'a> {
        // assert_eq!(self, ProjectsLister::new(self.gl));
        owned::ProjectsLister::new(self.gl)
    }

    pub fn search(self, query: String) -> search::ProjectsLister<'a> {
        // assert_eq!(self, ProjectsLister::new(self.gl));
        search::ProjectsLister::new(self.gl, query)
    }

    pub fn id(self, id: ListingId) -> id::ProjectsLister<'a> {
        // assert_eq!(self, ProjectsLister::new(self.gl));
        id::ProjectsLister::new(self.gl, id)
    }

    pub fn archived(&'a mut self, archived: bool) -> &'a mut ProjectsLister {
        self.internal.archived = Some(archived);
        self
    }

    pub fn visibility(&'a mut self, visibility: ::ListingVisibility) -> &'a mut ProjectsLister {
        self.internal.visibility = Some(visibility);
        self
    }

    pub fn order_by(&'a mut self, order_by: ListingOrderBy) -> &'a mut ProjectsLister {
        self.internal.order_by = Some(order_by);
        self
    }

    pub fn sort(&'a mut self, sort: ::ListingSort) -> &'a mut ProjectsLister {
        self.internal.sort = Some(sort);
        self
    }

    pub fn search_pattern(&'a mut self, search: String) -> &'a mut ProjectsLister {
        self.internal.search = Some(search);
        self
    }

    pub fn simple(&'a mut self, simple: bool) -> &'a mut ProjectsLister {
        self.internal.simple = Some(simple);
        self
    }

    /// Commit the lister: Query GitLab and return a list of projects.
    pub fn list(&self) -> Result<Projects> {
        let query = self.build_query();
        debug!("query: {:?}", query);

        self.gl.get(&query).chain_err(|| format!("cannot get query {}", query))
    }
}

impl<'a> BuildQuery for ProjectsLister<'a> {
    fn build_query(&self) -> String {

        let encoded = serde_urlencoded::to_string(&self.internal).unwrap();
        let mut query = String::from("projects");
        if !encoded.is_empty() {
            query.push_str("?");
            query.push_str(&encoded);
        }

        query
    }
}

impl<'a> Project {
    /// Return a lister for the project's issues
    pub fn issues(&'a self, gl: &'a ::GitLab) -> ::issues::project::IssuesLister {
        ::issues::project::IssuesLister::new(gl, self.id)
    }

    /// Return a lister for the project's merge requests
    pub fn merge_requests(&'a self, gl: &'a ::GitLab) -> ::merge_requests::MergeRequestsLister {
        ::merge_requests::MergeRequestsLister::new(gl, self.id)
    }
}

#[cfg(test)]
mod tests {
    use BuildQuery;

    #[test]
    fn build_query_default() {
        let expected_string = "projects";

        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let projects_lister = gl.projects();
        let query = projects_lister.build_query();
        assert_eq!(query, expected_string);

        let query = gl.projects().build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_archived() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?archived=true";

        let mut projects_lister = gl.projects();
        let query = projects_lister.archived(true).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().archived(true).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?archived=false";

        let mut projects_lister = gl.projects();
        let query = projects_lister.archived(false).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().archived(false).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_visibility() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?visibility=public";
        let mut projects_lister = gl.projects();
        let query = projects_lister.visibility(::ListingVisibility::Public).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().visibility(::ListingVisibility::Public).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?visibility=internal";
        let mut projects_lister = gl.projects();
        let query = projects_lister.visibility(::ListingVisibility::Internal).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().visibility(::ListingVisibility::Internal).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?visibility=private";
        let mut projects_lister = gl.projects();
        let query = projects_lister.visibility(::ListingVisibility::Private).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().visibility(::ListingVisibility::Private).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_order_by() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?order_by=id";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::Id).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::Id).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=name";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::Name).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::Name).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=path";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::Path).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::Path).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=created_at";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::CreatedAt).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::CreatedAt).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=updated_at";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::UpdatedAt).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::UpdatedAt).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=last_activity_at";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::LastActivityAt)
            .build_query();
        assert_eq!(query, expected_string);
        let query =
            gl.projects().order_by(::projects::ListingOrderBy::LastActivityAt).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_sort() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?sort=asc";
        let mut projects_lister = gl.projects();
        let query = projects_lister.sort(::ListingSort::Asc).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().sort(::ListingSort::Asc).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?sort=desc";
        let mut projects_lister = gl.projects();
        let query = projects_lister.sort(::ListingSort::Desc).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().sort(::ListingSort::Desc).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_search() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?search=SearchPattern";
        let mut projects_lister = gl.projects();
        let query = projects_lister.search_pattern(String::from("SearchPattern")).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().search_pattern(String::from("SearchPattern")).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_simple() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?simple=true";
        let mut projects_lister = gl.projects();
        let query = projects_lister.simple(true).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().simple(true).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?simple=false";
        let mut projects_lister = gl.projects();
        let query = projects_lister.simple(false).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().simple(false).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn groups_build_query_multiple() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?archived=true&simple=true";
        let mut projects_lister = gl.projects();
        let query = projects_lister.archived(true).simple(true).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().archived(true).simple(true).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn project_to_issues() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        let project_id = 123;
        let project = ::Project { id: project_id, ..Default::default() };
        let issues_lister = format!("{:?}", project.issues(&gl));
        let default_issues_lister = format!("{:?}", ::issues::project::IssuesLister::new(&gl, project_id));
        assert_eq!(issues_lister, default_issues_lister);
    }
}
<commit_msg>New unit test `project_to_merge_requests()` for `project.merge_requests()`<commit_after>//! List projects
//!
//! https://docs.gitlab.com/ce/api/projects.html
//!
//! # List projects
//!
//! Get a list of projects for which the authenticated user is a member.
//!
//! ```text
//! GET /projects
//! ```
//!
//! Parameters:
//!
//! | Attribute | Type | Required | Description |
//! | --------- | ---- | -------- | ----------- |
//! | `archived` | boolean | no | Limit by archived status |
//! | `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
//! | `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
//! | `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
//! | `search` | string | no | Return list of authorized projects matching the search criteria |
//! | `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
//!

use serde_urlencoded;

use BuildQuery;
use Project;
use Projects;

pub mod all;
pub mod id_branches;
pub mod id_branch;
pub mod id_events;
pub mod id_hooks_id;
pub mod id_hooks;
pub mod id;
pub mod owned;
pub mod search;
pub mod starred;
pub mod visible;

use ::errors::*;

#[cfg(feature = "serde_derive")]
include!("serde_types.in.rs");

#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/projects/serde_types.rs"));

#[derive(Debug, Clone)]
pub struct ProjectsLister<'a> {
    gl: &'a ::GitLab,
    internal: ProjectListerInternal,
}

impl<'a> ProjectsLister<'a> {
    pub fn new(gl: &'a ::GitLab) -> ProjectsLister {
        ProjectsLister {
            gl: gl,
            internal: ProjectListerInternal {
                archived: None,
                visibility: None,
                order_by: None,
                sort: None,
                search: None,
                simple: None,
            },
        }
    }

    pub fn all(self) -> all::ProjectsLister<'a> {
        // assert_eq!(self, ProjectsLister::new(self.gl));
        all::ProjectsLister::new(self.gl)
    }

    pub fn owned(self) -> owned::ProjectsLister<'a> {
        // assert_eq!(self, ProjectsLister::new(self.gl));
        owned::ProjectsLister::new(self.gl)
    }

    pub fn search(self, query: String) -> search::ProjectsLister<'a> {
        // assert_eq!(self, ProjectsLister::new(self.gl));
        search::ProjectsLister::new(self.gl, query)
    }

    pub fn id(self, id: ListingId) -> id::ProjectsLister<'a> {
        // assert_eq!(self, ProjectsLister::new(self.gl));
        id::ProjectsLister::new(self.gl, id)
    }

    pub fn archived(&'a mut self, archived: bool) -> &'a mut ProjectsLister {
        self.internal.archived = Some(archived);
        self
    }

    pub fn visibility(&'a mut self, visibility: ::ListingVisibility) -> &'a mut ProjectsLister {
        self.internal.visibility = Some(visibility);
        self
    }

    pub fn order_by(&'a mut self, order_by: ListingOrderBy) -> &'a mut ProjectsLister {
        self.internal.order_by = Some(order_by);
        self
    }

    pub fn sort(&'a mut self, sort: ::ListingSort) -> &'a mut ProjectsLister {
        self.internal.sort = Some(sort);
        self
    }

    pub fn search_pattern(&'a mut self, search: String) -> &'a mut ProjectsLister {
        self.internal.search = Some(search);
        self
    }

    pub fn simple(&'a mut self, simple: bool) -> &'a mut ProjectsLister {
        self.internal.simple = Some(simple);
        self
    }

    /// Commit the lister: Query GitLab and return a list of projects.
    pub fn list(&self) -> Result<Projects> {
        let query = self.build_query();
        debug!("query: {:?}", query);

        self.gl.get(&query).chain_err(|| format!("cannot get query {}", query))
    }
}

impl<'a> BuildQuery for ProjectsLister<'a> {
    fn build_query(&self) -> String {

        let encoded = serde_urlencoded::to_string(&self.internal).unwrap();
        let mut query = String::from("projects");
        if !encoded.is_empty() {
            query.push_str("?");
            query.push_str(&encoded);
        }

        query
    }
}

impl<'a> Project {
    /// Return a lister for the project's issues
    pub fn issues(&'a self, gl: &'a ::GitLab) -> ::issues::project::IssuesLister {
        ::issues::project::IssuesLister::new(gl, self.id)
    }

    /// Return a lister for the project's merge requests
    pub fn merge_requests(&'a self, gl: &'a ::GitLab) -> ::merge_requests::MergeRequestsLister {
        ::merge_requests::MergeRequestsLister::new(gl, self.id)
    }
}

#[cfg(test)]
mod tests {
    use BuildQuery;

    #[test]
    fn build_query_default() {
        let expected_string = "projects";

        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let projects_lister = gl.projects();
        let query = projects_lister.build_query();
        assert_eq!(query, expected_string);

        let query = gl.projects().build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_archived() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?archived=true";

        let mut projects_lister = gl.projects();
        let query = projects_lister.archived(true).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().archived(true).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?archived=false";

        let mut projects_lister = gl.projects();
        let query = projects_lister.archived(false).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().archived(false).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_visibility() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?visibility=public";
        let mut projects_lister = gl.projects();
        let query = projects_lister.visibility(::ListingVisibility::Public).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().visibility(::ListingVisibility::Public).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?visibility=internal";
        let mut projects_lister = gl.projects();
        let query = projects_lister.visibility(::ListingVisibility::Internal).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().visibility(::ListingVisibility::Internal).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?visibility=private";
        let mut projects_lister = gl.projects();
        let query = projects_lister.visibility(::ListingVisibility::Private).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().visibility(::ListingVisibility::Private).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_order_by() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?order_by=id";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::Id).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::Id).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=name";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::Name).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::Name).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=path";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::Path).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::Path).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=created_at";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::CreatedAt).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::CreatedAt).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=updated_at";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::UpdatedAt).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().order_by(::projects::ListingOrderBy::UpdatedAt).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?order_by=last_activity_at";
        let mut projects_lister = gl.projects();
        let query = projects_lister.order_by(::projects::ListingOrderBy::LastActivityAt)
            .build_query();
        assert_eq!(query, expected_string);
        let query =
            gl.projects().order_by(::projects::ListingOrderBy::LastActivityAt).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_sort() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?sort=asc";
        let mut projects_lister = gl.projects();
        let query = projects_lister.sort(::ListingSort::Asc).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().sort(::ListingSort::Asc).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?sort=desc";
        let mut projects_lister = gl.projects();
        let query = projects_lister.sort(::ListingSort::Desc).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().sort(::ListingSort::Desc).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_search() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?search=SearchPattern";
        let mut projects_lister = gl.projects();
        let query = projects_lister.search_pattern(String::from("SearchPattern")).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().search_pattern(String::from("SearchPattern")).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_simple() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?simple=true";
        let mut projects_lister = gl.projects();
        let query = projects_lister.simple(true).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().simple(true).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects?simple=false";
        let mut projects_lister = gl.projects();
        let query = projects_lister.simple(false).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().simple(false).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn groups_build_query_multiple() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = "projects?archived=true&simple=true";
        let mut projects_lister = gl.projects();
        let query = projects_lister.archived(true).simple(true).build_query();
        assert_eq!(query, expected_string);
        let query = gl.projects().archived(true).simple(true).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn project_to_issues() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        let project_id = 123;
        let project = ::Project { id: project_id, ..Default::default() };
        let issues_lister = format!("{:?}", project.issues(&gl));
        let default_issues_lister = format!("{:?}", ::issues::project::IssuesLister::new(&gl, project_id));
        assert_eq!(issues_lister, default_issues_lister);
    }

    #[test]
    fn project_to_merge_requests() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        let project_id = 123;
        let project = ::Project { id: project_id, ..Default::default() };
        let merge_requests_lister = format!("{:?}", project.merge_requests(&gl));
        let default_merge_requests_lister = format!("{:?}", ::merge_requests::MergeRequestsLister::new(&gl, project_id));
        assert_eq!(merge_requests_lister, default_merge_requests_lister);
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;

pub fn add(num_l: &str, num_r: &str) -> String {
    let sum = merge(denormalize(num_l), denormalize(num_r));
    normalize(&sum)
}

fn cmp(l: char, r: char) -> Ordering {
    match(l, r) {
        ('L', 'L') => Ordering::Equal,
        (_, 'L') => Ordering::Less,
        ('L', _) => Ordering::Greater,
        ('X', 'X') => Ordering::Equal,
        (_, 'X') => Ordering::Less,
        ('X', _) => Ordering::Greater,
        ('V', 'V') => Ordering::Equal,
        (_, 'V') => Ordering::Less,
        ('V', _) => Ordering::Greater,
        (_, _) => Ordering::Equal,
    }
}

fn merge(num_l: String, num_r: String) -> String {
    let mut digits_l = num_l.chars();
    let mut digits_r = num_r.chars();

    let mut sum = String::new();

    let mut next_l = digits_l.next();
    let mut next_r = digits_r.next();
    loop {
        match (next_l, next_r) {
            (Some(l), Some(r)) => {
                if cmp(l, r) == Ordering::Greater {
                    sum.push(l);
                    next_l = digits_l.next();
                } else {
                    sum.push(r);
                    next_r = digits_r.next();
                }
            },
            (Some(l), None) => {
                sum.push(l);
                next_l = digits_l.next();
            },
            (None, Some(r)) => {
                sum.push(r);
                next_r = digits_r.next();
            },
            (None, None) => { break }
        }
    }

    sum
}

pub fn denormalize(num: &str) -> String {
    let num = num.replace("IV", "IIII");
    let num = num.replace("IX", "VIIII");
    let num = num.replace("XL", "XXXX");
    num
}

pub fn normalize(num: &str) -> String {
    let num = num.replace("IIIII", "V");
    let num = num.replace("IIII", "IV");
    let num = num.replace("VIV", "IX");
    let num = num.replace("VV", "X");
    let num = num.replace("XXXXX", "L");
    num
}

#[cfg(test)]
mod tests {
    use super::add;
    use super::cmp;
    use super::normalize;
    use super::denormalize;

    use std::cmp::Ordering;

    #[test]
    fn i_equal_to_i() {
        assert_eq!(Ordering::Equal, cmp('I', 'I'));
    }

    #[test]
    fn i_less_than_v() {
        assert_eq!(Ordering::Less, cmp('I', 'V'));
    }

    #[test]
    fn v_greater_than_i() {
        assert_eq!(Ordering::Greater, cmp('V', 'I'));
    }

    #[test]
    fn v_equal_to_v() {
        assert_eq!(Ordering::Equal, cmp('V', 'V'));
    }

    #[test]
    fn x_greater_than_v() {
        assert_eq!(Ordering::Greater, cmp('X', 'V'));
    }

    #[test]
    fn v_less_than_x() {
        assert_eq!(Ordering::Less, cmp('V', 'X'));
    }

    #[test]
    fn x_equal_to_x() {
        assert_eq!(Ordering::Equal, cmp('X', 'X'));
    }

    #[test]
    fn l_greater_than_x() {
        assert_eq!(Ordering::Greater, cmp('L', 'X'));
    }

    #[test]
    fn x_less_than_l() {
        assert_eq!(Ordering::Less, cmp('X', 'L'));
    }

    #[test]
    fn l_equal_to_l() {
        assert_eq!(Ordering::Equal, cmp('L', 'L'));
    }

    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    #[test]
    fn add_ii_iii_requires_normalization_to_v() {
        assert_eq!("V", add("II", "III"));

    }

    #[test]
    fn add_v_i() {
        assert_eq!("VI", add("V", "I"));
    }

    #[test]
    fn add_i_v_understands_the_relative_order_of_v_and_i() {
        assert_eq!("VI", add("I", "V"));
    }

    #[test]
    fn add_i_iv_denormalizes_before_adding() {
        assert_eq!("V", add("I", "IV"));
    }

    #[test]
    fn add_l_i_supports_l() {
        assert_eq!("LI", add("L", "I"));
    }

    #[test]
    fn add_l_xi_understands_l_x_sort_order() {
        assert_eq!("LXI", add("L", "XI"));
    }

    #[test]
    fn denormalize_iv() {
        assert_eq!("IIII", denormalize("IV"));
    }

    #[test]
    fn denormalize_ix() {
        assert_eq!("VIIII", denormalize("IX"));
    }

    #[test]
    fn denormalize_xiv_performs_a_partial_denormalization_on_tail() {
        assert_eq!("XIIII", denormalize("XIV"));
    }

    #[test]
    fn denormalize_xl() {
        assert_eq!("XXXX", denormalize("XL"));
    }

    #[test]
    fn normalize_iiiii() {
        assert_eq!("V", normalize("IIIII"));
    }

    #[test]
    fn normalize_iiii() {
        assert_eq!("IV", normalize("IIII"));
    }

    #[test]
    fn normalize_vv() {
        assert_eq!("X", normalize("VV"));
    }

    #[test]
    fn normalize_viiii() {
        assert_eq!("IX", normalize("VIIII"));
    }

    #[test]
    fn normalize_viiiii() {
        assert_eq!("X", normalize("VIIIII"));
    }

    #[test]
    fn normalize_xxxxx() {
        assert_eq!("L", normalize("XXXXX"));
    }
}
<commit_msg>cmp() now supports full roman numeral alphabet in Rust<commit_after>use std::cmp::Ordering;

pub fn add(num_l: &str, num_r: &str) -> String {
    let sum = merge(denormalize(num_l), denormalize(num_r));
    normalize(&sum)
}

fn cmp(l: char, r: char) -> Ordering {
    if l == r {
        Ordering::Equal
    } else {
        match(l, r) {
            (_, 'M') => Ordering::Less,
            ('M', _) => Ordering::Greater,
            (_, 'D') => Ordering::Less,
            ('D', _) => Ordering::Greater,
            (_, 'C') => Ordering::Less,
            ('C', _) => Ordering::Greater,
            (_, 'L') => Ordering::Less,
            ('L', _) => Ordering::Greater,
            (_, 'X') => Ordering::Less,
            ('X', _) => Ordering::Greater,
            (_, 'V') => Ordering::Less,
            ('V', _) => Ordering::Greater,
            (_, _) => Ordering::Equal,
        }
    }
}

fn merge(num_l: String, num_r: String) -> String {
    let mut digits_l = num_l.chars();
    let mut digits_r = num_r.chars();

    let mut sum = String::new();

    let mut next_l = digits_l.next();
    let mut next_r = digits_r.next();
    loop {
        match (next_l, next_r) {
            (Some(l), Some(r)) => {
                if cmp(l, r) == Ordering::Greater {
                    sum.push(l);
                    next_l = digits_l.next();
                } else {
                    sum.push(r);
                    next_r = digits_r.next();
                }
            },
            (Some(l), None) => {
                sum.push(l);
                next_l = digits_l.next();
            },
            (None, Some(r)) => {
                sum.push(r);
                next_r = digits_r.next();
            },
            (None, None) => { break }
        }
    }

    sum
}

pub fn denormalize(num: &str) -> String {
    let num = num.replace("IV", "IIII");
    let num = num.replace("IX", "VIIII");
    let num = num.replace("XL", "XXXX");
    num
}

pub fn normalize(num: &str) -> String {
    let num = num.replace("IIIII", "V");
    let num = num.replace("IIII", "IV");
    let num = num.replace("VIV", "IX");
    let num = num.replace("VV", "X");
    let num = num.replace("XXXXX", "L");
    num
}

#[cfg(test)]
mod tests {
    use super::add;
    use super::cmp;
    use super::normalize;
    use super::denormalize;

    use std::cmp::Ordering;

    #[test] fn i_equal_to_i() { assert_eq!(Ordering::Equal, cmp('I', 'I')); }

    #[test] fn i_less_than_v() { assert_eq!(Ordering::Less, cmp('I', 'V')); }
    #[test] fn v_greater_than_i() { assert_eq!(Ordering::Greater, cmp('V', 'I')); }
    #[test] fn v_equal_to_v() { assert_eq!(Ordering::Equal, cmp('V', 'V')); }

    #[test] fn x_greater_than_v() { assert_eq!(Ordering::Greater, cmp('X', 'V')); }
    #[test] fn v_less_than_x() { assert_eq!(Ordering::Less, cmp('V', 'X')); }
    #[test] fn x_equal_to_x() { assert_eq!(Ordering::Equal, cmp('X', 'X')); }

    #[test] fn l_greater_than_x() { assert_eq!(Ordering::Greater, cmp('L', 'X')); }
    #[test] fn x_less_than_l() { assert_eq!(Ordering::Less, cmp('X', 'L')); }
    #[test] fn l_equal_to_l() { assert_eq!(Ordering::Equal, cmp('L', 'L')); }

    #[test] fn c_greater_than_l() { assert_eq!(Ordering::Greater, cmp('C', 'L')); }
    #[test] fn l_less_than_c() { assert_eq!(Ordering::Less, cmp('L', 'C')); }
    #[test] fn c_equal_to_c() { assert_eq!(Ordering::Equal, cmp('C', 'C')); }

    #[test] fn d_greater_than_c() { assert_eq!(Ordering::Greater, cmp('D', 'C')); }
    #[test] fn c_less_than_d() { assert_eq!(Ordering::Less, cmp('C', 'D')); }
    #[test] fn d_equal_to_d() { assert_eq!(Ordering::Equal, cmp('D', 'D')); }

    #[test] fn m_greater_than_d() { assert_eq!(Ordering::Greater, cmp('M', 'D')); }
    #[test] fn d_less_than_m() { assert_eq!(Ordering::Less, cmp('D', 'M')); }
    #[test] fn m_equal_to_m() { assert_eq!(Ordering::Equal, cmp('M', 'M')); }

    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    #[test]
    fn add_ii_iii_requires_normalization_to_v() {
        assert_eq!("V", add("II", "III"));

    }

    #[test]
    fn add_v_i() {
        assert_eq!("VI", add("V", "I"));
    }

    #[test]
    fn add_i_v_understands_the_relative_order_of_v_and_i() {
        assert_eq!("VI", add("I", "V"));
    }

    #[test]
    fn add_i_iv_denormalizes_before_adding() {
        assert_eq!("V", add("I", "IV"));
    }

    #[test]
    fn add_l_i_supports_l() {
        assert_eq!("LI", add("L", "I"));
    }

    #[test]
    fn add_l_xi_understands_l_x_sort_order() {
        assert_eq!("LXI", add("L", "XI"));
    }

    #[test]
    fn denormalize_iv() {
        assert_eq!("IIII", denormalize("IV"));
    }

    #[test]
    fn denormalize_ix() {
        assert_eq!("VIIII", denormalize("IX"));
    }

    #[test]
    fn denormalize_xiv_performs_a_partial_denormalization_on_tail() {
        assert_eq!("XIIII", denormalize("XIV"));
    }

    #[test]
    fn denormalize_xl() {
        assert_eq!("XXXX", denormalize("XL"));
    }

    #[test]
    fn normalize_iiiii() {
        assert_eq!("V", normalize("IIIII"));
    }

    #[test]
    fn normalize_iiii() {
        assert_eq!("IV", normalize("IIII"));
    }

    #[test]
    fn normalize_vv() {
        assert_eq!("X", normalize("VV"));
    }

    #[test]
    fn normalize_viiii() {
        assert_eq!("IX", normalize("VIIII"));
    }

    #[test]
    fn normalize_viiiii() {
        assert_eq!("X", normalize("VIIIII"));
    }

    #[test]
    fn normalize_xxxxx() {
        assert_eq!("L", normalize("XXXXX"));
    }
}
<|endoftext|>


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

#![cfg_attr(feature = "clippy", allow(inline_always))]

#[cfg(feature = "simd")]
macro_rules! transmute_shuffle {
    ($tmp:ident, $shuffle:ident, $vec:expr, $idx:expr) => {
        unsafe {
            use simdty::$tmp;
            use simdint::$shuffle;
            use std::mem::transmute;

            let tmp_i: $tmp = transmute($vec);
            let tmp_o: $tmp = $shuffle(tmp_i, tmp_i, $idx);
            transmute(tmp_o)
        }
    }
}

#[cfg(feature = "simd")] pub mod u32x4;
#[cfg(feature = "simd")] pub mod u64x4;

#[cfg(not(feature = "simd"))]
macro_rules! simd_opt {
    ($vec:ident) => {
        pub mod $vec {
            use simdty::$vec;

            #[inline(always)]
            pub fn rotate_right_const(vec: $vec, n: u32) -> $vec {
                $vec::new(vec.0.rotate_right(n),
                          vec.1.rotate_right(n),
                          vec.2.rotate_right(n),
                          vec.3.rotate_right(n))
            }
        }
    }
}

#[cfg(not(feature = "simd"))] simd_opt!(u32x4);
#[cfg(not(feature = "simd"))] simd_opt!(u64x4);
<commit_msg>Fix no_std simd_opt<commit_after>// Copyright 2015 blake2-rfc Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

#![cfg_attr(feature = "clippy", allow(inline_always))]

#[cfg(feature = "simd")]
macro_rules! transmute_shuffle {
    ($tmp:ident, $shuffle:ident, $vec:expr, $idx:expr) => {
        unsafe {
            use simdty::$tmp;
            use simdint::$shuffle;
            use core::mem::transmute;

            let tmp_i: $tmp = transmute($vec);
            let tmp_o: $tmp = $shuffle(tmp_i, tmp_i, $idx);
            transmute(tmp_o)
        }
    }
}

#[cfg(feature = "simd")] pub mod u32x4;
#[cfg(feature = "simd")] pub mod u64x4;

#[cfg(not(feature = "simd"))]
macro_rules! simd_opt {
    ($vec:ident) => {
        pub mod $vec {
            use simdty::$vec;

            #[inline(always)]
            pub fn rotate_right_const(vec: $vec, n: u32) -> $vec {
                $vec::new(vec.0.rotate_right(n),
                          vec.1.rotate_right(n),
                          vec.2.rotate_right(n),
                          vec.3.rotate_right(n))
            }
        }
    }
}

#[cfg(not(feature = "simd"))] simd_opt!(u32x4);
#[cfg(not(feature = "simd"))] simd_opt!(u64x4);
<|endoftext|>


<commit_before>//! Syslog drain for slog-rs
//!
//! WARNING: This crate needs some improvements.
//!
//! ```
//! #[macro_use]
//! extern crate slog;
//! extern crate slog_syslog;
//!
//! use slog::*;
//! use slog_syslog::Facility;
//!
//! fn main() {
//!     let root = Logger::new_root(o!("build-id" => "8dfljdf"));
//!     root.set_drain(
//!             slog_syslog::unix_3164(
//!                 Facility::LOG_USER,
//!                 )
//!             );
//! }
//! ```
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate syslog;
extern crate nix;
extern crate rustc_serialize as serialize;

use slog::format;
use slog::format::Format;
use slog::drain;
use slog::Level;
use slog::ser::Serializer;
use slog::logger::RecordInfo;
use slog::{OwnedKeyValue, BorrowedKeyValue};
use std::io;
use std::sync::Mutex;
use serialize::hex::ToHex;

pub use syslog::Facility;

fn level_to_severity(level : slog::Level) -> syslog::Severity {
    match level {
        Level::Critical => syslog::Severity::LOG_CRIT,
        Level::Error => syslog::Severity::LOG_ERR,
        Level::Warning => syslog::Severity::LOG_WARNING,
        Level::Info => syslog::Severity::LOG_NOTICE,
        Level::Debug => syslog::Severity::LOG_INFO,
        Level::Trace => syslog::Severity::LOG_DEBUG,
    }

}

/// Drain formatting records and writing them to a syslog ``Logger`
///
/// Uses mutex to serialize writes.
/// TODO: Add one that does not serialize?
pub struct Streamer3164 {
    io: Mutex<Box<syslog::Logger>>,
    format : Format3164,
}

impl Streamer3164 {
    /// Create new syslog ``Streamer` using given `format`
    pub fn new(logger : Box<syslog::Logger>) -> Self {
        Streamer3164 {
            io: Mutex::new(logger),
            format : Format3164::new(),
        }
    }
}

impl drain::Drain for Streamer3164 {
    fn log(&self,
           info: &RecordInfo,
           logger_values: &[OwnedKeyValue],
           values: &[BorrowedKeyValue]) {
        let mut buf = Vec::with_capacity(128);
        self.format.format(&mut buf, info, logger_values, values);
        let sever = level_to_severity(info.level);
        {
            let io = self.io.lock().unwrap();
            io.send(sever, &String::from_utf8_lossy(&buf)).unwrap();
        }
    }
}

/// Formatter to format defined in RFC 3164
pub struct Format3164;

impl Format3164 {
    /// Create new `Format3164`
    pub fn new() -> Self {
        Format3164
    }
}

impl format::Format for Format3164 {
    fn format(&self,
              io : &mut io::Write,
              rinfo: &RecordInfo,
              logger_values: &[OwnedKeyValue],
              record_values: &[BorrowedKeyValue]) {
        let mut ser = KSV::new(io, "=".into());
        {
            for &(ref k, ref v) in logger_values.iter() {
                v.serialize(rinfo, k, &mut ser);
                let _ = ser.io().write_all(" ".as_bytes());
            }

            for &(ref k, ref v) in record_values.iter() {
                v.serialize(rinfo, k, &mut ser);
                let _ = ser.io().write_all(" ".as_bytes());
            }
        }
    }
}

/// Key-Separator-Value serializer
struct KSV<W : io::Write> {
    separator : String,
    io : W,
}

impl<W : io::Write> KSV<W> {
    fn new(io : W, separator : String) -> Self {
        KSV {
            io: io,
            separator : separator,
        }
    }

    fn io(&mut self) -> &mut W {
        &mut self.io
    }
}

impl<W : io::Write> Serializer for KSV<W> {
    fn emit_none(&mut self, key: &str) {
        write!(self.io, "{}{}{}", key, self.separator, "None").unwrap()
    }
    fn emit_unit(&mut self, key: &str) {
        write!(self.io, "{}", key).unwrap()
    }

    fn emit_bool(&mut self, key: &str, val: bool) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }

    fn emit_char(&mut self, key: &str, val: char) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_bytes(&mut self, key: &str, val: &[u8]) {
        write!(self.io, "{}{}{}", key, self.separator, val.to_hex()).unwrap()
    }

    fn emit_usize(&mut self, key: &str, val: usize) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_isize(&mut self, key: &str, val: isize) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }

    fn emit_u8(&mut self, key: &str, val: u8) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_i8(&mut self, key: &str, val: i8) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_u16(&mut self, key: &str, val: u16) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_i16(&mut self, key: &str, val: i16) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_u32(&mut self, key: &str, val: u32) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_i32(&mut self, key: &str, val: i32) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_f32(&mut self, key: &str, val: f32) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_u64(&mut self, key: &str, val: u64) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_i64(&mut self, key: &str, val: i64) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_f64(&mut self, key: &str, val: f64) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_str(&mut self, key: &str, val: &str) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
}

/// ``Streamer` to Unix syslog using RFC 3164 format
pub fn unix_3164(facility : syslog::Facility) -> Streamer3164 {
    Streamer3164::new(
        syslog::unix(facility).unwrap(),
        )
}
<commit_msg>slog-syslog: disable failing doc-test<commit_after>//! Syslog drain for slog-rs
//!
//! WARNING: This crate needs some improvements.
//!
//! ```norust
//! #[macro_use]
//! extern crate slog;
//! extern crate slog_syslog;
//!
//! use slog::*;
//! use slog_syslog::Facility;
//!
//! fn main() {
//!     let root = Logger::new_root(o!("build-id" => "8dfljdf"));
//!     root.set_drain(
//!             slog_syslog::unix_3164(
//!                 Facility::LOG_USER,
//!                 )
//!             );
//! }
//! ```
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate syslog;
extern crate nix;
extern crate rustc_serialize as serialize;

use slog::format;
use slog::format::Format;
use slog::drain;
use slog::Level;
use slog::ser::Serializer;
use slog::logger::RecordInfo;
use slog::{OwnedKeyValue, BorrowedKeyValue};
use std::io;
use std::sync::Mutex;
use serialize::hex::ToHex;

pub use syslog::Facility;

fn level_to_severity(level : slog::Level) -> syslog::Severity {
    match level {
        Level::Critical => syslog::Severity::LOG_CRIT,
        Level::Error => syslog::Severity::LOG_ERR,
        Level::Warning => syslog::Severity::LOG_WARNING,
        Level::Info => syslog::Severity::LOG_NOTICE,
        Level::Debug => syslog::Severity::LOG_INFO,
        Level::Trace => syslog::Severity::LOG_DEBUG,
    }

}

/// Drain formatting records and writing them to a syslog ``Logger`
///
/// Uses mutex to serialize writes.
/// TODO: Add one that does not serialize?
pub struct Streamer3164 {
    io: Mutex<Box<syslog::Logger>>,
    format : Format3164,
}

impl Streamer3164 {
    /// Create new syslog ``Streamer` using given `format`
    pub fn new(logger : Box<syslog::Logger>) -> Self {
        Streamer3164 {
            io: Mutex::new(logger),
            format : Format3164::new(),
        }
    }
}

impl drain::Drain for Streamer3164 {
    fn log(&self,
           info: &RecordInfo,
           logger_values: &[OwnedKeyValue],
           values: &[BorrowedKeyValue]) {
        let mut buf = Vec::with_capacity(128);
        self.format.format(&mut buf, info, logger_values, values);
        let sever = level_to_severity(info.level);
        {
            let io = self.io.lock().unwrap();
            io.send(sever, &String::from_utf8_lossy(&buf)).unwrap();
        }
    }
}

/// Formatter to format defined in RFC 3164
pub struct Format3164;

impl Format3164 {
    /// Create new `Format3164`
    pub fn new() -> Self {
        Format3164
    }
}

impl format::Format for Format3164 {
    fn format(&self,
              io : &mut io::Write,
              rinfo: &RecordInfo,
              logger_values: &[OwnedKeyValue],
              record_values: &[BorrowedKeyValue]) {
        let mut ser = KSV::new(io, "=".into());
        {
            for &(ref k, ref v) in logger_values.iter() {
                v.serialize(rinfo, k, &mut ser);
                let _ = ser.io().write_all(" ".as_bytes());
            }

            for &(ref k, ref v) in record_values.iter() {
                v.serialize(rinfo, k, &mut ser);
                let _ = ser.io().write_all(" ".as_bytes());
            }
        }
    }
}

/// Key-Separator-Value serializer
struct KSV<W : io::Write> {
    separator : String,
    io : W,
}

impl<W : io::Write> KSV<W> {
    fn new(io : W, separator : String) -> Self {
        KSV {
            io: io,
            separator : separator,
        }
    }

    fn io(&mut self) -> &mut W {
        &mut self.io
    }
}

impl<W : io::Write> Serializer for KSV<W> {
    fn emit_none(&mut self, key: &str) {
        write!(self.io, "{}{}{}", key, self.separator, "None").unwrap()
    }
    fn emit_unit(&mut self, key: &str) {
        write!(self.io, "{}", key).unwrap()
    }

    fn emit_bool(&mut self, key: &str, val: bool) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }

    fn emit_char(&mut self, key: &str, val: char) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_bytes(&mut self, key: &str, val: &[u8]) {
        write!(self.io, "{}{}{}", key, self.separator, val.to_hex()).unwrap()
    }

    fn emit_usize(&mut self, key: &str, val: usize) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_isize(&mut self, key: &str, val: isize) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }

    fn emit_u8(&mut self, key: &str, val: u8) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_i8(&mut self, key: &str, val: i8) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_u16(&mut self, key: &str, val: u16) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_i16(&mut self, key: &str, val: i16) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_u32(&mut self, key: &str, val: u32) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_i32(&mut self, key: &str, val: i32) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_f32(&mut self, key: &str, val: f32) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_u64(&mut self, key: &str, val: u64) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_i64(&mut self, key: &str, val: i64) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_f64(&mut self, key: &str, val: f64) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
    fn emit_str(&mut self, key: &str, val: &str) {
        write!(self.io, "{}{}{}", key, self.separator, val).unwrap()
    }
}

/// ``Streamer` to Unix syslog using RFC 3164 format
pub fn unix_3164(facility : syslog::Facility) -> Streamer3164 {
    Streamer3164::new(
        syslog::unix(facility).unwrap(),
        )
}
<|endoftext|>


<commit_before>//! SSL client support.
//!
//! Which particular library is used depends upon the configuration used at
//! compile time; at present it can only be OpenSSL (`--cfg openssl`); without
//! that, you won't be able to use SSL (an attempt to make an HTTPS connection
//! will return an error).

#[cfg(not(nossl))]
pub use self::openssl::NetworkStream;
#[cfg(nossl)]
pub use self::none::NetworkStream;

#[cfg(not(nossl))]
mod openssl;
#[cfg(nossl)]
mod none;
<commit_msg>Disable SSL support on android.<commit_after>//! SSL client support.
//!
//! Which particular library is used depends upon the configuration used at
//! compile time; at present it can only be OpenSSL (`--cfg openssl`); without
//! that, you won't be able to use SSL (an attempt to make an HTTPS connection
//! will return an error).

#[cfg(not(nossl),not(target_os="android"))]
pub use self::openssl::NetworkStream;
#[cfg(nossl)]
#[cfg(target_os="android")]
pub use self::none::NetworkStream;

#[cfg(not(nossl),not(target_os="android"))]
mod openssl;
#[cfg(nossl)]
#[cfg(target_os="android")]
mod none;
<|endoftext|>


<commit_before>//! Implements `Syscalls` for all types that implement `RawSyscalls`.

use crate::{
    exit_id, exit_on_drop, return_variant, subscribe, syscall_class, yield_id, CommandReturn,
    ErrorCode, RawSyscalls, Register, ReturnVariant, Subscribe, Syscalls, Upcall,
    YieldNoWaitReturn,
};

impl<S: RawSyscalls> Syscalls for S {
    // -------------------------------------------------------------------------
    // Yield
    // -------------------------------------------------------------------------

    fn yield_no_wait() -> YieldNoWaitReturn {
        let mut flag = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();

        unsafe {
            // Flag can be uninitialized here because the kernel promises to
            // only write to it, not read from it. MaybeUninit guarantees that
            // it is safe to write a YieldNoWaitReturn into it.
            Self::yield2([yield_id::NO_WAIT.into(), flag.as_mut_ptr().into()]);

            // yield-no-wait guarantees it sets (initializes) flag before
            // returning.
            flag.assume_init()
        }
    }

    fn yield_wait() {
        // Safety: yield-wait does not return a value, which satisfies yield1's
        // requirement. The yield-wait system call cannot trigger undefined
        // behavior on its own in any other way.
        unsafe {
            Self::yield1([yield_id::WAIT.into()]);
        }
    }

    // -------------------------------------------------------------------------
    // Subscribe
    // -------------------------------------------------------------------------

    fn subscribe<
        'scope,
        IDS: subscribe::SupportsId<DRIVER_NUM, SUBSCRIBE_NUM>,
        U: Upcall<IDS>,
        CONFIG: subscribe::Config,
        const DRIVER_NUM: u32,
        const SUBSCRIBE_NUM: u32,
    >(
        _subscribe: &Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM>,
        upcall: &'scope U,
    ) -> Result<(), ErrorCode> {
        // The upcall function passed to the Tock kernel.
        //
        // Safety: data must be a reference to a valid instance of U.
        unsafe extern "C" fn kernel_upcall<S: Syscalls, IDS, U: Upcall<IDS>>(
            arg0: u32,
            arg1: u32,
            arg2: u32,
            data: Register,
        ) {
            let upcall: *const U = data.into();
            let exit: exit_on_drop::ExitOnDrop<S> = Default::default();
            unsafe { &*upcall }.upcall(arg0, arg1, arg2);
            core::mem::forget(exit);
        }

        // Inner function that does the majority of the work. This is not
        // monomorphized over DRIVER_NUM and SUBSCRIBE_NUM to keep code size
        // small.
        //
        // Safety: upcall_fcn must be kernel_upcall<S, IDS, U> and upcall_data
        // must be a reference to an instance of U that will remain valid as
        // long as the 'scope lifetime is alive. Can only be called if a
        // Subscribe<'scope, S, driver_num, subscribe_num> exists.
        unsafe fn inner<S: Syscalls, CONFIG: subscribe::Config>(
            driver_num: u32,
            subscribe_num: u32,
            upcall_fcn: Register,
            upcall_data: Register,
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Subscribe. These arguments follow TRD104. kernel_upcall has the
            // required signature. This function's preconditions mean that
            // upcall is a reference to an instance of U that will remain valid
            // until the 'scope lifetime is alive The existence of the
            // Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM> guarantees
            // that if this Subscribe succeeds then the upcall will be cleaned
            // up before the 'scope lifetime ends, guaranteeing that upcall is
            // still alive when kernel_upcall is invoked.
            let [r0, r1, _, _] = unsafe {
                S::syscall4::<{ syscall_class::SUBSCRIBE }>([
                    driver_num.into(),
                    subscribe_num.into(),
                    upcall_fcn,
                    upcall_data,
                ])
            };

            let return_variant: ReturnVariant = r0.as_u32().into();
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                Err(unsafe { core::mem::transmute(r1.as_u32() as u16) })
            } else {
                // r0 indicates Success with 2 u32s. Confirm the null upcall was
                // returned, and it if wasn't then call the configured function.
                // We're relying on the optimizer to remove this branch if
                // returned_nonnull_upcall is a no-op.
                let returned_upcall: *const () = r1.into();
                // Note: TRD 104 specifies that the null upcall has address 0,
                // not necessarily a null pointer.
                #[allow(clippy::zero_ptr)]
                if returned_upcall != 0 as *const () {
                    CONFIG::returned_nonnull_upcall(driver_num, subscribe_num);
                }
                Ok(())
            }
        }

        let upcall_fcn = (kernel_upcall::<S, IDS, U> as usize).into();
        let upcall_data = (upcall as *const U).into();
        // Safety: upcall's type guarantees it is a reference to a U that will
        // remain valid for at least the 'scope lifetime. _subscribe is a
        // reference to a Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM>,
        // proving one exists. upcall_fcn and upcall_data are derived in ways
        // that satisfy inner's requirements.
        unsafe { inner::<Self, CONFIG>(DRIVER_NUM, SUBSCRIBE_NUM, upcall_fcn, upcall_data) }
    }

    fn unsubscribe(driver_num: u32, subscribe_num: u32) {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Subscribe. The upcall pointer passed is the null upcall, which
            // cannot cause undefined behavior on its own.
            Self::syscall4::<{ syscall_class::SUBSCRIBE }>([
                driver_num.into(),
                subscribe_num.into(),
                0usize.into(),
                0usize.into(),
            ]);
        }
    }

    // -------------------------------------------------------------------------
    // Command
    // -------------------------------------------------------------------------

    fn command(driver_id: u32, command_id: u32, argument0: u32, argument1: u32) -> CommandReturn {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Command. The Command system call cannot trigger undefined
            // behavior on its own.
            let [r0, r1, r2, r3] = Self::syscall4::<{ syscall_class::COMMAND }>([
                driver_id.into(),
                command_id.into(),
                argument0.into(),
                argument1.into(),
            ]);

            // Because r0 and r1 are returned directly from the kernel, we are
            // guaranteed that if r0 represents a failure variant then r1 is an
            // error code.
            CommandReturn::new(r0.as_u32().into(), r1.as_u32(), r2.as_u32(), r3.as_u32())
        }
    }

    // -------------------------------------------------------------------------
    // Exit
    // -------------------------------------------------------------------------

    fn exit_terminate(exit_code: u32) -> ! {
        unsafe {
            // syscall2's documentation indicates it can be used to call Exit.
            // The exit system call cannot trigger undefined behavior on its
            // own.
            Self::syscall2::<{ syscall_class::EXIT }>([
                exit_id::TERMINATE.into(),
                exit_code.into(),
            ]);
            // TRD104 indicates that exit-terminate MUST always succeed and so
            // never return.
            core::hint::unreachable_unchecked()
        }
    }

    fn exit_restart(exit_code: u32) -> ! {
        unsafe {
            // syscall2's documentation indicates it can be used to call Exit.
            // The exit system call cannot trigger undefined behavior on its
            // own.
            Self::syscall2::<{ syscall_class::EXIT }>([exit_id::RESTART.into(), exit_code.into()]);
            // TRD104 indicates that exit-restart MUST always succeed and so
            // never return.
            core::hint::unreachable_unchecked()
        }
    }
}
<commit_msg>More code review tweaks:<commit_after>//! Implements `Syscalls` for all types that implement `RawSyscalls`.

use crate::{
    exit_id, exit_on_drop, return_variant, subscribe, syscall_class, yield_id, CommandReturn,
    ErrorCode, RawSyscalls, Register, ReturnVariant, Subscribe, Syscalls, Upcall,
    YieldNoWaitReturn,
};

impl<S: RawSyscalls> Syscalls for S {
    // -------------------------------------------------------------------------
    // Yield
    // -------------------------------------------------------------------------

    fn yield_no_wait() -> YieldNoWaitReturn {
        let mut flag = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();

        unsafe {
            // Flag can be uninitialized here because the kernel promises to
            // only write to it, not read from it. MaybeUninit guarantees that
            // it is safe to write a YieldNoWaitReturn into it.
            Self::yield2([yield_id::NO_WAIT.into(), flag.as_mut_ptr().into()]);

            // yield-no-wait guarantees it sets (initializes) flag before
            // returning.
            flag.assume_init()
        }
    }

    fn yield_wait() {
        // Safety: yield-wait does not return a value, which satisfies yield1's
        // requirement. The yield-wait system call cannot trigger undefined
        // behavior on its own in any other way.
        unsafe {
            Self::yield1([yield_id::WAIT.into()]);
        }
    }

    // -------------------------------------------------------------------------
    // Subscribe
    // -------------------------------------------------------------------------

    fn subscribe<
        'scope,
        IDS: subscribe::SupportsId<DRIVER_NUM, SUBSCRIBE_NUM>,
        U: Upcall<IDS>,
        CONFIG: subscribe::Config,
        const DRIVER_NUM: u32,
        const SUBSCRIBE_NUM: u32,
    >(
        _subscribe: &Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM>,
        upcall: &'scope U,
    ) -> Result<(), ErrorCode> {
        // The upcall function passed to the Tock kernel.
        //
        // Safety: data must be a reference to a valid instance of U.
        unsafe extern "C" fn kernel_upcall<S: Syscalls, IDS, U: Upcall<IDS>>(
            arg0: u32,
            arg1: u32,
            arg2: u32,
            data: Register,
        ) {
            let exit: exit_on_drop::ExitOnDrop<S> = Default::default();
            let upcall: *const U = data.into();
            unsafe { &*upcall }.upcall(arg0, arg1, arg2);
            core::mem::forget(exit);
        }

        // Inner function that does the majority of the work. This is not
        // monomorphized over DRIVER_NUM and SUBSCRIBE_NUM to keep code size
        // small.
        //
        // Safety: upcall_fcn must be kernel_upcall<S, IDS, U> and upcall_data
        // must be a reference to an instance of U that will remain valid as
        // long as the 'scope lifetime is alive. Can only be called if a
        // Subscribe<'scope, S, driver_num, subscribe_num> exists.
        unsafe fn inner<S: Syscalls, CONFIG: subscribe::Config>(
            driver_num: u32,
            subscribe_num: u32,
            upcall_fcn: Register,
            upcall_data: Register,
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Subscribe. These arguments follow TRD104. kernel_upcall has the
            // required signature. This function's preconditions mean that
            // upcall is a reference to an instance of U that will remain valid
            // until the 'scope lifetime is alive The existence of the
            // Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM> guarantees
            // that if this Subscribe succeeds then the upcall will be cleaned
            // up before the 'scope lifetime ends, guaranteeing that upcall is
            // still alive when kernel_upcall is invoked.
            let [r0, r1, _, _] = unsafe {
                S::syscall4::<{ syscall_class::SUBSCRIBE }>([
                    driver_num.into(),
                    subscribe_num.into(),
                    upcall_fcn,
                    upcall_data,
                ])
            };

            let return_variant: ReturnVariant = r0.as_u32().into();
            // TRD 104 guarantees that Subscribe returns either Success with 2
            // U32 or Failure with 2 U32. We check the return variant by
            // comparing against Failure with 2 U32 for 2 reasons:
            //
            //   1. On RISC-V with compressed instructions, it generates smaller
            //      code. FAILURE_2_U32 has value 2, which can be loaded into a
            //      register with a single compressed instruction, whereas
            //      loading SUCCESS_2_U32 uses an uncompressed instruction.
            //   2. In the event the kernel malfuctions and returns a different
            //      return variant, the success path is actually safer than the
            //      failure path. The failure path assumes that r1 contains an
            //      ErrorCode, and produces UB if it has an out of range value.
            //      Incorrectly assuming the call succeeded will not generate
            //      unsoundness, and will likely lead to the application
            //      hanging.
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
            }

            // r0 indicates Success with 2 u32s. Confirm the null upcall was
            // returned, and it if wasn't then call the configured function.
            // We're relying on the optimizer to remove this branch if
            // returned_nonnull_upcall is a no-op.
            // Note: TRD 104 specifies that the null upcall has address 0,
            // not necessarily a null pointer.
            let returned_upcall: usize = r1.into();
            if returned_upcall != 0usize {
                CONFIG::returned_nonnull_upcall(driver_num, subscribe_num);
            }
            Ok(())
        }

        let upcall_fcn = (kernel_upcall::<S, IDS, U> as usize).into();
        let upcall_data = (upcall as *const U).into();
        // Safety: upcall's type guarantees it is a reference to a U that will
        // remain valid for at least the 'scope lifetime. _subscribe is a
        // reference to a Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM>,
        // proving one exists. upcall_fcn and upcall_data are derived in ways
        // that satisfy inner's requirements.
        unsafe { inner::<Self, CONFIG>(DRIVER_NUM, SUBSCRIBE_NUM, upcall_fcn, upcall_data) }
    }

    fn unsubscribe(driver_num: u32, subscribe_num: u32) {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Subscribe. The upcall pointer passed is the null upcall, which
            // cannot cause undefined behavior on its own.
            Self::syscall4::<{ syscall_class::SUBSCRIBE }>([
                driver_num.into(),
                subscribe_num.into(),
                0usize.into(),
                0usize.into(),
            ]);
        }
    }

    // -------------------------------------------------------------------------
    // Command
    // -------------------------------------------------------------------------

    fn command(driver_id: u32, command_id: u32, argument0: u32, argument1: u32) -> CommandReturn {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Command. The Command system call cannot trigger undefined
            // behavior on its own.
            let [r0, r1, r2, r3] = Self::syscall4::<{ syscall_class::COMMAND }>([
                driver_id.into(),
                command_id.into(),
                argument0.into(),
                argument1.into(),
            ]);

            // Because r0 and r1 are returned directly from the kernel, we are
            // guaranteed that if r0 represents a failure variant then r1 is an
            // error code.
            CommandReturn::new(r0.as_u32().into(), r1.as_u32(), r2.as_u32(), r3.as_u32())
        }
    }

    // -------------------------------------------------------------------------
    // Exit
    // -------------------------------------------------------------------------

    fn exit_terminate(exit_code: u32) -> ! {
        unsafe {
            // syscall2's documentation indicates it can be used to call Exit.
            // The exit system call cannot trigger undefined behavior on its
            // own.
            Self::syscall2::<{ syscall_class::EXIT }>([
                exit_id::TERMINATE.into(),
                exit_code.into(),
            ]);
            // TRD104 indicates that exit-terminate MUST always succeed and so
            // never return.
            core::hint::unreachable_unchecked()
        }
    }

    fn exit_restart(exit_code: u32) -> ! {
        unsafe {
            // syscall2's documentation indicates it can be used to call Exit.
            // The exit system call cannot trigger undefined behavior on its
            // own.
            Self::syscall2::<{ syscall_class::EXIT }>([exit_id::RESTART.into(), exit_code.into()]);
            // TRD104 indicates that exit-restart MUST always succeed and so
            // never return.
            core::hint::unreachable_unchecked()
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::{SeedableRng, FromEntropy, Rng, rngs::SmallRng};

#[test]
fn simple() {
    assert_eq!(4, 4);
}

// Having more than 1 test does seem to make a difference
// (i.e., this calls ptr::swap which having just one test does not).
#[test]
fn fixed_rng() {
    let mut rng = rand::rngs::StdRng::seed_from_u64(0xdeadcafe);
    let x: u32 = rng.gen();
    let y: u32 = rng.gen();
    assert_ne!(x, y);
}

#[test]
#[cfg(not(target_os="macos"))] // FIXME entropy does not work on macOS
fn entropy_rng() {
    // Use this opportunity to test querying the RNG (needs an external crate, hence tested here and not in the compiletest suite)
    let mut rng = SmallRng::from_entropy();
    let _val = rng.gen::<i32>();

    // Also try per-thread RNG.
    let mut rng = rand::thread_rng();
    let _val = rng.gen::<i32>();
}

// A test that won't work on miri
#[cfg(not(miri))]
#[test]
fn does_not_work_on_miri() {
    let x = 0u8;
    assert!(&x as *const _ as usize % 4 < 4);
}
<commit_msg>fix tests on macOS<commit_after>#![allow(unused_imports)] // FIXME for macOS

extern crate rand;

use rand::{SeedableRng, FromEntropy, Rng, rngs::SmallRng};

#[test]
fn simple() {
    assert_eq!(4, 4);
}

// Having more than 1 test does seem to make a difference
// (i.e., this calls ptr::swap which having just one test does not).
#[test]
fn fixed_rng() {
    let mut rng = rand::rngs::StdRng::seed_from_u64(0xdeadcafe);
    let x: u32 = rng.gen();
    let y: u32 = rng.gen();
    assert_ne!(x, y);
}

#[test]
#[cfg(not(target_os="macos"))] // FIXME entropy does not work on macOS
fn entropy_rng() {
    // Use this opportunity to test querying the RNG (needs an external crate, hence tested here and not in the compiletest suite)
    let mut rng = SmallRng::from_entropy();
    let _val = rng.gen::<i32>();

    // Also try per-thread RNG.
    let mut rng = rand::thread_rng();
    let _val = rng.gen::<i32>();
}

// A test that won't work on miri
#[cfg(not(miri))]
#[test]
fn does_not_work_on_miri() {
    let x = 0u8;
    assert!(&x as *const _ as usize % 4 < 4);
}
<|endoftext|>


<commit_before>use rand::{rngs::SmallRng, Rng, SeedableRng};

// Having more than 1 test does seem to make a difference
// (i.e., this calls ptr::swap which having just one test does not).
#[test]
fn simple1() {
    assert_eq!(4, 4);
}

#[test]
fn simple2() {
    assert_ne!(42, 24);
}

// A test that won't work on miri (tests disabling tests).
#[test]
#[cfg_attr(miri, ignore)]
fn does_not_work_on_miri() {
    let x = 0u8;
    assert!(&x as *const _ as usize % 4 < 4);
}

// We also use this to test some external crates, that we cannot depend on in the compiletest suite.

#[test]
fn entropy_rng() {
    // Test `getrandom` directly (in multiple different versions).
    let mut data = vec![0; 16];
    getrandom_1::getrandom(&mut data).unwrap();
    getrandom_2::getrandom(&mut data).unwrap();

    // Try seeding with "real" entropy.
    let mut rng = SmallRng::from_entropy();
    let _val = rng.gen::<i32>();
    let _val = rng.gen::<isize>();
    let _val = rng.gen::<i128>();

    // Also try per-thread RNG.
    let mut rng = rand::thread_rng();
    let _val = rng.gen::<i32>();
    let _val = rng.gen::<isize>();
    let _val = rng.gen::<i128>();
}

#[test]
fn cargo_env() {
    assert_eq!(env!("CARGO_PKG_NAME"), "cargo-miri-test");
    env!("CARGO_BIN_EXE_cargo-miri-test"); // Asserts that this exists.
}

#[test]
#[should_panic(expected = "Explicit panic")]
fn do_panic() // In large, friendly letters :)
{
    panic!("Explicit panic from test!");
}

#[test]
#[allow(unconditional_panic)]
#[should_panic(expected = "the len is 0 but the index is 42")]
fn fail_index_check() {
    [][42]
}

#[test]
fn page_size() {
    let page_size = page_size::get();

    // In particular, this checks that it is not 0.
    assert!(
        page_size.next_power_of_two() == page_size,
        "page size not a power of two: {}",
        page_size
    );
}
<commit_msg>Auto merge of #2168 - RalfJung:power, r=RalfJung<commit_after>use rand::{rngs::SmallRng, Rng, SeedableRng};

// Having more than 1 test does seem to make a difference
// (i.e., this calls ptr::swap which having just one test does not).
#[test]
fn simple1() {
    assert_eq!(4, 4);
}

#[test]
fn simple2() {
    assert_ne!(42, 24);
}

// A test that won't work on miri (tests disabling tests).
#[test]
#[cfg_attr(miri, ignore)]
fn does_not_work_on_miri() {
    let x = 0u8;
    assert!(&x as *const _ as usize % 4 < 4);
}

// We also use this to test some external crates, that we cannot depend on in the compiletest suite.

#[test]
fn entropy_rng() {
    // Test `getrandom` directly (in multiple different versions).
    let mut data = vec![0; 16];
    getrandom_1::getrandom(&mut data).unwrap();
    getrandom_2::getrandom(&mut data).unwrap();

    // Try seeding with "real" entropy.
    let mut rng = SmallRng::from_entropy();
    let _val = rng.gen::<i32>();
    let _val = rng.gen::<isize>();
    let _val = rng.gen::<i128>();

    // Also try per-thread RNG.
    let mut rng = rand::thread_rng();
    let _val = rng.gen::<i32>();
    let _val = rng.gen::<isize>();
    let _val = rng.gen::<i128>();
}

#[test]
fn cargo_env() {
    assert_eq!(env!("CARGO_PKG_NAME"), "cargo-miri-test");
    env!("CARGO_BIN_EXE_cargo-miri-test"); // Asserts that this exists.
}

#[test]
#[should_panic(expected = "Explicit panic")]
fn do_panic() // In large, friendly letters :)
{
    panic!("Explicit panic from test!");
}

#[test]
#[allow(unconditional_panic)]
#[should_panic(expected = "the len is 0 but the index is 42")]
fn fail_index_check() {
    [][42]
}

#[test]
fn page_size() {
    let page_size = page_size::get();

    // In particular, this checks that it is not 0.
    assert!(
        page_size.is_power_of_two(),
        "page size not a power of two: {}",
        page_size
    );
}
<|endoftext|>