<commit_before>extern crate dbus;
use self::dbus::{NameFlag, ReleaseNameReply};

use super::connection::DBusConnection;
use super::error::DBusError;
use super::interface::DBusInterfaceMap;
use super::message::{DBusMessage, DBusMessageType};
use super::object::DBusObject;
use super::target::DBusTarget;

use std::collections::btree_map::{BTreeMap, Entry};

pub type DBusSignalHandler = Box<FnMut(&DBusConnection, &DBusTarget) -> ()>;
type DBusSignalHandlers = Vec<DBusSignalHandler>;
type DBusSignalHandlerMap = BTreeMap<DBusTarget, DBusSignalHandlers>;

fn _add_handler(handlers: &mut DBusSignalHandlerMap, signal: DBusTarget, handler: DBusSignalHandler) {
    match handlers.entry(signal) {
        Entry::Vacant(v)    => { v.insert(vec![handler]); },
        Entry::Occupied(o)  => o.into_mut().push(handler),
    };
}

pub struct DBusServer<'a> {
    conn: &'a DBusConnection,
    name: String,

    objects: BTreeMap<String, DBusObject<'a>>,
    signals: DBusSignalHandlerMap,
    namespace_signals: DBusSignalHandlerMap,
}

impl<'a> DBusServer<'a> {
    pub fn new(conn: &'a DBusConnection, name: &str) -> Result<DBusServer<'a>, DBusError> {
        try!(conn.register_name(name, NameFlag::DoNotQueue as u32));

        Ok(DBusServer {
            conn: conn,
            name: name.to_owned(),

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
            namespace_signals: BTreeMap::new(),
        })
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn add_object(&mut self, path: &str, iface_map: DBusInterfaceMap<'a>) -> Result<&mut Self, DBusError> {
        // XXX: Use `.map` when type resolution works better. Currently, `.map` causes the caller
        // type to be set in stone due to eager type resolution and no fluidity in setting it. This
        // causes the type to be too concrete on the caller side which then fails to map to the end
        // result type of `.map` even though `.map` is "transparent" to the error type.
        Result::map(match self.objects.entry(path.to_owned()) {
            Entry::Vacant(v)    => {
                let obj = try!(DBusObject::new(self.conn, path, iface_map));

                v.insert(obj);

                Ok(())
            },
            Entry::Occupied(_)  => Err(DBusError::PathAlreadyRegistered(path.to_owned())),
        }, |_| self)
    }

    pub fn remove_object(&mut self, path: &str) -> Result<&mut Self, DBusError> {
        match self.objects.remove(path) {
            Some(_) => Ok(self),
            None    => Err(DBusError::NoSuchPath(path.to_owned())),
        }
    }

    pub fn connect(&mut self, signal: DBusTarget, callback: DBusSignalHandler) -> Result<&mut Self, DBusError> {
        try!(self.conn.add_match(&format!("type='signal',interface='{}',path='{}',member='{}'",
                                          signal.interface,
                                          signal.object,
                                          signal.method)));

        _add_handler(&mut self.signals, signal, callback);

        Ok(self)
    }

    pub fn connect_namespace(&mut self, signal: DBusTarget, callback: DBusSignalHandler) -> Result<&mut Self, DBusError> {
        try!(self.conn.add_match(&format!("type='signal',interface='{}',path_namespace='{}',member='{}'",
                                          signal.interface,
                                          signal.object,
                                          signal.method)));

        _add_handler(&mut self.namespace_signals, signal, callback);

        Ok(self)
    }

    pub fn handle_message<'b>(&mut self, m: &'b mut DBusMessage) -> Option<&'b mut DBusMessage> {
        match m.msg_type() {
            DBusMessageType::Signal     => Some(self._match_signal(m)),
            DBusMessageType::MethodCall => self._call_method(m),
            _                           => Some(m),
        }
    }

    fn _call_method<'b>(&mut self, m: &'b mut DBusMessage) -> Option<&'b mut DBusMessage> {
        self.objects.iter_mut().fold(Some(m), |opt_m, (_, object)| {
            opt_m.and_then(|mut m| {
                match object.handle_message(&mut m) {
                    None          => Some(m),
                    Some(Ok(()))  => None,
                    Some(Err(())) => {
                        println!("failed to send a reply for {:?}", m);
                        None
                    },
                }
            })
        })
    }

    fn _match_signal<'b>(&mut self, m: &'b mut DBusMessage) -> &'b mut DBusMessage {
        let conn = (&self.conn).clone();

        DBusTarget::extract(m).map(|signal| {
            self.signals.get_mut(&signal).map(|handlers| {
                handlers.iter_mut().map(|f| {
                    f(conn, &signal);
                })
            });

            self.namespace_signals.iter_mut().filter(|&(expect, _)| {
                expect.namespace_eq(&signal)
            }).map(|(_, handlers)| {
                handlers.iter_mut().map(|f| {
                    f(conn, &signal);
                })
            }).collect::<Vec<_>>();
        });

        m
    }
}

impl<'a> Drop for DBusServer<'a> {
    fn drop(&mut self) {
        let res = self.conn.release_name(&self.name);
        match res {
            Ok(reply) =>
                match reply {
                    ReleaseNameReply::Released    => (),
                    ReleaseNameReply::NonExistent => panic!("internal error: non-existent name {}?!", self.name),
                    ReleaseNameReply::NotOwner    => panic!("internal error: not the owner of {}?!", self.name),
                },
            Err(err) => println!("failed to release {}: {:?}: {:?}", self.name, err.name(), err.message()),
        }
    }
}
<commit_msg>server: simplify add_object<commit_after>extern crate dbus;
use self::dbus::{NameFlag, ReleaseNameReply};

use super::connection::DBusConnection;
use super::error::DBusError;
use super::interface::DBusInterfaceMap;
use super::message::{DBusMessage, DBusMessageType};
use super::object::DBusObject;
use super::target::DBusTarget;

use std::collections::btree_map::{BTreeMap, Entry};

pub type DBusSignalHandler = Box<FnMut(&DBusConnection, &DBusTarget) -> ()>;
type DBusSignalHandlers = Vec<DBusSignalHandler>;
type DBusSignalHandlerMap = BTreeMap<DBusTarget, DBusSignalHandlers>;

fn _add_handler(handlers: &mut DBusSignalHandlerMap, signal: DBusTarget, handler: DBusSignalHandler) {
    match handlers.entry(signal) {
        Entry::Vacant(v)    => { v.insert(vec![handler]); },
        Entry::Occupied(o)  => o.into_mut().push(handler),
    };
}

pub struct DBusServer<'a> {
    conn: &'a DBusConnection,
    name: String,

    objects: BTreeMap<String, DBusObject<'a>>,
    signals: DBusSignalHandlerMap,
    namespace_signals: DBusSignalHandlerMap,
}

impl<'a> DBusServer<'a> {
    pub fn new(conn: &'a DBusConnection, name: &str) -> Result<DBusServer<'a>, DBusError> {
        try!(conn.register_name(name, NameFlag::DoNotQueue as u32));

        Ok(DBusServer {
            conn: conn,
            name: name.to_owned(),

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
            namespace_signals: BTreeMap::new(),
        })
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn add_object(&mut self, path: &str, iface_map: DBusInterfaceMap<'a>) -> Result<&mut Self, DBusError> {
        match self.objects.entry(path.to_owned()) {
            Entry::Vacant(v)    => {
                let obj = try!(DBusObject::new(self.conn, path, iface_map));

                v.insert(obj);

                Ok(())
            },
            Entry::Occupied(_)  => Err(DBusError::PathAlreadyRegistered(path.to_owned())),
        }.map(|_| self)
    }

    pub fn remove_object(&mut self, path: &str) -> Result<&mut Self, DBusError> {
        match self.objects.remove(path) {
            Some(_) => Ok(self),
            None    => Err(DBusError::NoSuchPath(path.to_owned())),
        }
    }

    pub fn connect(&mut self, signal: DBusTarget, callback: DBusSignalHandler) -> Result<&mut Self, DBusError> {
        try!(self.conn.add_match(&format!("type='signal',interface='{}',path='{}',member='{}'",
                                          signal.interface,
                                          signal.object,
                                          signal.method)));

        _add_handler(&mut self.signals, signal, callback);

        Ok(self)
    }

    pub fn connect_namespace(&mut self, signal: DBusTarget, callback: DBusSignalHandler) -> Result<&mut Self, DBusError> {
        try!(self.conn.add_match(&format!("type='signal',interface='{}',path_namespace='{}',member='{}'",
                                          signal.interface,
                                          signal.object,
                                          signal.method)));

        _add_handler(&mut self.namespace_signals, signal, callback);

        Ok(self)
    }

    pub fn handle_message<'b>(&mut self, m: &'b mut DBusMessage) -> Option<&'b mut DBusMessage> {
        match m.msg_type() {
            DBusMessageType::Signal     => Some(self._match_signal(m)),
            DBusMessageType::MethodCall => self._call_method(m),
            _                           => Some(m),
        }
    }

    fn _call_method<'b>(&mut self, m: &'b mut DBusMessage) -> Option<&'b mut DBusMessage> {
        self.objects.iter_mut().fold(Some(m), |opt_m, (_, object)| {
            opt_m.and_then(|mut m| {
                match object.handle_message(&mut m) {
                    None          => Some(m),
                    Some(Ok(()))  => None,
                    Some(Err(())) => {
                        println!("failed to send a reply for {:?}", m);
                        None
                    },
                }
            })
        })
    }

    fn _match_signal<'b>(&mut self, m: &'b mut DBusMessage) -> &'b mut DBusMessage {
        let conn = (&self.conn).clone();

        DBusTarget::extract(m).map(|signal| {
            self.signals.get_mut(&signal).map(|handlers| {
                handlers.iter_mut().map(|f| {
                    f(conn, &signal);
                })
            });

            self.namespace_signals.iter_mut().filter(|&(expect, _)| {
                expect.namespace_eq(&signal)
            }).map(|(_, handlers)| {
                handlers.iter_mut().map(|f| {
                    f(conn, &signal);
                })
            }).collect::<Vec<_>>();
        });

        m
    }
}

impl<'a> Drop for DBusServer<'a> {
    fn drop(&mut self) {
        let res = self.conn.release_name(&self.name);
        match res {
            Ok(reply) =>
                match reply {
                    ReleaseNameReply::Released    => (),
                    ReleaseNameReply::NonExistent => panic!("internal error: non-existent name {}?!", self.name),
                    ReleaseNameReply::NotOwner    => panic!("internal error: not the owner of {}?!", self.name),
                },
            Err(err) => println!("failed to release {}: {:?}: {:?}", self.name, err.name(), err.message()),
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::Deref;
use std::sync::RwLock;
use std::sync::mpsc::{channel, Receiver, Sender};
use {Future, Poll, Async};
use task::{self, Task};
use lock::Lock;

/// 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> 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<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()
    }
}

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

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

/// The data that has to be synced to implement `Shared`, in order to satisfy the `Future` trait's constraints.
struct SyncedInner<F>
    where F: Future
{
    original_future: F, // The original future
    result: Option<Result<Async<SharedItem<F::Item>>, SharedError<F::Error>>>, // The original future result wrapped with `SharedItem`/`SharedError`
    tasks_receiver: Lock<Receiver<Task>>, // When original future is polled and ready, unparks all the tasks in that channel
}

struct Inner<F>
    where F: Future
{
    synced_inner: RwLock<SyncedInner<F>>,
    tasks_unpark_started: AtomicBool,
}

/// TODO: doc
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F>
    where F: Future
{
    inner: Arc<Inner<F>>,
    tasks_sender: Sender<Task>,
}

pub fn new<F>(future: F) -> Shared<F>
    where F: Future
{
    let (tasks_sender, tasks_receiver) = channel();
    Shared {
        inner: Arc::new(Inner {
            synced_inner: RwLock::new(SyncedInner {
                original_future: future,
                result: None,
                tasks_receiver: Lock::new(tasks_receiver),
            }),
            tasks_unpark_started: AtomicBool::new(false),
        }),
        tasks_sender: tasks_sender,
    }
}

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> {
        let mut polled_result: Option<Result<Async<SharedItem<F::Item>>, SharedError<F::Error>>> =
            None;

        // If the result is ready, just return it
        match self.inner.synced_inner.try_read() {
            Ok(inner_guard) => {
                let ref inner = *inner_guard;
                if let Some(ref result) = inner.result {
                    return result.clone();
                }
            }
            _ => {} // Mutex is locked for write
        }

        // The result was not ready.
        match self.inner.synced_inner.try_write() {
            Ok(mut inner_guard) => {
                let ref mut inner = *inner_guard;

                // By the time that synced_inner was unlocked, other thread could poll the result,
                // so we check if result has a value
                if inner.result.is_some() {
                    polled_result = inner.result.clone();
                } else {
                    match inner.original_future.poll() {
                        Ok(Async::Ready(item)) => {
                            inner.result = Some(Ok(Async::Ready(SharedItem::new(item))));
                            polled_result = inner.result.clone();
                        }
                        Err(error) => {
                            inner.result = Some(Err(SharedError::new(error)));
                            polled_result = inner.result.clone();
                        }
                        Ok(Async::NotReady) => {} // Will be handled later
                    }
                }
            }
            Err(_) => {} // Will be handled later
        }

        if polled_result.is_some() {
            match self.inner.synced_inner.try_read() {
                Ok(inner_guard) => {
                    let ref inner = *inner_guard;
                    self.inner.tasks_unpark_started.store(true, Ordering::Relaxed);
                    match inner.tasks_receiver.try_lock() {
                        Some(tasks_receiver_guard) => {
                            let ref tasks_receiver = *tasks_receiver_guard;
                            loop {
                                match tasks_receiver.try_recv() {
                                    Ok(task) => task.unpark(),
                                    _ => break,
                                }
                            }
                        }
                        None => {} // Other thread is unparking the tasks
                    }

                    if let Some(ref result) = inner.result {
                        return result.clone();
                    } else {
                        unreachable!();
                    }
                }
                _ => {
                    // The mutex is locked for write, after the poll was ready.
                    // The context that locked for write will unpark the tasks.
                }
            }
        }

        let t = task::park();
        let _ = self.tasks_sender.send(t);
        if self.inner.tasks_unpark_started.load(Ordering::Relaxed) {
            // If the tasks unpark has started, synced_inner can be locked for read,
            // and its result has value (not None).
            // The result must be read here because it is possible that the task,
            // t (see variable above), had not been unparked.
            match self.inner.synced_inner.try_read() {
                Ok(inner_guard) => {
                    let ref inner = *inner_guard;
                    if let Some(ref result) = inner.result {
                        return result.clone();
                    }
                }
                _ => {
                    // The mutex is locked for write, so the sent task will be unparked later
                }
            }
        }

        Ok(Async::NotReady)
    }
}

impl<F> Clone for Shared<F>
    where F: Future
{
    fn clone(&self) -> Self {
        Shared {
            inner: self.inner.clone(),
            tasks_sender: self.tasks_sender.clone(),
        }
    }
}
<commit_msg>Some cr fixes<commit_after>use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::Deref;
use std::sync::RwLock;
use std::sync::mpsc::{channel, Receiver, Sender};
use {Future, Poll, Async};
use task::{self, Task};
use lock::Lock;

/// 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> 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<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()
    }
}

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

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

/// The data that has to be synced to implement `Shared`, in order to satisfy the `Future` trait's constraints.
struct SyncedInner<F>
    where F: Future
{
    original_future: F, // The original future
    result: Option<Result<Async<SharedItem<F::Item>>, SharedError<F::Error>>>, // The original future result wrapped with `SharedItem`/`SharedError`
    tasks_receiver: Lock<Receiver<Task>>, // When original future is polled and ready, unparks all the tasks in that channel
}

struct Inner<F>
    where F: Future
{
    synced_inner: RwLock<SyncedInner<F>>,
    tasks_unpark_started: AtomicBool,
}

/// TODO: doc
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F>
    where F: Future
{
    inner: Arc<Inner<F>>,
    tasks_sender: Sender<Task>,
}

pub fn new<F>(future: F) -> Shared<F>
    where F: Future
{
    let (tasks_sender, tasks_receiver) = channel();
    Shared {
        inner: Arc::new(Inner {
            synced_inner: RwLock::new(SyncedInner {
                original_future: future,
                result: None,
                tasks_receiver: Lock::new(tasks_receiver),
            }),
            tasks_unpark_started: AtomicBool::new(false),
        }),
        tasks_sender: tasks_sender,
    }
}

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> {
        let mut polled_result: Option<Result<Async<SharedItem<F::Item>>, SharedError<F::Error>>> =
            None;

        // If the result is ready, just return it
        match self.inner.synced_inner.try_read() {
            Ok(inner_guard) => {
                let ref inner = *inner_guard;
                if let Some(ref result) = inner.result {
                    return result.clone();
                }
            }
            _ => {} // Mutex is locked for write
        }

        // The result was not ready.
        match self.inner.synced_inner.try_write() {
            Ok(mut inner_guard) => {
                let ref mut inner = *inner_guard;

                // By the time that synced_inner was unlocked, other thread could poll the result,
                // so we check if result has a value
                if inner.result.is_some() {
                    polled_result = inner.result.clone();
                } else {
                    match inner.original_future.poll() {
                        Ok(Async::Ready(item)) => {
                            inner.result = Some(Ok(Async::Ready(SharedItem::new(item))));
                            polled_result = inner.result.clone();
                        }
                        Err(error) => {
                            inner.result = Some(Err(SharedError::new(error)));
                            polled_result = inner.result.clone();
                        }
                        Ok(Async::NotReady) => {} // Will be handled later
                    }
                }
            }
            Err(_) => {} // Will be handled later
        }

        if let Some(result) = polled_result {
            match self.inner.synced_inner.try_read() {
                Ok(inner_guard) => {
                    let ref inner = *inner_guard;
                    self.inner.tasks_unpark_started.store(true, Ordering::Relaxed);
                    match inner.tasks_receiver.try_lock() {
                        Some(tasks_receiver_guard) => {
                            let ref tasks_receiver = *tasks_receiver_guard;
                            loop {
                                match tasks_receiver.try_recv() {
                                    Ok(task) => task.unpark(),
                                    _ => break,
                                }
                            }
                        }
                        None => {} // Other thread is unparking the tasks
                    }

                    return result.clone();
                }
                _ => {
                    // The mutex is locked for write, after the poll was ready.
                    // The context that locked for write will unpark the tasks.
                }
            }
        }

        let t = task::park();
        let _ = self.tasks_sender.send(t);
        if self.inner.tasks_unpark_started.load(Ordering::Relaxed) {
            // If the tasks unpark has started, synced_inner can be locked for read,
            // and its result has value (not None).
            // The result must be read here because it is possible that the task,
            // t (see variable above), had not been unparked.
            match self.inner.synced_inner.try_read() {
                Ok(inner_guard) => {
                    let ref inner = *inner_guard;
                    return inner.result.as_ref().unwrap().clone();
                }
                _ => {
                    // The mutex is locked for write, so the sent task will be unparked later
                }
            }
        }

        Ok(Async::NotReady)
    }
}

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


<commit_before>use iron::Middleware;
use std::sync::Arc;

pub struct Shared {
    pub middleware: Arc<Box<Middleware + Send + Share>>
}

// Needed to hack name resolution in our Clone impl
fn clone<T: Clone>(t: &T) -> T { t.clone() }

impl Clone for Shared {
    fn clone(&self) -> Shared {
        Shared {
            middleware: clone(&self.middleware)
        }
    }
}

<commit_msg>(feat) Switched to using ShareableMiddleware.<commit_after>use iron::{Middleware, Request, Response, Alloy};
use iron::middleware::Status;
use std::sync::Arc;

pub trait ShareableMiddleware {
    fn shared_enter(&self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status;
    fn shared_exit(&self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status;
}

pub struct Shared {
    pub middleware: Arc<Box<ShareableMiddleware + Send + Share>>
}

// Needed to hack name resolution in our Clone impl
fn clone<T: Clone>(t: &T) -> T { t.clone() }

impl Clone for Shared {
    fn clone(&self) -> Shared {
        Shared {
            middleware: clone(&self.middleware)
        }
    }
}

impl Middleware for Shared {
    fn enter(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        self.middleware.shared_enter(req, res, alloy)
    }

    fn exit(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        self.middleware.shared_exit(req, res, alloy)
    }
}

<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

#[deny(string_add)]
#[allow(string_add_assign)]
fn add_only() { // ignores assignment distinction
	let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you add something to a string.
    }

    let y = "".to_owned();
    let z = y + "..."; //~ERROR you add something to a string.

    assert_eq!(&x, &z);
}

#[deny(string_add_assign)]
fn add_assign_only() {
	let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you assign the result of adding something to this string.
    }

    let y = "".to_owned();
    let z = y + "...";

    assert_eq!(&x, &z);
}

#[deny(string_add, string_add_assign)]
fn both() {
    let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you assign the result of adding something to this string.
    }

    let y = "".to_owned();
    let z = y + "..."; //~ERROR you add something to a string.

    assert_eq!(&x, &z);
}

fn main() {
	add_only();
	add_assign_only();
	both();

	// the add is only caught for String
	let mut x = 1;
	x = x + 1;
	assert_eq!(2, x);
}
<commit_msg>fixed error messages in compile-fail test<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#[deny(string_add)]
#[allow(string_add_assign)]
fn add_only() { // ignores assignment distinction
	let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you added something to a string.
    }

    let y = "".to_owned();
    let z = y + "..."; //~ERROR you added something to a string.

    assert_eq!(&x, &z);
}

#[deny(string_add_assign)]
fn add_assign_only() {
	let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you assigned the result of adding something to this string.
    }

    let y = "".to_owned();
    let z = y + "...";

    assert_eq!(&x, &z);
}

#[deny(string_add, string_add_assign)]
fn both() {
    let mut x = "".to_owned();

    for _ in (1..3) {
        x = x + "."; //~ERROR you assigned the result of adding something to this string.
    }

    let y = "".to_owned();
    let z = y + "..."; //~ERROR you added something to a string.

    assert_eq!(&x, &z);
}

fn main() {
	add_only();
	add_assign_only();
	both();

	// the add is only caught for String
	let mut x = 1;
	x = x + 1;
	assert_eq!(2, x);
}
<|endoftext|>


<commit_before>//! Tests for configuration values that point to programs.

use cargo_test_support::{basic_lib_manifest, project, rustc_host, rustc_host_env};

#[cargo_test]
fn pathless_tools() {
    let target = rustc_host();

    let foo = project()
        .file("Cargo.toml", &basic_lib_manifest("foo"))
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.{}]
                    linker = "nonexistent-linker"
                "#,
                target
            ),
        )
        .build();

    foo.cargo("build --verbose")
        .with_stderr(
            "\
[COMPILING] foo v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C linker=nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn absolute_tools() {
    let target = rustc_host();

    // Escaped as they appear within a TOML config file
    let linker = if cfg!(windows) {
        r#"C:\\bogus\\nonexistent-linker"#
    } else {
        r#"/bogus/nonexistent-linker"#
    };

    let foo = project()
        .file("Cargo.toml", &basic_lib_manifest("foo"))
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.{target}]
                    linker = "{linker}"
                "#,
                target = target,
                linker = linker
            ),
        )
        .build();

    foo.cargo("build --verbose")
        .with_stderr(
            "\
[COMPILING] foo v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C linker=[..]bogus/nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn relative_tools() {
    let target = rustc_host();

    // Escaped as they appear within a TOML config file
    let linker = if cfg!(windows) {
        r#".\\tools\\nonexistent-linker"#
    } else {
        r#"./tools/nonexistent-linker"#
    };

    // Funky directory structure to test that relative tool paths are made absolute
    // by reference to the `.cargo/..` directory and not to (for example) the CWD.
    let p = project()
        .no_manifest()
        .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
        .file("bar/src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.{target}]
                    linker = "{linker}"
                "#,
                target = target,
                linker = linker
            ),
        )
        .build();

    let prefix = p.root().into_os_string().into_string().unwrap();

    p.cargo("build --verbose")
        .cwd("bar")
        .with_stderr(&format!(
            "\
[COMPILING] bar v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C linker={prefix}/./tools/nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
            prefix = prefix,
        ))
        .run();
}

#[cargo_test]
fn custom_runner() {
    let target = rustc_host();

    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file("tests/test.rs", "")
        .file("benches/bench.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.{}]
                    runner = "nonexistent-runner -r"
                "#,
                target
            ),
        )
        .build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )
        .run();

    p.cargo("test --test test --verbose -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]`
[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r [..]/target/debug/deps/test-[..][EXE] --param`
",
        )
        .run();

    p.cargo("bench --bench bench --verbose -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]`
[RUNNING] `rustc [..]`
[FINISHED] bench [optimized] target(s) in [..]
[RUNNING] `nonexistent-runner -r [..]/target/release/deps/bench-[..][EXE] --param --bench`
",
        )
        .run();
}

// can set a custom runner via `target.'cfg(..)'.runner`
#[cargo_test]
fn custom_runner_cfg() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
            [target.'cfg(not(target_os = "none"))']
            runner = "nonexistent-runner -r"
            "#,
        )
        .build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )
        .run();
}

// custom runner set via `target.$triple.runner` have precedence over `target.'cfg(..)'.runner`
#[cargo_test]
fn custom_runner_cfg_precedence() {
    let target = rustc_host();

    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.'cfg(not(target_os = "none"))']
                    runner = "ignored-runner"

                    [target.{}]
                    runner = "nonexistent-runner -r"
                "#,
                target
            ),
        )
        .build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )
        .run();
}

#[cargo_test]
fn custom_runner_cfg_collision() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
            [target.'cfg(not(target_arch = "avr"))']
            runner = "true"

            [target.'cfg(not(target_os = "none"))']
            runner = "false"
            "#,
        )
        .build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr(
            "\
[ERROR] several matching instances of `target.'cfg(..)'.runner` in `.cargo/config`
first match `cfg(not(target_arch = \"avr\"))` located in [..]/foo/.cargo/config
second match `cfg(not(target_os = \"none\"))` located in [..]/foo/.cargo/config
",
        )
        .run();
}

#[cargo_test]
fn custom_runner_env() {
    let p = project().file("src/main.rs", "fn main() {}").build();

    let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env());

    p.cargo("run")
        .env(&key, "nonexistent-runner --foo")
        .with_status(101)
        // FIXME: Update "Caused by" error message once rust/pull/87704 is merged.
        // On Windows, changing to a custom executable resolver has changed the
        // error messages.
        .with_stderr(&format!(
            "\
[COMPILING] foo [..]
[FINISHED] dev [..]
[RUNNING] `nonexistent-runner --foo target/debug/foo[EXE]`
[ERROR] could not execute process `nonexistent-runner --foo target/debug/foo[EXE]` (never executed)

Caused by:
  [..]
"
        ))
        .run();
}

#[cargo_test]
fn custom_runner_env_overrides_config() {
    let target = rustc_host();
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            &format!(
                r#"
                    [target.{}]
                    runner = "should-not-run -r"
                "#,
                target
            ),
        )
        .build();

    let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env());

    p.cargo("run")
        .env(&key, "should-run --foo")
        .with_status(101)
        .with_stderr_contains("[RUNNING] `should-run --foo target/debug/foo[EXE]`")
        .run();
}

#[cargo_test]
#[cfg(unix)] // Assumes `true` is in PATH.
fn custom_runner_env_true() {
    // Check for a bug where "true" was interpreted as a boolean instead of
    // the executable.
    let p = project().file("src/main.rs", "fn main() {}").build();

    let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env());

    p.cargo("run")
        .env(&key, "true")
        .with_stderr_contains("[RUNNING] `true target/debug/foo[EXE]`")
        .run();
}

#[cargo_test]
fn custom_linker_env() {
    let p = project().file("src/main.rs", "fn main() {}").build();

    let key = format!("CARGO_TARGET_{}_LINKER", rustc_host_env());

    p.cargo("build -v")
        .env(&key, "nonexistent-linker")
        .with_status(101)
        .with_stderr_contains("[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]")
        .run();
}

#[cargo_test]
fn target_in_environment_contains_lower_case() {
    let p = project().file("src/main.rs", "fn main() {}").build();

    let target = rustc_host();
    let env_key = format!(
        "CARGO_TARGET_{}_LINKER",
        target.to_lowercase().replace('-', "_")
    );

    p.cargo("build -v --target")
        .arg(target)
        .env(&env_key, "nonexistent-linker")
        .with_stderr_contains(format!(
            "warning: Environment variables are expected to use uppercase \
             letters and underscores, the variable `{}` will be ignored and \
             have no effect",
            env_key
        ))
        .run();
}

#[cargo_test]
fn cfg_ignored_fields() {
    // Test for some ignored fields in [target.'cfg()'] tables.
    let p = project()
        .file(
            ".cargo/config",
            r#"
            # Try some empty tables.
            [target.'cfg(not(foo))']
            [target.'cfg(not(bar))'.somelib]

            # A bunch of unused fields.
            [target.'cfg(not(target_os = "none"))']
            linker = 'false'
            ar = 'false'
            foo = {rustc-flags = "-l foo"}
            invalid = 1
            runner = 'false'
            rustflags = ''
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("check")
        .with_stderr(
            "\
[WARNING] unused key `somelib` in [target] config table `cfg(not(bar))`
[WARNING] unused key `ar` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `foo` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `invalid` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `linker` in [target] config table `cfg(not(target_os = \"none\"))`
[CHECKING] foo v0.0.1 ([..])
[FINISHED] [..]
",
        )
        .run();
}
<commit_msg>Fix test<commit_after>//! Tests for configuration values that point to programs.

use cargo_test_support::{basic_lib_manifest, project, rustc_host, rustc_host_env};

#[cargo_test]
fn pathless_tools() {
    let target = rustc_host();

    let foo = project()
        .file("Cargo.toml", &basic_lib_manifest("foo"))
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.{}]
                    linker = "nonexistent-linker"
                "#,
                target
            ),
        )
        .build();

    foo.cargo("build --verbose")
        .with_stderr(
            "\
[COMPILING] foo v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C linker=nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn absolute_tools() {
    let target = rustc_host();

    // Escaped as they appear within a TOML config file
    let linker = if cfg!(windows) {
        r#"C:\\bogus\\nonexistent-linker"#
    } else {
        r#"/bogus/nonexistent-linker"#
    };

    let foo = project()
        .file("Cargo.toml", &basic_lib_manifest("foo"))
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.{target}]
                    linker = "{linker}"
                "#,
                target = target,
                linker = linker
            ),
        )
        .build();

    foo.cargo("build --verbose")
        .with_stderr(
            "\
[COMPILING] foo v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C linker=[..]bogus/nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn relative_tools() {
    let target = rustc_host();

    // Escaped as they appear within a TOML config file
    let linker = if cfg!(windows) {
        r#".\\tools\\nonexistent-linker"#
    } else {
        r#"./tools/nonexistent-linker"#
    };

    // Funky directory structure to test that relative tool paths are made absolute
    // by reference to the `.cargo/..` directory and not to (for example) the CWD.
    let p = project()
        .no_manifest()
        .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
        .file("bar/src/lib.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.{target}]
                    linker = "{linker}"
                "#,
                target = target,
                linker = linker
            ),
        )
        .build();

    let prefix = p.root().into_os_string().into_string().unwrap();

    p.cargo("build --verbose")
        .cwd("bar")
        .with_stderr(&format!(
            "\
[COMPILING] bar v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C linker={prefix}/./tools/nonexistent-linker [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
            prefix = prefix,
        ))
        .run();
}

#[cargo_test]
fn custom_runner() {
    let target = rustc_host();

    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file("tests/test.rs", "")
        .file("benches/bench.rs", "")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.{}]
                    runner = "nonexistent-runner -r"
                "#,
                target
            ),
        )
        .build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )
        .run();

    p.cargo("test --test test --verbose -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]`
[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r [..]/target/debug/deps/test-[..][EXE] --param`
",
        )
        .run();

    p.cargo("bench --bench bench --verbose -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]`
[RUNNING] `rustc [..]`
[FINISHED] bench [optimized] target(s) in [..]
[RUNNING] `nonexistent-runner -r [..]/target/release/deps/bench-[..][EXE] --param --bench`
",
        )
        .run();
}

// can set a custom runner via `target.'cfg(..)'.runner`
#[cargo_test]
fn custom_runner_cfg() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
            [target.'cfg(not(target_os = "none"))']
            runner = "nonexistent-runner -r"
            "#,
        )
        .build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )
        .run();
}

// custom runner set via `target.$triple.runner` have precedence over `target.'cfg(..)'.runner`
#[cargo_test]
fn custom_runner_cfg_precedence() {
    let target = rustc_host();

    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            &format!(
                r#"
                    [target.'cfg(not(target_os = "none"))']
                    runner = "ignored-runner"

                    [target.{}]
                    runner = "nonexistent-runner -r"
                "#,
                target
            ),
        )
        .build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr_contains(
            "\
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`
",
        )
        .run();
}

#[cargo_test]
fn custom_runner_cfg_collision() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config",
            r#"
            [target.'cfg(not(target_arch = "avr"))']
            runner = "true"

            [target.'cfg(not(target_os = "none"))']
            runner = "false"
            "#,
        )
        .build();

    p.cargo("run -- --param")
        .with_status(101)
        .with_stderr(
            "\
[ERROR] several matching instances of `target.'cfg(..)'.runner` in configurations
first match `cfg(not(target_arch = \"avr\"))` located in [..]/foo/.cargo/config
second match `cfg(not(target_os = \"none\"))` located in [..]/foo/.cargo/config
",
        )
        .run();
}

#[cargo_test]
fn custom_runner_env() {
    let p = project().file("src/main.rs", "fn main() {}").build();

    let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env());

    p.cargo("run")
        .env(&key, "nonexistent-runner --foo")
        .with_status(101)
        // FIXME: Update "Caused by" error message once rust/pull/87704 is merged.
        // On Windows, changing to a custom executable resolver has changed the
        // error messages.
        .with_stderr(&format!(
            "\
[COMPILING] foo [..]
[FINISHED] dev [..]
[RUNNING] `nonexistent-runner --foo target/debug/foo[EXE]`
[ERROR] could not execute process `nonexistent-runner --foo target/debug/foo[EXE]` (never executed)

Caused by:
  [..]
"
        ))
        .run();
}

#[cargo_test]
fn custom_runner_env_overrides_config() {
    let target = rustc_host();
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            &format!(
                r#"
                    [target.{}]
                    runner = "should-not-run -r"
                "#,
                target
            ),
        )
        .build();

    let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env());

    p.cargo("run")
        .env(&key, "should-run --foo")
        .with_status(101)
        .with_stderr_contains("[RUNNING] `should-run --foo target/debug/foo[EXE]`")
        .run();
}

#[cargo_test]
#[cfg(unix)] // Assumes `true` is in PATH.
fn custom_runner_env_true() {
    // Check for a bug where "true" was interpreted as a boolean instead of
    // the executable.
    let p = project().file("src/main.rs", "fn main() {}").build();

    let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env());

    p.cargo("run")
        .env(&key, "true")
        .with_stderr_contains("[RUNNING] `true target/debug/foo[EXE]`")
        .run();
}

#[cargo_test]
fn custom_linker_env() {
    let p = project().file("src/main.rs", "fn main() {}").build();

    let key = format!("CARGO_TARGET_{}_LINKER", rustc_host_env());

    p.cargo("build -v")
        .env(&key, "nonexistent-linker")
        .with_status(101)
        .with_stderr_contains("[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]")
        .run();
}

#[cargo_test]
fn target_in_environment_contains_lower_case() {
    let p = project().file("src/main.rs", "fn main() {}").build();

    let target = rustc_host();
    let env_key = format!(
        "CARGO_TARGET_{}_LINKER",
        target.to_lowercase().replace('-', "_")
    );

    p.cargo("build -v --target")
        .arg(target)
        .env(&env_key, "nonexistent-linker")
        .with_stderr_contains(format!(
            "warning: Environment variables are expected to use uppercase \
             letters and underscores, the variable `{}` will be ignored and \
             have no effect",
            env_key
        ))
        .run();
}

#[cargo_test]
fn cfg_ignored_fields() {
    // Test for some ignored fields in [target.'cfg()'] tables.
    let p = project()
        .file(
            ".cargo/config",
            r#"
            # Try some empty tables.
            [target.'cfg(not(foo))']
            [target.'cfg(not(bar))'.somelib]

            # A bunch of unused fields.
            [target.'cfg(not(target_os = "none"))']
            linker = 'false'
            ar = 'false'
            foo = {rustc-flags = "-l foo"}
            invalid = 1
            runner = 'false'
            rustflags = ''
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("check")
        .with_stderr(
            "\
[WARNING] unused key `somelib` in [target] config table `cfg(not(bar))`
[WARNING] unused key `ar` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `foo` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `invalid` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `linker` in [target] config table `cfg(not(target_os = \"none\"))`
[CHECKING] foo v0.0.1 ([..])
[FINISHED] [..]
",
        )
        .run();
}
<|endoftext|>


<commit_before>use crate::error::{Error, Result};
use crate::gen::fs;
use crate::Project;
use std::env;
use std::path::{Path, PathBuf};

pub(crate) enum TargetDir {
    Path(PathBuf),
    Unknown,
}

pub(crate) fn out_dir() -> Result<PathBuf> {
    env::var_os("OUT_DIR")
        .map(PathBuf::from)
        .ok_or(Error::MissingOutDir)
}

pub(crate) fn cc_build(prj: &Project) -> cc::Build {
    let mut build = cc::Build::new();
    build.include(include_dir(prj));
    if let TargetDir::Path(target_dir) = &prj.target_dir {
        build.include(target_dir.parent().unwrap());
    }
    build
}

// Symlink the header file into a predictable place. The header generated from
// path/to/mod.rs gets linked to target/cxxbridge/path/to/mod.rs.h.
pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {
    if let TargetDir::Unknown = prj.target_dir {
        return;
    }
    let _ = try_symlink_header(prj, path, original);
}

fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()> {
    let suffix = relative_to_parent_of_target_dir(prj, original)?;
    let ref dst = include_dir(prj).join(suffix);

    fs::create_dir_all(dst.parent().unwrap())?;
    let _ = fs::remove_file(dst);
    symlink_or_copy(path, dst)?;

    let mut file_name = dst.file_name().unwrap().to_os_string();
    file_name.push(".h");
    let ref dst2 = dst.with_file_name(file_name);
    symlink_or_copy(path, dst2)?;

    Ok(())
}

fn relative_to_parent_of_target_dir(prj: &Project, original: &Path) -> Result<PathBuf> {
    let mut outer = match &prj.target_dir {
        TargetDir::Path(target_dir) => target_dir.parent().unwrap(),
        TargetDir::Unknown => unimplemented!(), // FIXME
    };
    let original = canonicalize(original)?;
    loop {
        if let Ok(suffix) = original.strip_prefix(outer) {
            return Ok(suffix.to_owned());
        }
        match outer.parent() {
            Some(parent) => outer = parent,
            None => return Ok(original.components().skip(1).collect()),
        }
    }
}

pub(crate) fn out_with_extension(prj: &Project, path: &Path, ext: &str) -> Result<PathBuf> {
    let mut file_name = path.file_name().unwrap().to_owned();
    file_name.push(ext);

    let rel = relative_to_parent_of_target_dir(prj, path)?;
    Ok(prj.out_dir.join(rel).with_file_name(file_name))
}

pub(crate) fn include_dir(prj: &Project) -> PathBuf {
    match &prj.target_dir {
        TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
        TargetDir::Unknown => prj.out_dir.join("cxxbridge"),
    }
}

pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
    let mut dir = match out_dir.canonicalize() {
        Ok(dir) => dir,
        Err(_) => return TargetDir::Unknown,
    };
    loop {
        if dir.ends_with("target") {
            return TargetDir::Path(dir);
        }
        if !dir.pop() {
            return TargetDir::Unknown;
        }
    }
}

#[cfg(not(windows))]
fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
    Ok(fs::canonicalize(path)?)
}

#[cfg(windows)]
fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
    // unable to handle in includes. Use a poor approximation instead.
    // https://github.com/rust-lang/rust/issues/42869
    // https://github.com/alexcrichton/cc-rs/issues/169
    Ok(fs::current_dir()?.join(path))
}

#[cfg(unix)]
use self::fs::symlink_file as symlink_or_copy;

#[cfg(windows)]
fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
    // require Developer Mode. If it fails, fall back to copying the file.
    if fs::symlink_file(src, dst).is_err() {
        fs::copy(src, dst)?;
    }
    Ok(())
}

#[cfg(not(any(unix, windows)))]
use self::fs::copy as symlink_or_copy;
<commit_msg>Only assume target dir if parent contains Cargo.toml<commit_after>use crate::error::{Error, Result};
use crate::gen::fs;
use crate::Project;
use std::env;
use std::path::{Path, PathBuf};

pub(crate) enum TargetDir {
    Path(PathBuf),
    Unknown,
}

pub(crate) fn out_dir() -> Result<PathBuf> {
    env::var_os("OUT_DIR")
        .map(PathBuf::from)
        .ok_or(Error::MissingOutDir)
}

pub(crate) fn cc_build(prj: &Project) -> cc::Build {
    let mut build = cc::Build::new();
    build.include(include_dir(prj));
    if let TargetDir::Path(target_dir) = &prj.target_dir {
        build.include(target_dir.parent().unwrap());
    }
    build
}

// Symlink the header file into a predictable place. The header generated from
// path/to/mod.rs gets linked to target/cxxbridge/path/to/mod.rs.h.
pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {
    if let TargetDir::Unknown = prj.target_dir {
        return;
    }
    let _ = try_symlink_header(prj, path, original);
}

fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()> {
    let suffix = relative_to_parent_of_target_dir(prj, original)?;
    let ref dst = include_dir(prj).join(suffix);

    fs::create_dir_all(dst.parent().unwrap())?;
    let _ = fs::remove_file(dst);
    symlink_or_copy(path, dst)?;

    let mut file_name = dst.file_name().unwrap().to_os_string();
    file_name.push(".h");
    let ref dst2 = dst.with_file_name(file_name);
    symlink_or_copy(path, dst2)?;

    Ok(())
}

fn relative_to_parent_of_target_dir(prj: &Project, original: &Path) -> Result<PathBuf> {
    let mut outer = match &prj.target_dir {
        TargetDir::Path(target_dir) => target_dir.parent().unwrap(),
        TargetDir::Unknown => unimplemented!(), // FIXME
    };
    let original = canonicalize(original)?;
    loop {
        if let Ok(suffix) = original.strip_prefix(outer) {
            return Ok(suffix.to_owned());
        }
        match outer.parent() {
            Some(parent) => outer = parent,
            None => return Ok(original.components().skip(1).collect()),
        }
    }
}

pub(crate) fn out_with_extension(prj: &Project, path: &Path, ext: &str) -> Result<PathBuf> {
    let mut file_name = path.file_name().unwrap().to_owned();
    file_name.push(ext);

    let rel = relative_to_parent_of_target_dir(prj, path)?;
    Ok(prj.out_dir.join(rel).with_file_name(file_name))
}

pub(crate) fn include_dir(prj: &Project) -> PathBuf {
    match &prj.target_dir {
        TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
        TargetDir::Unknown => prj.out_dir.join("cxxbridge"),
    }
}

pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
    let mut dir = match out_dir.canonicalize() {
        Ok(dir) => dir,
        Err(_) => return TargetDir::Unknown,
    };
    loop {
        let is_target = dir.ends_with("target");
        let parent_contains_cargo_toml = dir.with_file_name("Cargo.toml").exists();
        if is_target && parent_contains_cargo_toml {
            return TargetDir::Path(dir);
        }
        if !dir.pop() {
            return TargetDir::Unknown;
        }
    }
}

#[cfg(not(windows))]
fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
    Ok(fs::canonicalize(path)?)
}

#[cfg(windows)]
fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
    // unable to handle in includes. Use a poor approximation instead.
    // https://github.com/rust-lang/rust/issues/42869
    // https://github.com/alexcrichton/cc-rs/issues/169
    Ok(fs::current_dir()?.join(path))
}

#[cfg(unix)]
use self::fs::symlink_file as symlink_or_copy;

#[cfg(windows)]
fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
    // require Developer Mode. If it fails, fall back to copying the file.
    if fs::symlink_file(src, dst).is_err() {
        fs::copy(src, dst)?;
    }
    Ok(())
}

#[cfg(not(any(unix, windows)))]
use self::fs::copy as symlink_or_copy;
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use actor::{Actor, ActorMessageStatus, ActorRegistry};
use protocol::JsonPacketStream;
use serde_json::Value;
use std::collections::BTreeMap;
use std::net::TcpStream;

#[derive(Serialize)]
struct ThreadAttachedReply {
    from: String,
    #[serde(rename = "type")]
    type_: String,
    actor: String,
    poppedFrames: Vec<PoppedFrameMsg>,
    why: WhyMsg,
}

#[derive(Serialize)]
enum PoppedFrameMsg {}

#[derive(Serialize)]
struct WhyMsg {
    #[serde(rename = "type")]
    type_: String,
}

#[derive(Serialize)]
struct ThreadResumedReply {
    from: String,
    #[serde(rename = "type")]
    type_: String,
}

#[derive(Serialize)]
struct ReconfigureReply {
    from: String
}

pub struct ThreadActor {
    name: String,
}

impl ThreadActor {
    pub fn new(name: String) -> ThreadActor {
        ThreadActor {
            name: name,
        }
    }
}

impl Actor for ThreadActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      registry: &ActorRegistry,
                      msg_type: &str,
                      _msg: &BTreeMap<String, Value>,
                      stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> {
        Ok(match msg_type {
            "attach" => {
                let msg = ThreadAttachedReply {
                    from: self.name(),
                    type_: "paused".to_owned(),
                    actor: registry.new_name("pause"),
                    poppedFrames: vec![],
                    why: WhyMsg { type_: "attached".to_owned() },
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            },

            "resume" => {
                let msg = ThreadResumedReply {
                    from: self.name(),
                    type_: "resumed".to_owned(),
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            },

            "reconfigure" => {
                stream.write_json_packet(&ReconfigureReply { from: self.name() });
                ActorMessageStatus::Processed
            }

            _ => ActorMessageStatus::Ignored,
        })
    }
}
<commit_msg>Implement a dummy sources message in the thread actor<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use actor::{Actor, ActorMessageStatus, ActorRegistry};
use protocol::JsonPacketStream;
use serde_json::Value;
use std::collections::BTreeMap;
use std::net::TcpStream;

#[derive(Serialize)]
struct ThreadAttachedReply {
    from: String,
    #[serde(rename = "type")]
    type_: String,
    actor: String,
    poppedFrames: Vec<PoppedFrameMsg>,
    why: WhyMsg,
}

#[derive(Serialize)]
enum PoppedFrameMsg {}

#[derive(Serialize)]
struct WhyMsg {
    #[serde(rename = "type")]
    type_: String,
}

#[derive(Serialize)]
struct ThreadResumedReply {
    from: String,
    #[serde(rename = "type")]
    type_: String,
}

#[derive(Serialize)]
struct ReconfigureReply {
    from: String
}

#[derive(Serialize)]
struct SourcesReply {
    from: String,
    sources: Vec<Source>,
}

#[derive(Serialize)]
enum Source {}

pub struct ThreadActor {
    name: String,
}

impl ThreadActor {
    pub fn new(name: String) -> ThreadActor {
        ThreadActor {
            name: name,
        }
    }
}

impl Actor for ThreadActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      registry: &ActorRegistry,
                      msg_type: &str,
                      _msg: &BTreeMap<String, Value>,
                      stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> {
        Ok(match msg_type {
            "attach" => {
                let msg = ThreadAttachedReply {
                    from: self.name(),
                    type_: "paused".to_owned(),
                    actor: registry.new_name("pause"),
                    poppedFrames: vec![],
                    why: WhyMsg { type_: "attached".to_owned() },
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            },

            "resume" => {
                let msg = ThreadResumedReply {
                    from: self.name(),
                    type_: "resumed".to_owned(),
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            },

            "reconfigure" => {
                stream.write_json_packet(&ReconfigureReply { from: self.name() });
                ActorMessageStatus::Processed
            }

            "sources" => {
                let msg = SourcesReply {
                    from: self.name(),
                    sources: vec![],
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            }

            _ => ActorMessageStatus::Ignored,
        })
    }
}
<|endoftext|>


<commit_before>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// Core/arch/amd64/threads.rs
//! Architecture-level thread handling (helpers for ::threads).
use _common::*;

#[derive(Default)]//,Copy,Clone)]
/// Low-level thread state
pub struct State
{
	cr3: u64,
	rsp: u64,
	tlsbase: u64,
	// TODO: SSE state
}

extern "C" {
	static low_InitialPML4: ();
	static v_ktls_size: ();
	static v_t_thread_ptr_ofs: ();
	static s_tid0_tls_base: u64;
	fn task_switch(oldrsp: &mut u64, newrsp: &u64, cr3: u64, tlsbase: u64);
}

#[thread_local]
#[no_mangle]
pub static mut t_thread_ptr: *mut ::threads::Thread = 0 as *mut _;
#[thread_local]
static mut t_thread_ptr_sent: bool = false;
//#[attribute(address_space(256))]
//static cpu_switch_disable: AtomicUsize = ATOMIC_USIZE_INIT;

/// Returns the thread state for TID0 (aka the kernel's core thread)
pub fn init_tid0_state() -> State
{
	State {
		cr3: &low_InitialPML4 as *const _ as u64,
		rsp: 0,
		tlsbase: s_tid0_tls_base,
		}
}

/// Idle for a short period, called when the CPU has nothing else to do
pub fn idle()
{
	if true {
		let flags = unsafe { let v: u64; asm!("pushf; pop $0" : "=r" (v)); v };
		assert!(flags & 0x200 != 0, "idle() with IF clear, RFLAGS = {:#x}", flags);
	}
	unsafe { asm!("hlt" : : : : "volatile"); }
}

/// Prepares the TLS block at the stop of a kernel stack
#[no_mangle]
pub extern "C" fn prep_tls(top: usize, bottom: usize, thread_ptr: *mut ::threads::Thread) -> usize
{
	/*const*/ let tls_size = &v_ktls_size as *const () as usize;
	/*const*/ let t_thread_ptr_ofs = &v_t_thread_ptr_ofs as *const () as usize;

	let mut pos = top;

	// 1. Create the TLS data block
	let tlsblock_top = pos;
	pos -= tls_size;
	let tlsblock = pos;
	// - Populate the TLS data area from the template
	//  > Also set the thread pointer
	unsafe {
		assert!( t_thread_ptr_ofs + 8 < tls_size );
		::lib::mem::memset(tlsblock as *mut u8, 0, tls_size);
		::core::ptr::write( (tlsblock + t_thread_ptr_ofs) as *mut *mut ::threads::Thread, thread_ptr );
	}

	// 2. Create the TLS pointer region (i.e. the stuff right behind %fs:0)
	#[repr(C)]
	struct TlsPtrArea
	{
		data_ptr: usize,
		_unk: [u64; 13],
		stack_limit: usize,
	}
	pos -= ::core::mem::size_of::<TlsPtrArea>();
	pos -= pos % ::core::mem::min_align_of::<TlsPtrArea>();
	let tls_base = pos;
	unsafe {
		let tls_base = &mut *(tls_base as *mut TlsPtrArea);
		tls_base.data_ptr = tlsblock_top;
		tls_base.stack_limit = bottom;
	}

	tls_base
}

/// Start a new thread using the provided TCB
///
/// Allocates a new stack within the current address space
pub fn start_thread<F: FnOnce()+Send>(mut thread: Box<::threads::Thread>, code: F)
{
	let stack = ::memory::virt::alloc_stack().into_array::<u8>();;

	let stack_rgn_top = &stack[stack.len()-1] as *const _ as usize + 1;
	let mut stack_top = stack_rgn_top;
	let stack_bottom = &stack[0] as *const _ as usize;

	// 1. Allocate TLS block at the top of the stack
	log_trace!("prep_tls({:#x},{:#x},{:p})", stack_top, stack_bottom, &*thread);
	let tls_base = prep_tls(stack_top, stack_bottom, &mut *thread as *mut _);
	stack_top = tls_base;

	// 2. Populate stack with `code`
	stack_top -= ::core::mem::size_of::<F>();
	stack_top -= stack_top % ::core::mem::min_align_of::<F>();
	let code_ptr = stack_top;
	unsafe {
		::core::ptr::write(code_ptr as *mut F, code);
	}

	// 3. Populate stack with trampoline state
	// - All that is needed is to push the trampoline address (it handles calling the rust code)
	unsafe {
		stack_top -= 8;
		::core::ptr::write(stack_top as *mut u64, thread_root::<F> as usize as u64);
		stack_top -= 8;
		::core::ptr::write(stack_top as *mut u64, thread_trampoline as usize as u64);
	}

	// 4. Apply newly updated state
	thread.cpu_state.rsp = stack_top as u64;
	thread.cpu_state.tlsbase = tls_base as u64;
	thread.cpu_state.cr3 = unsafe { (*t_thread_ptr).cpu_state.cr3 };

	// 5. Switch to new thread
	switch_to(thread);

	extern "C" {
		/// Pops the root function, and sets RDI=RSP
		fn thread_trampoline();
	}
	fn thread_root<F: FnOnce()+Send>(code_ptr: *const F) -> ! {
		// Copy the closure locally
		// - TODO: Find a way that avoids needing to make this unnessesary copy. By-value FnOnce is kinda undefined, sadly
		let code = unsafe { ::core::ptr::read(code_ptr) };
		// 1. Run closure
		code();
		// 2. terminate thread
		panic!("TODO: Terminate thread at end of thread_root");
	}
}

/// Switch to the passed thread (suspending the current thread until it is rescheduled)
pub fn switch_to(newthread: Box<::threads::Thread>)
{
	if is_task_switching_disabled()
	{
		// This code should only ever trigger if a Spinlock-holding thread
		// was interrupted by an IRQ. If said thread attempts to sleep, it's an error
		assert!( newthread.is_runnable() );
	}
	else
	{
		unsafe
		{
			// TODO: Lazy save/restore SSE state
			let outstate = &mut (*t_thread_ptr).cpu_state;
			let state = &newthread.cpu_state;
			//assert!(state.rsp != 0);
			assert!(state.cr3 != 0);
			assert!(state.tlsbase != 0);
			task_switch(&mut outstate.rsp, &state.rsp, state.cr3, state.tlsbase);
		}
		unsafe
		{
			t_thread_ptr_sent = false;
			::core::mem::forget(newthread);
		}
	}
}

/// Obtain the current thread's pointer (as a owned box, thread is destroyed when box is dropped)
pub fn get_thread_ptr() -> Option<Box<::threads::Thread>>
{
	unsafe {
		assert!( !t_thread_ptr.is_null() );
		assert!( !t_thread_ptr_sent );
		t_thread_ptr_sent = true;
		::core::mem::transmute( t_thread_ptr )
	}
}
/// Release or set the current thread pointer
pub fn set_thread_ptr(ptr: Box<::threads::Thread>)
{
	unsafe {
		let ptr: *mut _ = ::core::mem::transmute(ptr);
		if t_thread_ptr == ptr {
			assert!( !t_thread_ptr_sent );
			t_thread_ptr_sent = false;
		}
		else {
			assert!( t_thread_ptr.is_null(), "t_thread_ptr is not null when set_thread_ptr is called, instead {:p}", t_thread_ptr );
			t_thread_ptr = ptr;
			t_thread_ptr_sent = false;
		}
	}
}

/// Disable task switching until corresponding `enable_task_switch` call
pub fn disable_task_switch()
{
	// TODO: increment CPU-local counter representing task switch state
}
/// Re-enable task switching
pub fn enable_task_switch()
{
}
/// Returns true is task switching is enabled
pub fn is_task_switching_disabled() -> bool
{
	// Return (s_cpu_local.
	false
}

// vim: ft=rust

<commit_msg>Fixed bug caused/exposed by binutils upgrade<commit_after>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// Core/arch/amd64/threads.rs
//! Architecture-level thread handling (helpers for ::threads).
use _common::*;

#[derive(Default)]//,Copy,Clone)]
/// Low-level thread state
pub struct State
{
	cr3: u64,
	rsp: u64,
	tlsbase: u64,
	// TODO: SSE state
}

extern "C" {
	static InitialPML4: ();
	static v_ktls_size: ();
	static v_t_thread_ptr_ofs: ();
	static s_tid0_tls_base: u64;
	fn task_switch(oldrsp: &mut u64, newrsp: &u64, cr3: u64, tlsbase: u64);
}

#[thread_local]
#[no_mangle]
pub static mut t_thread_ptr: *mut ::threads::Thread = 0 as *mut _;
#[thread_local]
static mut t_thread_ptr_sent: bool = false;
//#[attribute(address_space(256))]
//static cpu_switch_disable: AtomicUsize = ATOMIC_USIZE_INIT;

/// Returns the thread state for TID0 (aka the kernel's core thread)
pub fn init_tid0_state() -> State
{
	State {
		cr3: &InitialPML4 as *const _ as u64 - super::memory::addresses::IDENT_START as u64,
		rsp: 0,
		tlsbase: s_tid0_tls_base,
		}
}

/// Idle for a short period, called when the CPU has nothing else to do
pub fn idle()
{
	if true {
		let flags = unsafe { let v: u64; asm!("pushf; pop $0" : "=r" (v)); v };
		assert!(flags & 0x200 != 0, "idle() with IF clear, RFLAGS = {:#x}", flags);
	}
	unsafe { asm!("hlt" : : : : "volatile"); }
}

/// Prepares the TLS block at the stop of a kernel stack
#[no_mangle]
pub extern "C" fn prep_tls(top: usize, bottom: usize, thread_ptr: *mut ::threads::Thread) -> usize
{
	/*const*/ let tls_size = &v_ktls_size as *const () as usize;
	/*const*/ let t_thread_ptr_ofs = &v_t_thread_ptr_ofs as *const () as usize;

	let mut pos = top;

	// 1. Create the TLS data block
	let tlsblock_top = pos;
	pos -= tls_size;
	let tlsblock = pos;
	// - Populate the TLS data area from the template
	//  > Also set the thread pointer
	unsafe {
		assert!( t_thread_ptr_ofs + 8 < tls_size );
		::lib::mem::memset(tlsblock as *mut u8, 0, tls_size);
		::core::ptr::write( (tlsblock + t_thread_ptr_ofs) as *mut *mut ::threads::Thread, thread_ptr );
	}

	// 2. Create the TLS pointer region (i.e. the stuff right behind %fs:0)
	#[repr(C)]
	struct TlsPtrArea
	{
		data_ptr: usize,
		_unk: [u64; 13],
		stack_limit: usize,
	}
	pos -= ::core::mem::size_of::<TlsPtrArea>();
	pos -= pos % ::core::mem::min_align_of::<TlsPtrArea>();
	let tls_base = pos;
	unsafe {
		let tls_base = &mut *(tls_base as *mut TlsPtrArea);
		tls_base.data_ptr = tlsblock_top;
		tls_base.stack_limit = bottom;
	}

	tls_base
}

/// Start a new thread using the provided TCB
///
/// Allocates a new stack within the current address space
pub fn start_thread<F: FnOnce()+Send>(mut thread: Box<::threads::Thread>, code: F)
{
	let stack = ::memory::virt::alloc_stack().into_array::<u8>();;

	let stack_rgn_top = &stack[stack.len()-1] as *const _ as usize + 1;
	let mut stack_top = stack_rgn_top;
	let stack_bottom = &stack[0] as *const _ as usize;

	// 1. Allocate TLS block at the top of the stack
	log_trace!("prep_tls({:#x},{:#x},{:p})", stack_top, stack_bottom, &*thread);
	let tls_base = prep_tls(stack_top, stack_bottom, &mut *thread as *mut _);
	stack_top = tls_base;

	// 2. Populate stack with `code`
	stack_top -= ::core::mem::size_of::<F>();
	stack_top -= stack_top % ::core::mem::min_align_of::<F>();
	let code_ptr = stack_top;
	unsafe {
		::core::ptr::write(code_ptr as *mut F, code);
	}

	// 3. Populate stack with trampoline state
	// - All that is needed is to push the trampoline address (it handles calling the rust code)
	unsafe {
		stack_top -= 8;
		::core::ptr::write(stack_top as *mut u64, thread_root::<F> as usize as u64);
		stack_top -= 8;
		::core::ptr::write(stack_top as *mut u64, thread_trampoline as usize as u64);
	}

	// 4. Apply newly updated state
	thread.cpu_state.rsp = stack_top as u64;
	thread.cpu_state.tlsbase = tls_base as u64;
	thread.cpu_state.cr3 = unsafe { (*t_thread_ptr).cpu_state.cr3 };

	// 5. Switch to new thread
	switch_to(thread);

	extern "C" {
		/// Pops the root function, and sets RDI=RSP
		fn thread_trampoline();
	}
	fn thread_root<F: FnOnce()+Send>(code_ptr: *const F) -> ! {
		// Copy the closure locally
		// - TODO: Find a way that avoids needing to make this unnessesary copy. By-value FnOnce is kinda undefined, sadly
		let code = unsafe { ::core::ptr::read(code_ptr) };
		// 1. Run closure
		code();
		// 2. terminate thread
		panic!("TODO: Terminate thread at end of thread_root");
	}
}

/// Switch to the passed thread (suspending the current thread until it is rescheduled)
pub fn switch_to(newthread: Box<::threads::Thread>)
{
	if is_task_switching_disabled()
	{
		// This code should only ever trigger if a Spinlock-holding thread
		// was interrupted by an IRQ. If said thread attempts to sleep, it's an error
		assert!( newthread.is_runnable() );
	}
	else
	{
		unsafe
		{
			// TODO: Lazy save/restore SSE state
			let outstate = &mut (*t_thread_ptr).cpu_state;
			let state = &newthread.cpu_state;
			//assert!(state.rsp != 0);
			assert!(state.cr3 != 0);
			assert!(state.tlsbase != 0);
			task_switch(&mut outstate.rsp, &state.rsp, state.cr3, state.tlsbase);
		}
		unsafe
		{
			t_thread_ptr_sent = false;
			::core::mem::forget(newthread);
		}
	}
}

/// Obtain the current thread's pointer (as a owned box, thread is destroyed when box is dropped)
pub fn get_thread_ptr() -> Option<Box<::threads::Thread>>
{
	unsafe {
		assert!( !t_thread_ptr.is_null() );
		assert!( !t_thread_ptr_sent );
		t_thread_ptr_sent = true;
		::core::mem::transmute( t_thread_ptr )
	}
}
/// Release or set the current thread pointer
pub fn set_thread_ptr(ptr: Box<::threads::Thread>)
{
	unsafe {
		let ptr: *mut _ = ::core::mem::transmute(ptr);
		if t_thread_ptr == ptr {
			assert!( !t_thread_ptr_sent );
			t_thread_ptr_sent = false;
		}
		else {
			assert!( t_thread_ptr.is_null(), "t_thread_ptr is not null when set_thread_ptr is called, instead {:p}", t_thread_ptr );
			t_thread_ptr = ptr;
			t_thread_ptr_sent = false;
		}
	}
}

/// Disable task switching until corresponding `enable_task_switch` call
pub fn disable_task_switch()
{
	// TODO: increment CPU-local counter representing task switch state
}
/// Re-enable task switching
pub fn enable_task_switch()
{
}
/// Returns true is task switching is enabled
pub fn is_task_switching_disabled() -> bool
{
	// Return (s_cpu_local.
	false
}

// vim: ft=rust

<|endoftext|>


<commit_before>extern crate nucleotide_codons as codons;

#[test]
fn test_methionine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("ATG"), Ok("methionine"));
}

#[test]
#[ignore]
fn test_cysteine_tgt() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_cysteine_tgy() { // "compressed" name for TGT and TGC
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TGY"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_stop() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TAA"), Ok("stop codon"));
}

#[test]
#[ignore]
fn test_valine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("GTN"), Ok("valine"));
}

#[test]
#[ignore]
fn test_isoleucine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("ATH"), Ok("isoleucine"));
}

#[test]
#[ignore]
fn test_arginine_name() {
    // In arginine CGA can be "compresed" both as CGN and as MGR
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("CGA"), Ok("arginine"));
    assert_eq!(info.name_for("CGN"), Ok("arginine"));
    assert_eq!(info.name_for("MGR"), Ok("arginine"));
}

#[test]
#[ignore]
fn test_invalid() {
    let info = codons::parse(make_pairs());
    assert!(info.name_for("").is_err());
    assert!(info.name_for("VWX").is_err()); // X is not a shorthand
    assert!(info.name_for("AB").is_err()); // too short
    assert!(info.name_for("ABCD").is_err()); // too long
}

// The input data constructor. Returns a list of codon, name pairs.
fn make_pairs() -> Vec<(&'static str, &'static str)> {
    let grouped = vec![
        ("isoleucine", vec!["ATT", "ATC", "ATA"]),
        ("leucine", vec!["CTT", "CTC", "CTA", "CTG", "TTA", "TTG"]),
        ("valine", vec!["GTT", "GTC", "GTA", "GTG"]),
        ("phenylalanine", vec!["TTT", "TTC"]),
        ("methionine", vec!["ATG"]),
        ("cysteine", vec!["TGT", "TGC"]),
        ("alanine", vec!["GCT", "GCC", "GCA", "GCG"]),
        ("glycine", vec!["GGT", "GGC", "GGA", "GGG"]),
        ("proline", vec!["CCT", "CCC", "CCA", "CCG"]),
        ("threonine", vec!["ACT", "ACC", "ACA", "ACG"]),
        ("serine", vec!["TCT", "TCC", "TCA", "TCG", "AGT", "AGC"]),
        ("tyrosine", vec!["TAT", "TAC"]),
        ("tryptophan", vec!["TGG"]),
        ("glutamine", vec!["CAA", "CAG"]),
        ("asparagine", vec!["AAT", "AAC"]),
        ("histidine", vec!["CAT", "CAC"]),
        ("glutamic acid", vec!["GAA", "GAG"]),
        ("aspartic acid", vec!["GAT", "GAC"]),
        ("lysine", vec!["AAA", "AAG"]),
        ("arginine", vec!["CGT", "CGC", "CGA", "CGG", "AGA", "AGG"]),
        ("stop codon", vec!["TAA", "TAG", "TGA"])];
    let mut pairs = Vec::<(&'static str, &'static str)>::new();
    for (name, codons) in grouped.into_iter() {
        for codon in codons {
            pairs.push((codon, name));
        }
    };
    pairs.sort_by(|&(_, a), &(_, b)| a.cmp(b));
    return pairs
}
<commit_msg>nucleotide-codons: Test TGT and TGC in TGY test<commit_after>extern crate nucleotide_codons as codons;

#[test]
fn test_methionine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("ATG"), Ok("methionine"));
}

#[test]
#[ignore]
fn test_cysteine_tgt() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_cysteine_tgy() { // "compressed" name for TGT and TGC
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), info.name_for("TGY"));
    assert_eq!(info.name_for("TGC"), info.name_for("TGY"));
}

#[test]
#[ignore]
fn test_stop() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TAA"), Ok("stop codon"));
}

#[test]
#[ignore]
fn test_valine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("GTN"), Ok("valine"));
}

#[test]
#[ignore]
fn test_isoleucine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("ATH"), Ok("isoleucine"));
}

#[test]
#[ignore]
fn test_arginine_name() {
    // In arginine CGA can be "compresed" both as CGN and as MGR
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("CGA"), Ok("arginine"));
    assert_eq!(info.name_for("CGN"), Ok("arginine"));
    assert_eq!(info.name_for("MGR"), Ok("arginine"));
}

#[test]
#[ignore]
fn test_invalid() {
    let info = codons::parse(make_pairs());
    assert!(info.name_for("").is_err());
    assert!(info.name_for("VWX").is_err()); // X is not a shorthand
    assert!(info.name_for("AB").is_err()); // too short
    assert!(info.name_for("ABCD").is_err()); // too long
}

// The input data constructor. Returns a list of codon, name pairs.
fn make_pairs() -> Vec<(&'static str, &'static str)> {
    let grouped = vec![
        ("isoleucine", vec!["ATT", "ATC", "ATA"]),
        ("leucine", vec!["CTT", "CTC", "CTA", "CTG", "TTA", "TTG"]),
        ("valine", vec!["GTT", "GTC", "GTA", "GTG"]),
        ("phenylalanine", vec!["TTT", "TTC"]),
        ("methionine", vec!["ATG"]),
        ("cysteine", vec!["TGT", "TGC"]),
        ("alanine", vec!["GCT", "GCC", "GCA", "GCG"]),
        ("glycine", vec!["GGT", "GGC", "GGA", "GGG"]),
        ("proline", vec!["CCT", "CCC", "CCA", "CCG"]),
        ("threonine", vec!["ACT", "ACC", "ACA", "ACG"]),
        ("serine", vec!["TCT", "TCC", "TCA", "TCG", "AGT", "AGC"]),
        ("tyrosine", vec!["TAT", "TAC"]),
        ("tryptophan", vec!["TGG"]),
        ("glutamine", vec!["CAA", "CAG"]),
        ("asparagine", vec!["AAT", "AAC"]),
        ("histidine", vec!["CAT", "CAC"]),
        ("glutamic acid", vec!["GAA", "GAG"]),
        ("aspartic acid", vec!["GAT", "GAC"]),
        ("lysine", vec!["AAA", "AAG"]),
        ("arginine", vec!["CGT", "CGC", "CGA", "CGG", "AGA", "AGG"]),
        ("stop codon", vec!["TAA", "TAG", "TGA"])];
    let mut pairs = Vec::<(&'static str, &'static str)>::new();
    for (name, codons) in grouped.into_iter() {
        for codon in codons {
            pairs.push((codon, name));
        }
    };
    pairs.sort_by(|&(_, a), &(_, b)| a.cmp(b));
    return pairs
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate columnar;
use columnar::Columnar;
use columnar::bitmap::FilteredCollection;
#[macro_use] extern crate columnar_derive;

use std::mem::size_of;

// The data for the benchmark, consiting of 8x64b=512b which is a cache line on most architectures
#[derive(Columnar, Debug, Default, Clone)]
struct Data {
    id: usize,
    val: f64,
    dummy: [usize; 6],
}

/// Perform assign operation on columnar type, input=output
#[bench]
fn data_columnar(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    let mut dc = <Data as Columnar>::with_capacity(size);
    dc.extend(a);
    b.bytes = (size_of::<usize>() * size) as u64;
    b.iter(|| {
        for e in dc.iter_mut() {
            *e.id *= 2;
        }
    })
}

/// Perform add/assign operation on row type with three inputs, one output
#[bench]
fn data_columnar_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    let mut ca = <Data as Columnar>::with_capacity(size);
    let mut cb = <Data as Columnar>::with_capacity(size);
    let mut cr = <Data as Columnar>::with_capacity(size);
    ca.extend(a);
    cb.extend(b);
    test::black_box(r.first().unwrap().dummy);
    cr.extend(r);
    bench.bytes = (size_of::<f64>() * size * 3) as u64;
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = ca.iter().zip(cb.iter()).zip(cr.iter_mut());
        for ((ea, eb), er) in zip {
            *er.val += ea.val + eb.val;
        };
    })
}

/// Perform assign operation on row type, input=output
#[bench]
fn data_row_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    test::black_box(r.first().unwrap().dummy);
    bench.bytes = (size_of::<f64>() * size * 3) as u64;
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = a.iter().zip(b.iter()).zip(r.iter_mut());
        for ((ea, eb), er) in zip {
            er.val += ea.val + eb.val;
        };
    })
}

/// Perform assign operation on row type, input=output
#[bench]
fn data_row(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    b.bytes = (size_of::<usize>() * size) as u64;
    b.iter(|| {
        for e in &mut a {
            e.id *= 2;
        }
    })
}

/// Perform add/assign operation on columnar type with three inputs, one output
#[bench]
fn data_bitmap_columnar_add_assign(bench: &mut test::Bencher) {
    let size = 1 << (20 + 1);
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    let mut ca = <Data as Columnar>::with_capacity(size);
    let mut cb = <Data as Columnar>::with_capacity(size);
    let mut cr = <Data as Columnar>::with_capacity(size);
    ca.extend(a);
    cb.extend(b);
    test::black_box(r.first().unwrap().dummy);
    cr.extend(r);
    let mut bitmap_container: FilteredCollection<_> = FilteredCollection::new(&ca, ca.len());
    // Retain every second element
    bitmap_container.retain(|d| d.id & 1 == 1);
    // We touch three values but the bitmap only exposes every second element
    bench.bytes = (size_of::<f64>() * size * 3 / 2) as u64;
    bench.iter(|| {
        // iterate the filtered collection and zip it with `cb` and `cr`.
        let zip: ::std::iter::Zip<_, _> = bitmap_container.iter().zip(cb.iter()).zip(cr.iter_mut());
        for ((ea, eb), er) in zip {
            *er.val += ea.val + eb.val;
        };
    })
}

/// Perform add/assign operation on columnar type with three inputs, one output
#[bench]
fn data_bitmap_vec_add_assign(bench: &mut test::Bencher) {
    let size = 1 << (20 + 1);
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    test::black_box(r.first().unwrap().dummy);
    let mut bitmap_container: FilteredCollection<_> = FilteredCollection::new(&a, a.len());
    // Retain every second element
    bitmap_container.retain(|d| d.id & 1 == 1);
    // We touch three values but the bitmap only exposes every second element
    bench.bytes = (size_of::<f64>() * size * 3 / 2) as u64;
    bench.iter(|| {
        // iterate the filtered collection and zip it with `b` and `r`.
        let zip: ::std::iter::Zip<_, _> = bitmap_container.iter().zip(b.iter()).zip(r.iter_mut());
        for ((ea, eb), er) in zip {
            er.val += ea.val + eb.val;
        };
    })
}
<commit_msg>bench: Benchmark extend operation<commit_after>#![feature(test)]

extern crate test;
extern crate columnar;
use columnar::Columnar;
use columnar::bitmap::FilteredCollection;
#[macro_use] extern crate columnar_derive;

use std::mem::size_of;

// The data for the benchmark, consiting of 8x64b=512b which is a cache line on most architectures
#[derive(Columnar, Debug, Default, Clone)]
struct Data {
    id: usize,
    val: f64,
    dummy: [usize; 6],
}

/// Perform assign operation on columnar type, input=output
#[bench]
fn data_columnar(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    let mut dc = <Data as Columnar>::with_capacity(size);
    dc.extend(a);
    b.bytes = (size_of::<usize>() * size) as u64;
    b.iter(|| {
        for e in dc.iter_mut() {
            *e.id *= 2;
        }
    })
}

/// Perform add/assign operation on row type with three inputs, one output
#[bench]
fn data_columnar_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    let mut ca = <Data as Columnar>::with_capacity(size);
    let mut cb = <Data as Columnar>::with_capacity(size);
    let mut cr = <Data as Columnar>::with_capacity(size);
    ca.extend(a);
    cb.extend(b);
    test::black_box(r.first().unwrap().dummy);
    cr.extend(r);
    bench.bytes = (size_of::<f64>() * size * 3) as u64;
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = ca.iter().zip(cb.iter()).zip(cr.iter_mut());
        for ((ea, eb), er) in zip {
            *er.val += ea.val + eb.val;
        };
    })
}

/// Perform assign operation on row type, input=output
#[bench]
fn data_row_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    test::black_box(r.first().unwrap().dummy);
    bench.bytes = (size_of::<f64>() * size * 3) as u64;
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = a.iter().zip(b.iter()).zip(r.iter_mut());
        for ((ea, eb), er) in zip {
            er.val += ea.val + eb.val;
        };
    })
}

/// Perform assign operation on row type, input=output
#[bench]
fn data_row(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    b.bytes = (size_of::<usize>() * size) as u64;
    b.iter(|| {
        for e in &mut a {
            e.id *= 2;
        }
    })
}

/// Perform add/assign operation on columnar type with three inputs, one output
#[bench]
fn data_bitmap_columnar_add_assign(bench: &mut test::Bencher) {
    let size = 1 << (20 + 1);
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    let mut ca = <Data as Columnar>::with_capacity(size);
    let mut cb = <Data as Columnar>::with_capacity(size);
    let mut cr = <Data as Columnar>::with_capacity(size);
    ca.extend(a);
    cb.extend(b);
    test::black_box(r.first().unwrap().dummy);
    cr.extend(r);
    let mut bitmap_container: FilteredCollection<_> = FilteredCollection::new(&ca, ca.len());
    // Retain every second element
    bitmap_container.retain(|d| d.id & 1 == 1);
    // We touch three values but the bitmap only exposes every second element
    bench.bytes = (size_of::<f64>() * size * 3 / 2) as u64;
    bench.iter(|| {
        // iterate the filtered collection and zip it with `cb` and `cr`.
        let zip: ::std::iter::Zip<_, _> = bitmap_container.iter().zip(cb.iter()).zip(cr.iter_mut());
        for ((ea, eb), er) in zip {
            *er.val += ea.val + eb.val;
        };
    })
}

/// Perform add/assign operation on columnar type with three inputs, one output
#[bench]
fn data_bitmap_vec_add_assign(bench: &mut test::Bencher) {
    let size = 1 << (20 + 1);
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    test::black_box(r.first().unwrap().dummy);
    let mut bitmap_container: FilteredCollection<_> = FilteredCollection::new(&a, a.len());
    // Retain every second element
    bitmap_container.retain(|d| d.id & 1 == 1);
    // We touch three values but the bitmap only exposes every second element
    bench.bytes = (size_of::<f64>() * size * 3 / 2) as u64;
    bench.iter(|| {
        // iterate the filtered collection and zip it with `b` and `r`.
        let zip: ::std::iter::Zip<_, _> = bitmap_container.iter().zip(b.iter()).zip(r.iter_mut());
        for ((ea, eb), er) in zip {
            er.val += ea.val + eb.val;
        };
    })
}

/// Perform assign operation on columnar type, input=output
#[bench]
fn data_row_to_columnar(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    b.bytes = (size_of::<Data>() * size) as u64;
    let mut dc = <Data as Columnar>::with_capacity(size);
    let a = &a;
    b.iter(move || {
        dc.clear();
        dc.extend(a.iter().cloned());
    })
}

<|endoftext|>


<commit_before>// Copyright Dan Schatzberg, 2015. This file is part of Genesis.

// Genesis is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Genesis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with Genesis.  If not, see <http://www.gnu.org/licenses/>.
use core::cmp::Ordering;
use core::fmt;

#[derive(Copy, Clone, Debug, Default)]
pub struct PAddr(u64);

#[derive(Copy, Clone, Debug, Default)]
pub struct VAddr(usize);

impl PAddr {
    pub fn as_u64(&self) -> u64 {
        self.0
    }
    pub fn from_u64(v: u64) -> Self {
        PAddr(v)
    }
}

impl fmt::Binary for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Display for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::LowerHex for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Octal for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::UpperHex for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl Eq for PAddr {}
impl PartialEq for PAddr {
    fn eq(&self, other: &PAddr) -> bool {
        self.0.eq(&other.0)
    }
}

impl PartialOrd for PAddr {
    fn partial_cmp(&self, other: &PAddr) -> Option<Ordering> {
        self.0.partial_cmp(&other.0)
    }
}

impl Ord for PAddr {
    fn cmp(&self, other: &PAddr) -> Ordering {
        self.0.cmp(&other.0)
    }
}

impl fmt::Binary for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Display for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::LowerHex for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Octal for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::UpperHex for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl Eq for VAddr {}
impl PartialEq for VAddr {
    fn eq(&self, other: &VAddr) -> bool {
        self.0.eq(&other.0)
    }
}

impl PartialOrd for VAddr {
    fn partial_cmp(&self, other: &VAddr) -> Option<Ordering> {
        self.0.partial_cmp(&other.0)
    }
}

impl Ord for VAddr {
    fn cmp(&self, other: &VAddr) -> Ordering {
        self.0.cmp(&other.0)
    }
}
<commit_msg>Change mem ordering impls to #[derive]<commit_after>// Copyright Dan Schatzberg, 2015. This file is part of Genesis.

// Genesis is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Genesis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with Genesis.  If not, see <http://www.gnu.org/licenses/>.
use core::fmt;

#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
pub struct PAddr(u64);

#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
pub struct VAddr(usize);

impl PAddr {
    pub fn as_u64(&self) -> u64 {
        self.0
    }
    pub fn from_u64(v: u64) -> Self {
        PAddr(v)
    }
}

impl fmt::Binary for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Display for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::LowerHex for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Octal for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::UpperHex for PAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Binary for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Display for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::LowerHex for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::Octal for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl fmt::UpperHex for VAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}
<|endoftext|>