<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{CliResult, Tool};
use clap::Parser;

/// In order to ensure that there aren't duplicate input arguments for untested CLI commands,
/// we call help on every command to ensure it at least runs
#[tokio::test]
async fn ensure_every_command_args_work() {
    assert_cmd_not_panic(&["aptos"]).await;

    assert_cmd_not_panic(&["aptos", "account"]).await;
    assert_cmd_not_panic(&["aptos", "account", "create", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "create-resource-account", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "fund-with-faucet", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "list", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "transfer", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "config"]).await;
    assert_cmd_not_panic(&["aptos", "config", "generate-shell-completions", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "config", "init", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "config", "set-global-config", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "config", "show-global-config"]).await;
    assert_cmd_not_panic(&["aptos", "config", "show-profiles"]).await;

    assert_cmd_not_panic(&["aptos", "genesis"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "generate-genesis", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "generate-keys", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "generate-layout-template", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "set-validator-configuration", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "setup-git", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "governance"]).await;
    assert_cmd_not_panic(&["aptos", "governance", "execute-proposal", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "governance", "generate-upgrade-proposal", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "governance", "propose", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "governance", "vote", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "info"]).await;

    assert_cmd_not_panic(&["aptos", "init", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "key"]).await;
    assert_cmd_not_panic(&["aptos", "key", "generate", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "key", "extract-peer", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "move"]).await;
    assert_cmd_not_panic(&["aptos", "move", "clean", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "compile", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "download", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "init", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "list", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "prove", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "publish", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "run", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "run-script", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "test", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "transactional-test", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "node"]).await;
    assert_cmd_not_panic(&["aptos", "node", "analyze-validator-performance", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "initialize-validator", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "join-validator-set", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "leave-validator-set", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "run-local-testnet", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "show-validator-config", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "show-validator-set", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "show-validator-stake", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "update-consensus-key", "--help"]).await;
    assert_cmd_not_panic(&[
        "aptos",
        "node",
        "update-validator-network-addresses",
        "--help",
    ])
    .await;

    assert_cmd_not_panic(&["aptos", "stake"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "add-stake", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "increase-lockup", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "initialize-stake-owner", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "set-delegated-voter", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "set-operator", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "unlock-stake", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "withdraw-stake", "--help"]).await;
}

async fn assert_cmd_not_panic(args: &[&str]) {
    // When a command fails, it will have a panic in it due to an improperly setup command
    // thread 'main' panicked at 'Command propose: Argument names must be unique, but 'assume-yes' is
    // in use by more than one argument or group', ...

    match run_cmd(args).await {
        Ok(inner) => assert!(
            !inner.contains("panic"),
            "Failed to not panic cmd {}: {}",
            args.join(" "),
            inner
        ),
        Err(inner) => assert!(
            !inner.contains("panic"),
            "Failed to not panic cmd {}: {}",
            args.join(" "),
            inner
        ),
    }
}

async fn run_cmd(args: &[&str]) -> CliResult {
    let tool: Tool = Tool::try_parse_from(args).map_err(|msg| msg.to_string())?;
    tool.execute().await
}
<commit_msg>[aptos-cli] Add missing commands to arg checker<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{CliResult, Tool};
use clap::Parser;

/// In order to ensure that there aren't duplicate input arguments for untested CLI commands,
/// we call help on every command to ensure it at least runs
#[tokio::test]
async fn ensure_every_command_args_work() {
    assert_cmd_not_panic(&["aptos"]).await;

    assert_cmd_not_panic(&["aptos", "account"]).await;
    assert_cmd_not_panic(&["aptos", "account", "create", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "create-resource-account", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "fund-with-faucet", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "list", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "lookup-address", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "rotate-key", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "account", "transfer", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "config"]).await;
    assert_cmd_not_panic(&["aptos", "config", "generate-shell-completions", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "config", "init", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "config", "set-global-config", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "config", "show-global-config"]).await;
    assert_cmd_not_panic(&["aptos", "config", "show-profiles"]).await;

    assert_cmd_not_panic(&["aptos", "genesis"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "generate-genesis", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "generate-keys", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "generate-layout-template", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "set-validator-configuration", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "genesis", "setup-git", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "governance"]).await;
    assert_cmd_not_panic(&["aptos", "governance", "execute-proposal", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "governance", "generate-upgrade-proposal", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "governance", "propose", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "governance", "vote", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "info"]).await;

    assert_cmd_not_panic(&["aptos", "init", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "key"]).await;
    assert_cmd_not_panic(&["aptos", "key", "generate", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "key", "extract-peer", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "move"]).await;
    assert_cmd_not_panic(&["aptos", "move", "clean", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "compile", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "download", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "init", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "list", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "prove", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "publish", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "run", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "run-script", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "test", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "move", "transactional-test", "--help"]).await;

    assert_cmd_not_panic(&["aptos", "node"]).await;
    assert_cmd_not_panic(&["aptos", "node", "analyze-validator-performance", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "bootstrap-db-from-backup", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "initialize-validator", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "join-validator-set", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "leave-validator-set", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "run-local-testnet", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "show-validator-config", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "show-validator-set", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "show-validator-stake", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "node", "update-consensus-key", "--help"]).await;
    assert_cmd_not_panic(&[
        "aptos",
        "node",
        "update-validator-network-addresses",
        "--help",
    ])
    .await;

    assert_cmd_not_panic(&["aptos", "stake"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "add-stake", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "increase-lockup", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "initialize-stake-owner", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "set-delegated-voter", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "set-operator", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "unlock-stake", "--help"]).await;
    assert_cmd_not_panic(&["aptos", "stake", "withdraw-stake", "--help"]).await;
}

async fn assert_cmd_not_panic(args: &[&str]) {
    // When a command fails, it will have a panic in it due to an improperly setup command
    // thread 'main' panicked at 'Command propose: Argument names must be unique, but 'assume-yes' is
    // in use by more than one argument or group', ...

    match run_cmd(args).await {
        Ok(inner) => assert!(
            !inner.contains("panic"),
            "Failed to not panic cmd {}: {}",
            args.join(" "),
            inner
        ),
        Err(inner) => assert!(
            !inner.contains("panic"),
            "Failed to not panic cmd {}: {}",
            args.join(" "),
            inner
        ),
    }
}

async fn run_cmd(args: &[&str]) -> CliResult {
    let tool: Tool = Tool::try_parse_from(args).map_err(|msg| msg.to_string())?;
    tool.execute().await
}
<|endoftext|>


<commit_before>use std::thread;
use std::pin::Pin;
use std::task::{Poll, Context};

use tokio::sync::mpsc;
use tokio::stream::Stream;
use serde::{Serialize, de::DeserializeOwned};
use ipc_channel::ipc::{IpcReceiver, IpcError};

/// Asynchronous wrapper over `IpcReceiver` that yields `Result<T, IpcError>`.
///
/// The `ipc_channel::ipc::IpcReceiver` type can't be shared between threads, so it can't be used
/// from `tokio::task::spawn_blocking`. This type uses a separate thread to manage receiving
/// values asynchronously. It implements the `Stream` trait, which allows it to be polled over
/// and over again for each received value.
#[derive(Debug)]
pub struct AsyncIpcReceiver<T: Serialize + DeserializeOwned + Send + 'static> {
    receiver: mpsc::UnboundedReceiver<Result<T, IpcError>>,
}

impl<T: Serialize + DeserializeOwned + Send + 'static> AsyncIpcReceiver<T> {
    pub fn new(ipc_receiver: IpcReceiver<T>) -> Self {
        let (sender, receiver) = mpsc::unbounded_channel();

        thread::spawn(move || {
            loop {
                let next_value = match ipc_receiver.recv() {
                    // No longer connected
                    Err(IpcError::Disconnected) => break,
                    // For anything else, just forward along the entire value
                    value => value,
                };

                match sender.send(next_value) {
                    Ok(()) => {},
                    // Main thread has quit, so this thread should terminate too
                    Err(_) => break,
                }
            }
        });

        Self {receiver}
    }

    /// Receives the next value from the IPC receiver.
    pub async fn recv(&mut self) -> Result<T, IpcError> {
        // This should never return None because the spawned thread runs forever
        self.receiver.recv().await
            .expect("bug: thread carrying sender terminated before main thread")
    }
}

impl<T: Serialize + DeserializeOwned + Send + 'static> Stream for AsyncIpcReceiver<T> {
    type Item = Result<T, IpcError>;

    fn poll_next(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Option<Self::Item>> {
        // This is safe because `receiver` is pinned whenever `Self` is pinned.
        //
        // Note that this requires upholding several invariants as documented here:
        // https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
        let receiver = unsafe { self.map_unchecked_mut(|r| &mut r.receiver) };
        Stream::poll_next(receiver, ctx)
    }
}
<commit_msg>No need for unsafe because UnboundedReceiver is Unpin<commit_after>use std::thread;
use std::pin::Pin;
use std::task::{Poll, Context};

use tokio::sync::mpsc;
use tokio::stream::Stream;
use serde::{Serialize, de::DeserializeOwned};
use ipc_channel::ipc::{IpcReceiver, IpcError};

/// Asynchronous wrapper over `IpcReceiver` that yields `Result<T, IpcError>`.
///
/// The `ipc_channel::ipc::IpcReceiver` type can't be shared between threads, so it can't be used
/// from `tokio::task::spawn_blocking`. This type uses a separate thread to manage receiving
/// values asynchronously. It implements the `Stream` trait, which allows it to be polled over
/// and over again for each received value.
#[derive(Debug)]
pub struct AsyncIpcReceiver<T: Serialize + DeserializeOwned + Send + 'static> {
    receiver: mpsc::UnboundedReceiver<Result<T, IpcError>>,
}

impl<T: Serialize + DeserializeOwned + Send + 'static> AsyncIpcReceiver<T> {
    pub fn new(ipc_receiver: IpcReceiver<T>) -> Self {
        let (sender, receiver) = mpsc::unbounded_channel();

        thread::spawn(move || {
            loop {
                let next_value = match ipc_receiver.recv() {
                    // No longer connected
                    Err(IpcError::Disconnected) => break,
                    // For anything else, just forward along the entire value
                    value => value,
                };

                match sender.send(next_value) {
                    Ok(()) => {},
                    // Main thread has quit, so this thread should terminate too
                    Err(_) => break,
                }
            }
        });

        Self {receiver}
    }

    /// Receives the next value from the IPC receiver.
    pub async fn recv(&mut self) -> Result<T, IpcError> {
        // This should never return None because the spawned thread runs forever
        self.receiver.recv().await
            .expect("bug: thread carrying sender terminated before main thread")
    }
}

impl<T: Serialize + DeserializeOwned + Send + 'static> Stream for AsyncIpcReceiver<T> {
    type Item = Result<T, IpcError>;

    fn poll_next(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Option<Self::Item>> {
        Stream::poll_next(Pin::new(&mut self.get_mut().receiver), ctx)
    }
}
<|endoftext|>


<commit_before>/// Provides implementations of `From<$a> for $b` and `From<$b> for $a` that transmutes the value.
macro_rules! from_transmute {
    { unsafe $a:ty => $b:ty } => {
        from_transmute!{ @impl $a => $b }
        from_transmute!{ @impl $b => $a }
    };
    { @impl $from:ty => $to:ty } => {
        impl core::convert::From<$from> for $to {
            #[inline]
            fn from(value: $from) -> $to {
                unsafe { core::mem::transmute(value) }
            }
        }
    };
}

/// Provides implementations of `From<$generic> for core::arch::{x86, x86_64}::$intel` and
/// vice-versa that transmutes the value.
macro_rules! from_transmute_x86 {
    { unsafe $generic:ty => $intel:ident } => {
        #[cfg(target_arch = "x86")]
        from_transmute! { unsafe $generic => core::arch::x86::$intel }

        #[cfg(target_arch = "x86_64")]
        from_transmute! { unsafe $generic => core::arch::x86_64::$intel }
    }
}

/// Calls a the macro `$mac` with the provided `$args` followed by `$repeat` repeated the specified
/// number of times.
macro_rules! call_repeat {
    { 1 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)*
        }
    };
    { 2 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)*
        }
    };
    { 4 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
    { 8 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
    { 16 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
    { 32 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
    { 64 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
}

/// Calls the macro `$mac` with the specified `$args` followed by the specified number of unique
/// identifiers.
macro_rules! call_counting_args {
    { 1 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            value
        }
    };
    { 2 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0 v1
        }
    };
    { 4 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0 v1 v2 v3
        }
    };
    { 8 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0 v1 v2 v3 v4 v5 v6 v7
        }
    };
    { 16 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
        }
    };
    { 32 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0  v1  v2  v3  v4  v5  v6  v7  v8  v9  v10 v11 v12 v13 v14 v15
            v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31
        }
    };
    { 64 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0  v1  v2  v3  v4  v5  v6  v7  v8  v9  v10 v11 v12 v13 v14 v15
            v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31
            v32 v33 v34 v35 v36 v37 v38 v39 v40 v41 v42 v43 v44 v45 v46 v47
            v48 v49 v50 v51 v52 v53 v54 v55 v56 v57 v58 v59 v60 v61 v62 v63
        }
    };
}

/// Implements common traits on the specified vector `$name`, holding multiple `$lanes` of `$type`.
macro_rules! base_vector_traits {
    { $name:path => [$type:ty; $lanes:literal] } => {
        impl Copy for $name {}

        impl Clone for $name {
            fn clone(&self) -> Self {
                *self
            }
        }

        impl Default for $name {
            fn default() -> Self {
                Self::splat(<$type>::default())
            }
        }

        impl PartialEq for $name {
            fn eq(&self, other: &Self) -> bool {
                AsRef::<[$type]>::as_ref(self) == AsRef::<[$type]>::as_ref(other)
            }
        }

        impl PartialOrd for $name {
            fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
                AsRef::<[$type]>::as_ref(self).partial_cmp(AsRef::<[$type]>::as_ref(other))
            }
        }

        // array references
        impl AsRef<[$type; $lanes]> for $name {
            #[inline]
            fn as_ref(&self) -> &[$type; $lanes] {
                unsafe { &*(self as *const _ as *const _) }
            }
        }

        impl AsMut<[$type; $lanes]> for $name {
            #[inline]
            fn as_mut(&mut self) -> &mut [$type; $lanes] {
                unsafe { &mut *(self as *mut _ as *mut _) }
            }
        }

        // slice references
        impl AsRef<[$type]> for $name {
            #[inline]
            fn as_ref(&self) -> &[$type] {
                AsRef::<[$type; $lanes]>::as_ref(self)
            }
        }

        impl AsMut<[$type]> for $name {
            #[inline]
            fn as_mut(&mut self) -> &mut [$type] {
                AsMut::<[$type; $lanes]>::as_mut(self)
            }
        }

        // vector/array conversion
        from_transmute! { unsafe $name => [$type; $lanes] }

        // splat
        impl From<$type> for $name {
            #[inline]
            fn from(value: $type) -> Self {
                Self::splat(value)
            }
        }
    }
}

/// Implements additional integer traits (Eq, Ord, Hash) on the specified vector `$name`, holding multiple `$lanes` of `$type`.
macro_rules! integer_vector_traits {
    { $name:path => [$type:ty; $lanes:literal] } => {
        impl Eq for $name {}

        impl Ord for $name {
            fn cmp(&self, other: &Self) -> core::cmp::Ordering {
                AsRef::<[$type]>::as_ref(self).cmp(AsRef::<[$type]>::as_ref(other))
            }
        }

        impl core::hash::Hash for $name {
            fn hash<H>(&self, state: &mut H)
            where
                H: core::hash::Hasher
            {
                AsRef::<[$type]>::as_ref(self).hash(state)
            }
        }
    }
}

/// Defines a vector `$name` containing multiple `$lanes` of `$type`.
macro_rules! define_vector {
    { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
        call_repeat! { $lanes => define_vector [$type] def $(#[$attr])* | $name | }

        impl $name {
            call_repeat! { $lanes => define_vector [$type] splat $type | }
            call_counting_args! { $lanes => define_vector => new $type | }
        }

        base_vector_traits! { $name => [$type; $lanes] }
    };
    { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
        $(#[$attr])*
        #[allow(non_camel_case_types)]
        #[repr(simd)]
        pub struct $name($($itype),*);
    };
    { splat $type:ty | $($itype:ty)* } => {
        /// Construct a vector by setting all lanes to the given value.
        #[inline]
        pub const fn splat(value: $type) -> Self {
            Self($(value as $itype),*)
        }
    };
    { new $type:ty | $($var:ident)* } => {
        /// Construct a vector by setting each lane to the given values.
        #[allow(clippy::too_many_arguments)]
        #[inline]
        pub const fn new($($var: $type),*) -> Self {
            Self($($var),*)
        }
    }
}

/// Defines an integer vector `$name` containing multiple `$lanes` of integer `$type`.
macro_rules! define_integer_vector {
    { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
        define_vector! {
            $(#[$attr])*
            struct $name([$type; $lanes]);
        }

        integer_vector_traits! { $name => [$type; $lanes] }
    }
}

/// Defines a mask vector `$name` containing multiple `$lanes` of `$type`, represented by the
/// underlying type `$impl_type`.
macro_rules! define_mask_vector {
    { $(#[$attr:meta])* struct $name:ident([$impl_type:ty as $type:ty; $lanes:tt]); } => {
        call_repeat! { $lanes => define_mask_vector [$impl_type] def $(#[$attr])* | $name | }

        impl $name {
            call_repeat! { $lanes => define_mask_vector [$impl_type] splat $type | }
            call_counting_args! { $lanes => define_mask_vector => new $type | }
        }

        base_vector_traits! { $name => [$type; $lanes] }
        integer_vector_traits! { $name => [$type; $lanes] }
    };
    { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
        $(#[$attr])*
        #[allow(non_camel_case_types)]
        #[repr(simd)]
        pub struct $name($($itype),*);
    };
    { splat $type:ty | $($itype:ty)* } => {
        /// Construct a vector by setting all lanes to the given value.
        #[inline]
        pub const fn splat(value: $type) -> Self {
            Self($(value.0 as $itype),*)
        }
    };
    { new $type:ty | $($var:ident)* } => {
        /// Construct a vector by setting each lane to the given values.
        #[allow(clippy::too_many_arguments)]
        #[inline]
        pub const fn new($($var: $type),*) -> Self {
            Self($($var.0),*)
        }
    }
}
<commit_msg>Mark trait methods inline<commit_after>/// Provides implementations of `From<$a> for $b` and `From<$b> for $a` that transmutes the value.
macro_rules! from_transmute {
    { unsafe $a:ty => $b:ty } => {
        from_transmute!{ @impl $a => $b }
        from_transmute!{ @impl $b => $a }
    };
    { @impl $from:ty => $to:ty } => {
        impl core::convert::From<$from> for $to {
            #[inline]
            fn from(value: $from) -> $to {
                unsafe { core::mem::transmute(value) }
            }
        }
    };
}

/// Provides implementations of `From<$generic> for core::arch::{x86, x86_64}::$intel` and
/// vice-versa that transmutes the value.
macro_rules! from_transmute_x86 {
    { unsafe $generic:ty => $intel:ident } => {
        #[cfg(target_arch = "x86")]
        from_transmute! { unsafe $generic => core::arch::x86::$intel }

        #[cfg(target_arch = "x86_64")]
        from_transmute! { unsafe $generic => core::arch::x86_64::$intel }
    }
}

/// Calls a the macro `$mac` with the provided `$args` followed by `$repeat` repeated the specified
/// number of times.
macro_rules! call_repeat {
    { 1 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)*
        }
    };
    { 2 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)*
        }
    };
    { 4 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
    { 8 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
    { 16 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
    { 32 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
    { 64 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
        $mac! {
            $($args)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
            $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
        }
    };
}

/// Calls the macro `$mac` with the specified `$args` followed by the specified number of unique
/// identifiers.
macro_rules! call_counting_args {
    { 1 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            value
        }
    };
    { 2 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0 v1
        }
    };
    { 4 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0 v1 v2 v3
        }
    };
    { 8 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0 v1 v2 v3 v4 v5 v6 v7
        }
    };
    { 16 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
        }
    };
    { 32 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0  v1  v2  v3  v4  v5  v6  v7  v8  v9  v10 v11 v12 v13 v14 v15
            v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31
        }
    };
    { 64 => $mac:path => $($args:tt)* } => {
        $mac! {
            $($args)*
            v0  v1  v2  v3  v4  v5  v6  v7  v8  v9  v10 v11 v12 v13 v14 v15
            v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31
            v32 v33 v34 v35 v36 v37 v38 v39 v40 v41 v42 v43 v44 v45 v46 v47
            v48 v49 v50 v51 v52 v53 v54 v55 v56 v57 v58 v59 v60 v61 v62 v63
        }
    };
}

/// Implements common traits on the specified vector `$name`, holding multiple `$lanes` of `$type`.
macro_rules! base_vector_traits {
    { $name:path => [$type:ty; $lanes:literal] } => {
        impl Copy for $name {}

        impl Clone for $name {
            #[inline]
            fn clone(&self) -> Self {
                *self
            }
        }

        impl Default for $name {
            #[inline]
            fn default() -> Self {
                Self::splat(<$type>::default())
            }
        }

        impl PartialEq for $name {
            #[inline]
            fn eq(&self, other: &Self) -> bool {
                AsRef::<[$type]>::as_ref(self) == AsRef::<[$type]>::as_ref(other)
            }
        }

        impl PartialOrd for $name {
            #[inline]
            fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
                AsRef::<[$type]>::as_ref(self).partial_cmp(AsRef::<[$type]>::as_ref(other))
            }
        }

        // array references
        impl AsRef<[$type; $lanes]> for $name {
            #[inline]
            fn as_ref(&self) -> &[$type; $lanes] {
                unsafe { &*(self as *const _ as *const _) }
            }
        }

        impl AsMut<[$type; $lanes]> for $name {
            #[inline]
            fn as_mut(&mut self) -> &mut [$type; $lanes] {
                unsafe { &mut *(self as *mut _ as *mut _) }
            }
        }

        // slice references
        impl AsRef<[$type]> for $name {
            #[inline]
            fn as_ref(&self) -> &[$type] {
                AsRef::<[$type; $lanes]>::as_ref(self)
            }
        }

        impl AsMut<[$type]> for $name {
            #[inline]
            fn as_mut(&mut self) -> &mut [$type] {
                AsMut::<[$type; $lanes]>::as_mut(self)
            }
        }

        // vector/array conversion
        from_transmute! { unsafe $name => [$type; $lanes] }

        // splat
        impl From<$type> for $name {
            #[inline]
            fn from(value: $type) -> Self {
                Self::splat(value)
            }
        }
    }
}

/// Implements additional integer traits (Eq, Ord, Hash) on the specified vector `$name`, holding multiple `$lanes` of `$type`.
macro_rules! integer_vector_traits {
    { $name:path => [$type:ty; $lanes:literal] } => {
        impl Eq for $name {}

        impl Ord for $name {
            #[inline]
            fn cmp(&self, other: &Self) -> core::cmp::Ordering {
                AsRef::<[$type]>::as_ref(self).cmp(AsRef::<[$type]>::as_ref(other))
            }
        }

        impl core::hash::Hash for $name {
            #[inline]
            fn hash<H>(&self, state: &mut H)
            where
                H: core::hash::Hasher
            {
                AsRef::<[$type]>::as_ref(self).hash(state)
            }
        }
    }
}

/// Defines a vector `$name` containing multiple `$lanes` of `$type`.
macro_rules! define_vector {
    { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
        call_repeat! { $lanes => define_vector [$type] def $(#[$attr])* | $name | }

        impl $name {
            call_repeat! { $lanes => define_vector [$type] splat $type | }
            call_counting_args! { $lanes => define_vector => new $type | }
        }

        base_vector_traits! { $name => [$type; $lanes] }
    };
    { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
        $(#[$attr])*
        #[allow(non_camel_case_types)]
        #[repr(simd)]
        pub struct $name($($itype),*);
    };
    { splat $type:ty | $($itype:ty)* } => {
        /// Construct a vector by setting all lanes to the given value.
        #[inline]
        pub const fn splat(value: $type) -> Self {
            Self($(value as $itype),*)
        }
    };
    { new $type:ty | $($var:ident)* } => {
        /// Construct a vector by setting each lane to the given values.
        #[allow(clippy::too_many_arguments)]
        #[inline]
        pub const fn new($($var: $type),*) -> Self {
            Self($($var),*)
        }
    }
}

/// Defines an integer vector `$name` containing multiple `$lanes` of integer `$type`.
macro_rules! define_integer_vector {
    { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
        define_vector! {
            $(#[$attr])*
            struct $name([$type; $lanes]);
        }

        integer_vector_traits! { $name => [$type; $lanes] }
    }
}

/// Defines a mask vector `$name` containing multiple `$lanes` of `$type`, represented by the
/// underlying type `$impl_type`.
macro_rules! define_mask_vector {
    { $(#[$attr:meta])* struct $name:ident([$impl_type:ty as $type:ty; $lanes:tt]); } => {
        call_repeat! { $lanes => define_mask_vector [$impl_type] def $(#[$attr])* | $name | }

        impl $name {
            call_repeat! { $lanes => define_mask_vector [$impl_type] splat $type | }
            call_counting_args! { $lanes => define_mask_vector => new $type | }
        }

        base_vector_traits! { $name => [$type; $lanes] }
        integer_vector_traits! { $name => [$type; $lanes] }
    };
    { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
        $(#[$attr])*
        #[allow(non_camel_case_types)]
        #[repr(simd)]
        pub struct $name($($itype),*);
    };
    { splat $type:ty | $($itype:ty)* } => {
        /// Construct a vector by setting all lanes to the given value.
        #[inline]
        pub const fn splat(value: $type) -> Self {
            Self($(value.0 as $itype),*)
        }
    };
    { new $type:ty | $($var:ident)* } => {
        /// Construct a vector by setting each lane to the given values.
        #[allow(clippy::too_many_arguments)]
        #[inline]
        pub const fn new($($var: $type),*) -> Self {
            Self($($var.0),*)
        }
    }
}
<|endoftext|>


<commit_before>
<commit_msg>Add missing module declaration for windows<commit_after>pub mod process_helper;
<|endoftext|>


<commit_before>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * 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/
*/
#![allow(non_snake_case)]
//! Testing physical properties of a Lennard-Jones gaz of Helium.
extern crate env_logger;
extern crate cymbalum;
use self::cymbalum::*;

use std::path::Path;

fn setup<T: Integrator + 'static>(integrator: T) -> (Simulation, Universe) {
    let data_dir = Path::new(file!()).parent().unwrap();
    let configuration = data_dir.join("data").join("Helium.xyz");
    let mut universe = Universe::from_file(configuration.to_str().unwrap()).unwrap();
    universe.set_cell(UnitCell::cubic(10.0));
    universe.add_pair_interaction("He", "He",
        LennardJones{
            sigma: units::from(2.0, "A").unwrap(),
            epsilon: units::from(0.2, "kJ/mol").unwrap()
        }
    );

    let mut velocities = BoltzmanVelocities::new(units::from(300.0, "K").unwrap());
    velocities.init(&mut universe);

    let simulation = Simulation::new(
        MolecularDynamics::from_integrator(integrator)
    );
    return (simulation, universe);
}

#[test]
#[allow(unused_must_use)]
fn constant_energy_velocity_verlet() {
    env_logger::init();
    let (mut simulation, mut universe) = setup(
        VelocityVerlet::new(units::from(1.0, "fs").unwrap())
    );

    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();

    assert!(f64::abs(E_initial - E_final) < 1e-5);
}

#[test]
#[allow(unused_must_use)]
fn constant_energy_verlet() {
    env_logger::init();
    let (mut simulation, mut universe) = setup(
        Verlet::new(units::from(1.0, "fs").unwrap())
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs(E_initial - E_final) < 1e-4);
}

#[test]
#[allow(unused_must_use)]
fn constant_energy_leap_frog() {
    env_logger::init();
    let (mut simulation, mut universe) = setup(
        LeapFrog::new(units::from(1.0, "fs").unwrap())
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs(E_initial - E_final) < 1e-5);
}
<commit_msg>Check perfect gaz relation in tests<commit_after>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * 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/
*/
#![allow(non_snake_case)]
//! Testing physical properties of a Lennard-Jones gaz of Helium.
extern crate env_logger;
extern crate cymbalum;
use self::cymbalum::*;

use std::path::Path;

fn setup<T: Integrator + 'static>(integrator: T) -> (Simulation, Universe) {
    let data_dir = Path::new(file!()).parent().unwrap();
    let configuration = data_dir.join("data").join("Helium.xyz");
    let mut universe = Universe::from_file(configuration.to_str().unwrap()).unwrap();
    universe.set_cell(UnitCell::cubic(10.0));
    universe.add_pair_interaction("He", "He",
        LennardJones{
            sigma: units::from(2.0, "A").unwrap(),
            epsilon: units::from(0.2, "kJ/mol").unwrap()
        }
    );

    let mut velocities = BoltzmanVelocities::new(units::from(300.0, "K").unwrap());
    velocities.init(&mut universe);

    let simulation = Simulation::new(
        MolecularDynamics::from_integrator(integrator)
    );
    return (simulation, universe);
}

#[test]
#[allow(unused_must_use)]
fn constant_energy_velocity_verlet() {
    env_logger::init();
    let (mut simulation, mut universe) = setup(
        VelocityVerlet::new(units::from(1.0, "fs").unwrap())
    );

    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();

    assert!(f64::abs(E_initial - E_final) < 1e-5);
}

#[test]
#[allow(unused_must_use)]
fn constant_energy_verlet() {
    env_logger::init();
    let (mut simulation, mut universe) = setup(
        Verlet::new(units::from(1.0, "fs").unwrap())
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs(E_initial - E_final) < 1e-4);
}

#[test]
#[allow(unused_must_use)]
fn constant_energy_leap_frog() {
    env_logger::init();
    let (mut simulation, mut universe) = setup(
        LeapFrog::new(units::from(1.0, "fs").unwrap())
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs(E_initial - E_final) < 1e-5);
}

#[test]
fn perfect_gaz() {
    let (mut simulation, mut universe) = setup(
        VelocityVerlet::new(units::from(1.0, "fs").unwrap())
    );

    // dilating the universe!
    for particle in universe.iter_mut() {
        let pos = particle.position().clone();
        particle.set_position(10.0 * pos);
    }
    universe.set_cell(UnitCell::cubic(100.0));

    simulation.run(&mut universe, 1000);
    let P = universe.pressure();
    let V = universe.volume();
    let T = universe.temperature();
    let N = universe.size() as f64;

    assert!(f64::abs(P * V - N * constants::K_BOLTZMANN * T) < 1e-3);
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

use sys::{Component, Disk, DiskType, NetworkData, Process, Processor};
use Pid;
use ProcessStatus;
use RefreshKind;

use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::Path;

/// Contains all the methods of the `Disk` struct.
pub trait DiskExt {
    /// Returns the disk type.
    fn get_type(&self) -> DiskType;

    /// Returns the disk name.
    fn get_name(&self) -> &OsStr;

    /// Returns the file system used on this disk (so for example: `EXT4`, `NTFS`, etc...).
    fn get_file_system(&self) -> &[u8];

    /// Returns the mount point of the disk (`/` for example).
    fn get_mount_point(&self) -> &Path;

    /// Returns the total disk size, in bytes.
    fn get_total_space(&self) -> u64;

    /// Returns the available disk size, in bytes.
    fn get_available_space(&self) -> u64;

    /// Update the disk' information.
    fn update(&mut self) -> bool;
}

/// Contains all the methods of the `Process` struct.
pub trait ProcessExt {
    /// Create a new process only containing the given information.
    ///
    /// On windows, the `start_time` argument is ignored.
    fn new(pid: Pid, parent: Option<Pid>, start_time: u64) -> Self;

    /// Sends the given `signal` to the process.
    fn kill(&self, signal: ::Signal) -> bool;

    /// Returns the name of the process.
    fn name(&self) -> &str;

    /// Returns the command line.
    // ///
    // /// On Windows, this is always a one element vector.
    fn cmd(&self) -> &[String];

    /// Returns the path to the process.
    fn exe(&self) -> &Path;

    /// Returns the pid of the process.
    fn pid(&self) -> Pid;

    /// Returns the environment of the process.
    ///
    /// Always empty on Windows except for current process.
    fn environ(&self) -> &[String];

    /// Returns the current working directory.
    ///
    /// Always empty on Windows.
    fn cwd(&self) -> &Path;

    /// Returns the path of the root directory.
    ///
    /// Always empty on Windows.
    fn root(&self) -> &Path;

    /// Returns the memory usage (in kB).
    fn memory(&self) -> u64;

    /// Returns the parent pid.
    fn parent(&self) -> Option<Pid>;

    /// Returns the status of the processus.
    fn status(&self) -> ProcessStatus;

    /// Returns the time of process launch (in seconds).
    fn start_time(&self) -> u64;

    /// Returns the total CPU usage.
    fn cpu_usage(&self) -> f32;
}

/// Contains all the methods of the `Processor` struct.
pub trait ProcessorExt {
    /// Returns this processor's usage.
    ///
    /// Note: You'll need to refresh it at least twice at first if you want to have a
    /// non-zero value.
    fn get_cpu_usage(&self) -> f32;

    /// Returns this processor's name.
    fn get_name(&self) -> &str;
}

/// Contains all the methods of the [`System`] type.
pub trait SystemExt: Sized {
    /// Creates a new [`System`] instance. It only contains the disks' list  and the processes list
    /// at this stage. Use the [`refresh_all`] method to update its internal information (or any of
    /// the `refresh_` method).
    ///
    /// [`refresh_all`]: #method.refresh_all
    fn new() -> Self {
        let mut s = Self::new_with_specifics(RefreshKind::new());
        s.refresh_all();
        s
    }

    /// Creates a new [`System`] instance and refresh the data corresponding to the
    /// given [`RefreshKind`].
    ///
    /// # Example
    ///
    /// ```
    /// use sysinfo::{RefreshKind, System, SystemExt};
    ///
    /// // We want everything except disks.
    /// let mut system = System::new_with_specifics(RefreshKind::everything().without_disk_list());
    ///
    /// assert_eq!(system.get_disks().len(), 0);
    /// assert!(system.get_process_list().len() > 0);
    ///
    /// // If you want the disks list afterwards, just call the corresponding
    /// // "refresh_disk_list":
    /// system.refresh_disk_list();
    /// assert!(system.get_disks().len() > 0);
    /// ```
    fn new_with_specifics(refreshes: RefreshKind) -> Self;

    /// Refreshes according to the given [`RefreshKind`]. It calls the corresponding
    /// "refresh_" methods.
    ///
    /// # Examples
    ///
    /// ```
    /// use sysinfo::{RefreshKind, System, SystemExt};
    ///
    /// let mut s = System::new();
    ///
    /// // Let's just update network data and processes:
    /// s.refresh_specifics(RefreshKind::new().with_network().with_processes());
    /// ```
    fn refresh_specifics(&mut self, refreshes: RefreshKind) {
        if refreshes.system() {
            self.refresh_system();
        }
        if refreshes.network() {
            self.refresh_network();
        }
        if refreshes.processes() {
            self.refresh_processes();
        }
        if refreshes.disk_list() {
            self.refresh_disk_list();
        }
        if refreshes.disks() {
            self.refresh_disks();
        }
    }

    /// Refresh system information (such as memory, swap, CPU usage and components' temperature).
    fn refresh_system(&mut self);

    /// Get all processes and update their information.
    fn refresh_processes(&mut self);

    /// Refresh *only* the process corresponding to `pid`. Returns `false` if the process doesn't
    /// exist.
    fn refresh_process(&mut self, pid: Pid) -> bool;

    /// Refreshes the listed disks' information.
    fn refresh_disks(&mut self);

    /// The disk list will be emptied then completely recomputed.
    fn refresh_disk_list(&mut self);

    /// Refresh data network.
    fn refresh_network(&mut self);

    /// Refreshes all system, processes and disks information.
    fn refresh_all(&mut self) {
        self.refresh_system();
        self.refresh_processes();
        self.refresh_disks();
        self.refresh_network();
    }

    /// Returns the process list.
    fn get_process_list(&self) -> &HashMap<Pid, Process>;

    /// Returns the process corresponding to the given pid or `None` if no such process exists.
    fn get_process(&self, pid: Pid) -> Option<&Process>;

    /// Returns a list of process containing the given `name`.
    fn get_process_by_name(&self, name: &str) -> Vec<&Process> {
        let mut ret = vec!();
        for val in self.get_process_list().values() {
            if val.name().contains(name) {
                ret.push(val);
            }
        }
        ret
    }

    /// The first processor in the array is the "main" one (aka the addition of all the others).
    fn get_processor_list(&self) -> &[Processor];

    /// Returns total RAM size in KiB.
    fn get_total_memory(&self) -> u64;

    /// Returns free RAM size in KiB.
    fn get_free_memory(&self) -> u64;

    /// Returns used RAM size in KiB.
    fn get_used_memory(&self) -> u64;

    /// Returns SWAP size in KiB.
    fn get_total_swap(&self) -> u64;

    /// Returns free SWAP size in KiB.
    fn get_free_swap(&self) -> u64;

    /// Returns used SWAP size in KiB.
    fn get_used_swap(&self) -> u64;

    /// Returns components list.
    fn get_components_list(&self) -> &[Component];

    /// Returns disks' list.
    fn get_disks(&self) -> &[Disk];

    /// Returns network data.
    fn get_network(&self) -> &NetworkData;

    /// Returns system uptime.
    fn get_uptime(&self) -> u64;
}

/// Getting volume of incoming and outgoing data.
pub trait NetworkExt {
    /// Returns the number of incoming bytes.
    fn get_income(&self) -> u64;

    /// Returns the number of outgoing bytes.
    fn get_outcome(&self) -> u64;
}

/// Getting a component temperature information.
pub trait ComponentExt {
    /// Returns the component's temperature (in celsius degree).
    fn get_temperature(&self) -> f32;
    /// Returns the maximum temperature of this component.
    fn get_max(&self) -> f32;
    /// Returns the highest temperature before the computer halts.
    fn get_critical(&self) -> Option<f32>;
    /// Returns component's label.
    fn get_label(&self) -> &str;
}
<commit_msg>Add disk list loading on SystemExt::new<commit_after>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

use sys::{Component, Disk, DiskType, NetworkData, Process, Processor};
use Pid;
use ProcessStatus;
use RefreshKind;

use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::Path;

/// Contains all the methods of the `Disk` struct.
pub trait DiskExt {
    /// Returns the disk type.
    fn get_type(&self) -> DiskType;

    /// Returns the disk name.
    fn get_name(&self) -> &OsStr;

    /// Returns the file system used on this disk (so for example: `EXT4`, `NTFS`, etc...).
    fn get_file_system(&self) -> &[u8];

    /// Returns the mount point of the disk (`/` for example).
    fn get_mount_point(&self) -> &Path;

    /// Returns the total disk size, in bytes.
    fn get_total_space(&self) -> u64;

    /// Returns the available disk size, in bytes.
    fn get_available_space(&self) -> u64;

    /// Update the disk' information.
    fn update(&mut self) -> bool;
}

/// Contains all the methods of the `Process` struct.
pub trait ProcessExt {
    /// Create a new process only containing the given information.
    ///
    /// On windows, the `start_time` argument is ignored.
    fn new(pid: Pid, parent: Option<Pid>, start_time: u64) -> Self;

    /// Sends the given `signal` to the process.
    fn kill(&self, signal: ::Signal) -> bool;

    /// Returns the name of the process.
    fn name(&self) -> &str;

    /// Returns the command line.
    // ///
    // /// On Windows, this is always a one element vector.
    fn cmd(&self) -> &[String];

    /// Returns the path to the process.
    fn exe(&self) -> &Path;

    /// Returns the pid of the process.
    fn pid(&self) -> Pid;

    /// Returns the environment of the process.
    ///
    /// Always empty on Windows except for current process.
    fn environ(&self) -> &[String];

    /// Returns the current working directory.
    ///
    /// Always empty on Windows.
    fn cwd(&self) -> &Path;

    /// Returns the path of the root directory.
    ///
    /// Always empty on Windows.
    fn root(&self) -> &Path;

    /// Returns the memory usage (in kB).
    fn memory(&self) -> u64;

    /// Returns the parent pid.
    fn parent(&self) -> Option<Pid>;

    /// Returns the status of the processus.
    fn status(&self) -> ProcessStatus;

    /// Returns the time of process launch (in seconds).
    fn start_time(&self) -> u64;

    /// Returns the total CPU usage.
    fn cpu_usage(&self) -> f32;
}

/// Contains all the methods of the `Processor` struct.
pub trait ProcessorExt {
    /// Returns this processor's usage.
    ///
    /// Note: You'll need to refresh it at least twice at first if you want to have a
    /// non-zero value.
    fn get_cpu_usage(&self) -> f32;

    /// Returns this processor's name.
    fn get_name(&self) -> &str;
}

/// Contains all the methods of the [`System`] type.
pub trait SystemExt: Sized {
    /// Creates a new [`System`] instance. It only contains the disks' list  and the processes list
    /// at this stage. Use the [`refresh_all`] method to update its internal information (or any of
    /// the `refresh_` method).
    ///
    /// [`refresh_all`]: #method.refresh_all
    fn new() -> Self {
        let mut s = Self::new_with_specifics(RefreshKind::new());
        s.refresh_disk_list();
        s.refresh_all();
        s
    }

    /// Creates a new [`System`] instance and refresh the data corresponding to the
    /// given [`RefreshKind`].
    ///
    /// # Example
    ///
    /// ```
    /// use sysinfo::{RefreshKind, System, SystemExt};
    ///
    /// // We want everything except disks.
    /// let mut system = System::new_with_specifics(RefreshKind::everything().without_disk_list());
    ///
    /// assert_eq!(system.get_disks().len(), 0);
    /// assert!(system.get_process_list().len() > 0);
    ///
    /// // If you want the disks list afterwards, just call the corresponding
    /// // "refresh_disk_list":
    /// system.refresh_disk_list();
    /// assert!(system.get_disks().len() > 0);
    /// ```
    fn new_with_specifics(refreshes: RefreshKind) -> Self;

    /// Refreshes according to the given [`RefreshKind`]. It calls the corresponding
    /// "refresh_" methods.
    ///
    /// # Examples
    ///
    /// ```
    /// use sysinfo::{RefreshKind, System, SystemExt};
    ///
    /// let mut s = System::new();
    ///
    /// // Let's just update network data and processes:
    /// s.refresh_specifics(RefreshKind::new().with_network().with_processes());
    /// ```
    fn refresh_specifics(&mut self, refreshes: RefreshKind) {
        if refreshes.system() {
            self.refresh_system();
        }
        if refreshes.network() {
            self.refresh_network();
        }
        if refreshes.processes() {
            self.refresh_processes();
        }
        if refreshes.disk_list() {
            self.refresh_disk_list();
        }
        if refreshes.disks() {
            self.refresh_disks();
        }
    }

    /// Refresh system information (such as memory, swap, CPU usage and components' temperature).
    fn refresh_system(&mut self);

    /// Get all processes and update their information.
    fn refresh_processes(&mut self);

    /// Refresh *only* the process corresponding to `pid`. Returns `false` if the process doesn't
    /// exist.
    fn refresh_process(&mut self, pid: Pid) -> bool;

    /// Refreshes the listed disks' information.
    fn refresh_disks(&mut self);

    /// The disk list will be emptied then completely recomputed.
    fn refresh_disk_list(&mut self);

    /// Refresh data network.
    fn refresh_network(&mut self);

    /// Refreshes all system, processes and disks information.
    fn refresh_all(&mut self) {
        self.refresh_system();
        self.refresh_processes();
        self.refresh_disks();
        self.refresh_network();
    }

    /// Returns the process list.
    fn get_process_list(&self) -> &HashMap<Pid, Process>;

    /// Returns the process corresponding to the given pid or `None` if no such process exists.
    fn get_process(&self, pid: Pid) -> Option<&Process>;

    /// Returns a list of process containing the given `name`.
    fn get_process_by_name(&self, name: &str) -> Vec<&Process> {
        let mut ret = vec!();
        for val in self.get_process_list().values() {
            if val.name().contains(name) {
                ret.push(val);
            }
        }
        ret
    }

    /// The first processor in the array is the "main" one (aka the addition of all the others).
    fn get_processor_list(&self) -> &[Processor];

    /// Returns total RAM size in KiB.
    fn get_total_memory(&self) -> u64;

    /// Returns free RAM size in KiB.
    fn get_free_memory(&self) -> u64;

    /// Returns used RAM size in KiB.
    fn get_used_memory(&self) -> u64;

    /// Returns SWAP size in KiB.
    fn get_total_swap(&self) -> u64;

    /// Returns free SWAP size in KiB.
    fn get_free_swap(&self) -> u64;

    /// Returns used SWAP size in KiB.
    fn get_used_swap(&self) -> u64;

    /// Returns components list.
    fn get_components_list(&self) -> &[Component];

    /// Returns disks' list.
    fn get_disks(&self) -> &[Disk];

    /// Returns network data.
    fn get_network(&self) -> &NetworkData;

    /// Returns system uptime.
    fn get_uptime(&self) -> u64;
}

/// Getting volume of incoming and outgoing data.
pub trait NetworkExt {
    /// Returns the number of incoming bytes.
    fn get_income(&self) -> u64;

    /// Returns the number of outgoing bytes.
    fn get_outcome(&self) -> u64;
}

/// Getting a component temperature information.
pub trait ComponentExt {
    /// Returns the component's temperature (in celsius degree).
    fn get_temperature(&self) -> f32;
    /// Returns the maximum temperature of this component.
    fn get_max(&self) -> f32;
    /// Returns the highest temperature before the computer halts.
    fn get_critical(&self) -> Option<f32>;
    /// Returns component's label.
    fn get_label(&self) -> &str;
}
<|endoftext|>


<commit_before>//! Various useful traits

use num::FromPrimitive;

/// Useful constants for radians.
pub trait Radians: FromPrimitive {
    /// Returns radians corresponding to 90 degrees.
    fn _90() -> Self;

    /// Returns radians corresponding to 180 degrees.
    fn _180() -> Self;

    /// Returns radians corresponding to 360 degrees.
    fn _360() -> Self;

    /// Convert a value to radians from degrees.
    /// Equivalent to ```value * (π / 180)```.
    fn deg_to_rad(self) -> Self;
}

impl Radians for f32 {
    #[inline(always)]
    fn _90() -> f32 {
        ::std::f32::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f32 {
        ::std::f32::consts::PI
    }

    #[inline(always)]
    fn _360() -> f32 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f32::consts::PI / 180.0f32)
    }
}

impl Radians for f64 {
    #[inline(always)]
    fn _90() -> f64 {
        ::std::f64::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f64 {
        ::std::f64::consts::PI
    }

    #[inline(always)]
    fn _360() -> f64 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f64::consts::PI / 180.0f64)
    }
}

/// Number 1.
pub trait One {
    /// Returns 1.
    fn one() -> Self;
}

/// Number 0.
pub trait Zero {
    /// Returns 0.
    fn zero() -> Self;
}

impl One for f64 {
    #[inline(always)]
    fn one() -> f64 { 1.0 }
}

impl One for f32 {
    #[inline(always)]
    fn one() -> f32 { 1.0 }
}

impl Zero for f64 {
    #[inline(always)]
    fn zero() -> f64 { 0.0 }
}

impl Zero for f32 {
    #[inline(always)]
    fn zero() -> f32 { 0.0 }
}

/// Square root.
pub trait Sqrt {
    /// Returns square root.
    fn sqrt(self) -> Self;
}

impl Sqrt for f32 {
    #[inline(always)]
    fn sqrt(self) -> f32 { self.sqrt() }
}

impl Sqrt for f64 {
    #[inline(always)]
    fn sqrt(self) -> f64 { self.sqrt() }
}

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

    #[test]
    fn test_f32_sqrt() {
        let a = 4.0f32;
        let b = <f32 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f32);
    }

    #[test]
    fn test_f64_sqrt() {
        let a = 4.0f64;
        let b = <f64 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f64);
    }

    #[test]
    fn test_f32_deg_to_rad() {
        let degrees = 23.0f32;
        let radians = degrees.deg_to_rad();
        assert!(Float::abs_sub(radians, 0.401425) > ::std::f32::EPSILON);
    }

    #[test]
    fn test_f64_deg_to_rad() {
        let degrees = 60.0f64;
        let radians = degrees.deg_to_rad();
        assert!(Float::abs_sub(radians, 1.047197)  > ::std::f64::EPSILON);
    }
}
<commit_msg>Added `Radians::rad_to_deg`<commit_after>//! Various useful traits

/// Useful constants for radians.
pub trait Radians {
    /// Returns radians corresponding to 90 degrees.
    fn _90() -> Self;

    /// Returns radians corresponding to 180 degrees.
    fn _180() -> Self;

    /// Returns radians corresponding to 360 degrees.
    fn _360() -> Self;

    /// Convert a value to radians from degrees.
    /// Equivalent to ```value * (π / 180)```.
    fn deg_to_rad(self) -> Self;

    /// Convert a value to degrees from radians.
    /// Equivalent to ```value * (180 / π)```.
    fn rad_to_deg(self) -> Self;
}

impl Radians for f32 {
    #[inline(always)]
    fn _90() -> f32 {
        ::std::f32::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f32 {
        ::std::f32::consts::PI
    }

    #[inline(always)]
    fn _360() -> f32 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f32::consts::PI / 180.0f32)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f32 / ::std::f32::consts::PI)
    }
}

impl Radians for f64 {
    #[inline(always)]
    fn _90() -> f64 {
        ::std::f64::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f64 {
        ::std::f64::consts::PI
    }

    #[inline(always)]
    fn _360() -> f64 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f64::consts::PI / 180.0f64)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f64 / ::std::f64::consts::PI)
    }
}

/// Number 1.
pub trait One {
    /// Returns 1.
    fn one() -> Self;
}

/// Number 0.
pub trait Zero {
    /// Returns 0.
    fn zero() -> Self;
}

impl One for f64 {
    #[inline(always)]
    fn one() -> f64 { 1.0 }
}

impl One for f32 {
    #[inline(always)]
    fn one() -> f32 { 1.0 }
}

impl Zero for f64 {
    #[inline(always)]
    fn zero() -> f64 { 0.0 }
}

impl Zero for f32 {
    #[inline(always)]
    fn zero() -> f32 { 0.0 }
}

/// Square root.
pub trait Sqrt {
    /// Returns square root.
    fn sqrt(self) -> Self;
}

impl Sqrt for f32 {
    #[inline(always)]
    fn sqrt(self) -> f32 { self.sqrt() }
}

impl Sqrt for f64 {
    #[inline(always)]
    fn sqrt(self) -> f64 { self.sqrt() }
}

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

    #[test]
    fn test_f32_sqrt() {
        let a = 4.0f32;
        let b = <f32 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f32);
    }

    #[test]
    fn test_f64_sqrt() {
        let a = 4.0f64;
        let b = <f64 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f64);
    }

    #[test]
    fn test_f32_deg_to_rad() {
        let degrees = 23.0f32;
        let radians = degrees.deg_to_rad();
        assert!(Float::abs_sub(radians, 0.401425) > ::std::f32::EPSILON);
    }

    #[test]
    fn test_f64_deg_to_rad() {
        let degrees = 60.0f64;
        let radians = degrees.deg_to_rad();
        assert!(Float::abs_sub(radians, 1.047197)  > ::std::f64::EPSILON);
    }
}
<|endoftext|>


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

use std::ops::{Add, Div, Mul, Sub};

/// Vector with two f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec2f {
    pub x: f32,
    pub y: f32
}

impl Vec2f {
    /// Create a Vec2f from two components
    pub fn new(x: f32, y: f32) -> Vec2f {
        Vec2f { x: x,
                y: y }
    }

    pub fn cross(&self, other: Vec2f) -> f32 {
        self.x * other.y - self.y * other.x
    }
}

impl Add for Vec2f {
    type Output = Vec2f;
    fn add(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x + v.x, self.y + v.y)
    }
}

impl Sub for Vec2f {
    type Output = Vec2f;
    fn sub(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x - v.x, self.y - v.y)
    }
}

impl Div<f32> for Vec2f {
    type Output = Vec2f;
    fn div(self, s: f32) -> Vec2f {
        Vec2f::new(self.x / s, self.y / s)
    }
}

/// 2D Quadrilateral
///
/// ```
///   p3____p2
///    |    |
///    |____|
///   p0    p1
/// ```
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Quad2f {
    pub points: (Vec2f, Vec2f, Vec2f, Vec2f)
}

impl Quad2f {
    pub fn new(points: (Vec2f, Vec2f, Vec2f, Vec2f)) -> Quad2f {
        Quad2f {
            points: points
        }
    }

    // Adapted from stackoverflow.com/questions/808441
    pub fn iblerp(&self, point: Vec2f) {
        let a = (self.points.0 - point).cross(self.points.0 - self.points.2);
        let b = ( (self.points.0 - point).cross(self.points.1 - self.points.3) + (self.points.1 - point).cross(self.points.0 - self.points.2) ) / 2;
        let c = (self.points.1 - point).cross(self.points.1 - self.points.3);
    }
}

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    /// Create a Vec3f from three components
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    /// Create a Vec3f with all components set to the same scalar
    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    /// Squared length of the vector
    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    /// Length of the vector
    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    /// Create a normalized copy, or None if the magnitude is zero
    pub fn normalized(&self) -> Option<Vec3f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            let f = 1.0 / m;
            Some((*self) * f)
        }
    }

    /// Projection of `self` into `v`, or None if the magnitude of
    /// `b` is zero.
    pub fn project_onto(&self, v: Vec3f) -> Option<Vec3f> {
        if v == ZERO_3F {
            None
        }
        else {
            Some(v * (dot3(*self, v) / dot3(v, v)))
        }
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

/// Convert a numeric type to an f32
pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for isize { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for usize { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

/// Linearly interpolate between two points by the factor `t`. When
/// `t` is zero the result is `p0`, and when `t` is one the result is
/// `p1`. The range of `t` is not clamped.
pub fn lerp3(p0: &Vec3f, p1: &Vec3f, t: f32) -> Vec3f {
    let n = 1.0 - t;
    Vec3f::new(p0.x * n + p1.x * t,
               p0.y * n + p1.y * t,
               p0.z * n + p1.z * t)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Add<f32> for Vec3f {
    type Output = Vec3f;
    fn add(self, s: f32) -> Vec3f {
        Vec3f::new(self.x + s, self.y + s, self.z + s)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

impl Sub<f32> for Vec3f {
    type Output = Vec3f;
    fn sub(self, s: f32) -> Vec3f {
        Vec3f::new(self.x - s, self.y - s, self.z - s)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_normalized() {
    assert_eq!(vec3f(0, 0, 0).normalized(), None);
    assert_eq!(vec3f(0.5, 0, 0).normalized(), Some(vec3f(1, 0, 0)));
}

#[test]
fn test_vec3f_project_onto() {
    let z = vec3f(0, 0, 0);
    let a = vec3f(1, 0, 0);
    let b = vec3f(1, 1, 0);
    assert_eq!(a.project_onto(z), None);
    assert_eq!(a.project_onto(b).unwrap(), vec3f(0.5, 0.5, 0));
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}

#[test]
fn test_vec3f_lerp() {
    let p0 = vec3f(1.0, 2.0, 3.0);
    let p1 = vec3f(-1.0, -2.0, -3.0);
    assert!(lerp3(&p0, &p1, 0.0) == p0);
    assert!(lerp3(&p0, &p1, 0.25) == vec3f(0.5, 1.0, 1.5));
    assert!(lerp3(&p0, &p1, 0.5) == vec3f(0.0, 0.0, 0.0));
    assert!(lerp3(&p0, &p1, 1.0) == p1);
}
<commit_msg>Simplify Quad2f::new interface<commit_after>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with two f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec2f {
    pub x: f32,
    pub y: f32
}

impl Vec2f {
    /// Create a Vec2f from two components
    pub fn new(x: f32, y: f32) -> Vec2f {
        Vec2f { x: x,
                y: y }
    }

    pub fn cross(&self, other: Vec2f) -> f32 {
        self.x * other.y - self.y * other.x
    }
}

impl Add for Vec2f {
    type Output = Vec2f;
    fn add(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x + v.x, self.y + v.y)
    }
}

impl Sub for Vec2f {
    type Output = Vec2f;
    fn sub(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x - v.x, self.y - v.y)
    }
}

impl Div<f32> for Vec2f {
    type Output = Vec2f;
    fn div(self, s: f32) -> Vec2f {
        Vec2f::new(self.x / s, self.y / s)
    }
}

/// 2D Quadrilateral
///
/// ```
///   p3____p2
///    |    |
///    |____|
///   p0    p1
/// ```
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Quad2f {
    pub points: (Vec2f, Vec2f, Vec2f, Vec2f)
}

impl Quad2f {
    pub fn new(a: Vec2f, b: Vec2f, c: Vec2f, d: Vec2f) -> Quad2f {
        Quad2f {
            points: (a, b, c, d)
        }
    }

    // Adapted from stackoverflow.com/questions/808441
    pub fn iblerp(&self, point: Vec2f) {
        let a = (self.points.0 - point).cross(self.points.0 - self.points.2);
        let b = ( (self.points.0 - point).cross(self.points.1 - self.points.3) + (self.points.1 - point).cross(self.points.0 - self.points.2) ) / 2;
        let c = (self.points.1 - point).cross(self.points.1 - self.points.3);
    }
}

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    /// Create a Vec3f from three components
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    /// Create a Vec3f with all components set to the same scalar
    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    /// Squared length of the vector
    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    /// Length of the vector
    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    /// Create a normalized copy, or None if the magnitude is zero
    pub fn normalized(&self) -> Option<Vec3f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            let f = 1.0 / m;
            Some((*self) * f)
        }
    }

    /// Projection of `self` into `v`, or None if the magnitude of
    /// `b` is zero.
    pub fn project_onto(&self, v: Vec3f) -> Option<Vec3f> {
        if v == ZERO_3F {
            None
        }
        else {
            Some(v * (dot3(*self, v) / dot3(v, v)))
        }
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

/// Convert a numeric type to an f32
pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for isize { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for usize { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

/// Linearly interpolate between two points by the factor `t`. When
/// `t` is zero the result is `p0`, and when `t` is one the result is
/// `p1`. The range of `t` is not clamped.
pub fn lerp3(p0: &Vec3f, p1: &Vec3f, t: f32) -> Vec3f {
    let n = 1.0 - t;
    Vec3f::new(p0.x * n + p1.x * t,
               p0.y * n + p1.y * t,
               p0.z * n + p1.z * t)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Add<f32> for Vec3f {
    type Output = Vec3f;
    fn add(self, s: f32) -> Vec3f {
        Vec3f::new(self.x + s, self.y + s, self.z + s)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

impl Sub<f32> for Vec3f {
    type Output = Vec3f;
    fn sub(self, s: f32) -> Vec3f {
        Vec3f::new(self.x - s, self.y - s, self.z - s)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_normalized() {
    assert_eq!(vec3f(0, 0, 0).normalized(), None);
    assert_eq!(vec3f(0.5, 0, 0).normalized(), Some(vec3f(1, 0, 0)));
}

#[test]
fn test_vec3f_project_onto() {
    let z = vec3f(0, 0, 0);
    let a = vec3f(1, 0, 0);
    let b = vec3f(1, 1, 0);
    assert_eq!(a.project_onto(z), None);
    assert_eq!(a.project_onto(b).unwrap(), vec3f(0.5, 0.5, 0));
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}

#[test]
fn test_vec3f_lerp() {
    let p0 = vec3f(1.0, 2.0, 3.0);
    let p1 = vec3f(-1.0, -2.0, -3.0);
    assert!(lerp3(&p0, &p1, 0.0) == p0);
    assert!(lerp3(&p0, &p1, 0.25) == vec3f(0.5, 1.0, 1.5));
    assert!(lerp3(&p0, &p1, 0.5) == vec3f(0.0, 0.0, 0.0));
    assert!(lerp3(&p0, &p1, 1.0) == p1);
}
<|endoftext|>