<commit_before>use axum::{
    body::{boxed, Body, BoxBody},
    response::{Html, IntoResponse},
    routing::{get, get_service},
    Router,
};
use axum_extra::middleware::{self, Next};
use headers::{ContentLength, HeaderMapExt as _};
use http::{header, HeaderValue, Request, Response, StatusCode};
use structopt::StructOpt;
use tower::ServiceBuilder;
use tower_http::{services::ServeDir, trace::TraceLayer};
use webbundle::{Bundle, Version};

#[derive(StructOpt, Debug)]
struct Cli {
    // TODO: Support https.
    // #[structopt(long = "https")]
    // https: bool,
    #[structopt(short = "p", long = "port", default_value = "8000")]
    port: u16,
    #[structopt(long = "bind-all")]
    /// Bind all interfaces (default: only localhost - "127.0.0.1"),
    bind_all: bool,
}

#[tokio::main]
async fn main() {
    // Set the RUST_LOG, if it hasn't been explicitly defined
    if std::env::var_os("RUST_LOG").is_none() {
        std::env::set_var("RUST_LOG", "my_http_server=debug,tower_http=debug")
    }
    tracing_subscriber::fmt::init();
    let args = Cli::from_args();

    let app = Router::new()
        .nest("/wbn", get(webbundle_serve))
        .fallback(
            get_service(ServeDir::new("."))
                .handle_error(|error: std::io::Error| async move {
                    (
                        StatusCode::INTERNAL_SERVER_ERROR,
                        format!("Unhandled internal error: {}", error),
                    )
                })
                .layer(middleware::from_fn(serve_dir_extra)),
        )
        .layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));

    let addr = std::net::SocketAddr::from((
        if args.bind_all {
            [0, 0, 0, 0]
        } else {
            [127, 0, 0, 1]
        },
        args.port,
    ));
    println!("Listening on http://{}/", addr);
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

async fn webbundle_serve(req: Request) -> Result<Response<BoxBody>, (StatusCode, String)> {
    webbundle_serve_internal(req).await.map_err(|err| {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Unhandled internal error {}", err),
        )
    })
}

async fn webbundle_serve_internal(req: Request) -> anyhow::Result<Response<BoxBody>> {
    let path = req.uri().path();
    let mut full_path = std::path::PathBuf::from(".");
    for seg in path.trim_start_matches('/').split('/') {
        anyhow::ensure!(
            !seg.starts_with("..") && !seg.contains('\\'),
            "Invalid request"
        );
        full_path.push(seg);
    }
    anyhow::ensure!(is_dir(&full_path).await, "Not found");

    let bundle = Bundle::builder()
        .version(Version::VersionB2)
        .exchanges_from_dir(full_path)
        .await?
        .build()?;

    let bytes = bundle.encode()?;
    let content_length = ContentLength(bytes.len() as u64);
    let mut response = Response::new(boxed(Body::from(bytes)));
    response.headers_mut().typed_insert(content_length);
    set_response_webbundle_headers(&mut response);
    Ok(response)
}

fn set_response_webbundle_headers(response: &mut Response<BoxBody>) {
    response.headers_mut().insert(
        header::CONTENT_TYPE,
        HeaderValue::from_static("application/webbundle"),
    );
    response.headers_mut().insert(
        header::X_CONTENT_TYPE_OPTIONS,
        HeaderValue::from_static("nosniff"),
    );
}

async fn is_dir(full_path: &std::path::Path) -> bool {
    tokio::fs::metadata(full_path)
        .await
        .map(|m| m.is_dir())
        .unwrap_or(false)
}

async fn serve_dir_extra(
    req: Request,
    next: Next,
) -> Result<Response<BoxBody>, (StatusCode, String)> {
    serve_dir_extra_internal(req, next).await.map_err(|err| {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Unhandled internal error {}", err),
        )
    })
}

async fn serve_dir_extra_internal(
    req: Request,
    next: Next,
) -> anyhow::Result<Response<BoxBody>> {
    // Directory listing.
    // Ref: https://docs.rs/tower-http/0.1.0/src/tower_http/services/fs/serve_dir.rs.html
    let path = req.uri().path();
    let mut full_path = std::path::PathBuf::from(".");
    for seg in path.trim_start_matches('/').split('/') {
        anyhow::ensure!(!seg.starts_with("..") && !seg.contains('\\'));
        full_path.push(seg);
    }
    if is_dir(&full_path).await {
        let html = directory_list_files(full_path, path).await?;
        return Ok(Html(html).into_response());
    }

    if req.uri().path().ends_with(".wbn") {
        let mut res = next.run(req).await;
        set_response_webbundle_headers(&mut res);
        return Ok(res);
    }

    // default.
    Ok(next.run(req).await)
}

async fn directory_list_files(
    path: impl AsRef<std::path::Path>,
    display_name: &str,
) -> anyhow::Result<String> {
    let path = path.as_ref();

    let mut contents = String::new();
    // ReadDir is Stream
    let mut read_dir = tokio::fs::read_dir(path).await?;
    let mut files = Vec::new();
    while let Some(file) = read_dir.next_entry().await? {
        files.push(file.path());
    }
    files.sort();
    for p in files {
        let link_name = format!(
            "{}{}",
            p.file_name().unwrap().to_str().unwrap(),
            if is_dir(&p).await { "/" } else { "" }
        );
        contents.push_str(&format!(
            "
{link}
",
            link = link_name
        ));
    }

    let inline_style = r#"
body {
  box-sizing: border-box;
  min-width: 200px;
  max-width: 980px;
  margin: 0 auto;
  padding: 45px;
}
"#;

    Ok(format!(
        r#"

<meta charset="utf-8"/>
<title>{title}</title>
<link rel=stylesheet href="https://cdn.jsdelivr.net/npm/github-markdown-css">

webbundle-server: Directory listing for {display_name}

..

{contents}

"#,
        title = display_name,
        inline_style = inline_style,
        display_name = display_name,
        contents = contents
    ))
}
<commit_msg>Fix the clippy warning<commit_after>use axum::{
    body::{boxed, Body, BoxBody},
    response::{Html, IntoResponse},
    routing::{get, get_service},
    Router,
};
use axum_extra::middleware::{self, Next};
use headers::{ContentLength, HeaderMapExt as _};
use http::{header, HeaderValue, Request, Response, StatusCode};
use std::fmt::Write as _;
use structopt::StructOpt;
use tower::ServiceBuilder;
use tower_http::{services::ServeDir, trace::TraceLayer};
use webbundle::{Bundle, Version};

#[derive(StructOpt, Debug)]
struct Cli {
    // TODO: Support https.
    // #[structopt(long = "https")]
    // https: bool,
    #[structopt(short = "p", long = "port", default_value = "8000")]
    port: u16,
    #[structopt(long = "bind-all")]
    /// Bind all interfaces (default: only localhost - "127.0.0.1"),
    bind_all: bool,
}

#[tokio::main]
async fn main() {
    // Set the RUST_LOG, if it hasn't been explicitly defined
    if std::env::var_os("RUST_LOG").is_none() {
        std::env::set_var("RUST_LOG", "my_http_server=debug,tower_http=debug")
    }
    tracing_subscriber::fmt::init();
    let args = Cli::from_args();

    let app = Router::new()
        .nest("/wbn", get(webbundle_serve))
        .fallback(
            get_service(ServeDir::new("."))
                .handle_error(|error: std::io::Error| async move {
                    (
                        StatusCode::INTERNAL_SERVER_ERROR,
                        format!("Unhandled internal error: {}", error),
                    )
                })
                .layer(middleware::from_fn(serve_dir_extra)),
        )
        .layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));

    let addr = std::net::SocketAddr::from((
        if args.bind_all {
            [0, 0, 0, 0]
        } else {
            [127, 0, 0, 1]
        },
        args.port,
    ));
    println!("Listening on http://{}/", addr);
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

async fn webbundle_serve(req: Request) -> Result<Response<BoxBody>, (StatusCode, String)> {
    webbundle_serve_internal(req).await.map_err(|err| {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Unhandled internal error {}", err),
        )
    })
}

async fn webbundle_serve_internal(req: Request) -> anyhow::Result<Response<BoxBody>> {
    let path = req.uri().path();
    let mut full_path = std::path::PathBuf::from(".");
    for seg in path.trim_start_matches('/').split('/') {
        anyhow::ensure!(
            !seg.starts_with("..") && !seg.contains('\\'),
            "Invalid request"
        );
        full_path.push(seg);
    }
    anyhow::ensure!(is_dir(&full_path).await, "Not found");

    let bundle = Bundle::builder()
        .version(Version::VersionB2)
        .exchanges_from_dir(full_path)
        .await?
        .build()?;

    let bytes = bundle.encode()?;
    let content_length = ContentLength(bytes.len() as u64);
    let mut response = Response::new(boxed(Body::from(bytes)));
    response.headers_mut().typed_insert(content_length);
    set_response_webbundle_headers(&mut response);
    Ok(response)
}

fn set_response_webbundle_headers(response: &mut Response<BoxBody>) {
    response.headers_mut().insert(
        header::CONTENT_TYPE,
        HeaderValue::from_static("application/webbundle"),
    );
    response.headers_mut().insert(
        header::X_CONTENT_TYPE_OPTIONS,
        HeaderValue::from_static("nosniff"),
    );
}

async fn is_dir(full_path: &std::path::Path) -> bool {
    tokio::fs::metadata(full_path)
        .await
        .map(|m| m.is_dir())
        .unwrap_or(false)
}

async fn serve_dir_extra(
    req: Request,
    next: Next,
) -> Result<Response<BoxBody>, (StatusCode, String)> {
    serve_dir_extra_internal(req, next).await.map_err(|err| {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Unhandled internal error {}", err),
        )
    })
}

async fn serve_dir_extra_internal(
    req: Request,
    next: Next,
) -> anyhow::Result<Response<BoxBody>> {
    // Directory listing.
    // Ref: https://docs.rs/tower-http/0.1.0/src/tower_http/services/fs/serve_dir.rs.html
    let path = req.uri().path();
    let mut full_path = std::path::PathBuf::from(".");
    for seg in path.trim_start_matches('/').split('/') {
        anyhow::ensure!(!seg.starts_with("..") && !seg.contains('\\'));
        full_path.push(seg);
    }
    if is_dir(&full_path).await {
        let html = directory_list_files(full_path, path).await?;
        return Ok(Html(html).into_response());
    }

    if req.uri().path().ends_with(".wbn") {
        let mut res = next.run(req).await;
        set_response_webbundle_headers(&mut res);
        return Ok(res);
    }

    // default.
    Ok(next.run(req).await)
}

async fn directory_list_files(
    path: impl AsRef<std::path::Path>,
    display_name: &str,
) -> anyhow::Result<String> {
    let path = path.as_ref();

    let mut contents = String::new();
    // ReadDir is Stream
    let mut read_dir = tokio::fs::read_dir(path).await?;
    let mut files = Vec::new();
    while let Some(file) = read_dir.next_entry().await? {
        files.push(file.path());
    }
    files.sort();
    for p in files {
        let link_name = format!(
            "{}{}",
            p.file_name().unwrap().to_str().unwrap(),
            if is_dir(&p).await { "/" } else { "" }
        );
        write!(
            contents,
            "
{link}
",
            link = link_name
        )?;
    }

    let inline_style = r#"
body {
  box-sizing: border-box;
  min-width: 200px;
  max-width: 980px;
  margin: 0 auto;
  padding: 45px;
}
"#;

    Ok(format!(
        r#"

<meta charset="utf-8"/>
<title>{title}</title>
<link rel=stylesheet href="https://cdn.jsdelivr.net/npm/github-markdown-css">

webbundle-server: Directory listing for {display_name}

..

{contents}

"#,
        title = display_name,
        inline_style = inline_style,
        display_name = display_name,
        contents = contents
    ))
}
<|endoftext|>


<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license

use energy::Potential;
use energy::{PairPotential, BondPotential, AnglePotential, DihedralPotential};

/// The `NullPotential` always returns 0 as energy and force.
///
/// It should be used to indicate that there is no potential interaction between
/// two particles kinds.
#[derive(Clone, Copy)]
pub struct NullPotential;
impl Potential for NullPotential {
    #[inline] fn energy(&self, _: f64) -> f64 {0.0}
    #[inline] fn force(&self, _: f64) -> f64 {0.0}
}

impl PairPotential for NullPotential {}
impl BondPotential for NullPotential {}
impl AnglePotential for NullPotential {}
impl DihedralPotential for NullPotential {}

/******************************************************************************/
/// Lennard-Jones potential.
///
/// The following expression is used:
/// $$ V(r) = 4 \epsilon \left[ (\sigma/r)^{12} - (\sigma/r)^{6} \right] $$
/// where $\sigma$ is a distance constant, and $\epsilon$ an energetic constant.
#[derive(Clone, Copy)]
pub struct LennardJones {
    /// Distance constant of the Lennard-Jones potential
    pub sigma: f64,
    /// Energy constant of the Lennard-Jones potential
    pub epsilon: f64,
}

impl Potential for LennardJones {
    #[inline]
    fn energy(&self, r: f64) -> f64 {
        let s6 = f64::powi(self.sigma/r, 6);
        4.0 * self.epsilon * (f64::powi(s6, 2) - s6)
    }

    #[inline]
    fn force(&self, r: f64) -> f64 {
        let s6 = f64::powi(self.sigma/r, 6);
        -24.0 * self.epsilon * (s6 - 2.0 * f64::powi(s6, 2)) / r
    }
}

impl PairPotential for LennardJones {}

/******************************************************************************/
/// Harmonic potential.
///
/// The following expression is used:
/// $$ V(x) = \frac 12 k (x - x_0)^2 $$
/// where $x_0$ is the distance equilibrium, and $k$ the elastic constant.
#[derive(Clone, Copy)]
pub struct Harmonic {
    /// Spring constant
    pub k: f64,
    /// Equilibrium value
    pub x0: f64,
}

impl Potential for Harmonic {
    #[inline]
    fn energy(&self, x: f64) -> f64 {
        let dx = x - self.x0;
        0.5 * self.k * dx * dx
    }

    #[inline]
    fn force(&self, x: f64) -> f64 {
        self.k * (self.x0 - x)
    }
}

impl PairPotential for Harmonic {}
impl BondPotential for Harmonic {}
impl AnglePotential for Harmonic {}
impl DihedralPotential for Harmonic {}

/******************************************************************************/
/// Cosine harmonic potential.
///
/// The following expression is used:
/// $$ V(r) = \frac 12 k (\cos r - \cos x_0)^2 $$
/// where $x_0$ is the distance equilibrium, and $k$ the elastic constant.
#[derive(Clone, Copy)]
pub struct CosineHarmonic {
    /// Spring constant
    k: f64,
    /// Cosine of the equilibrium value
    cos_x0: f64,
}

impl CosineHarmonic {
    /// Create a new `CosineHarmonic` potentials, with elastic constant of `k`
    /// and equilibrium value of `x0`
    pub fn new(k: f64, x0:f64) -> CosineHarmonic {
        CosineHarmonic{k: k, cos_x0: f64::cos(x0)}
    }
}

impl Potential for CosineHarmonic {
    #[inline]
    fn energy(&self, x: f64) -> f64 {
        let dr = f64::cos(x) - self.cos_x0;
        0.5 * self.k * dr * dr
    }

    #[inline]
    fn force(&self, x: f64) -> f64 {
        self.k * (f64::cos(x) - self.cos_x0) * f64::sin(x)
    }
}

impl AnglePotential for CosineHarmonic {}
impl DihedralPotential for CosineHarmonic {}

/******************************************************************************/
/// Torsion potential.
///
/// The following expression is used:
/// $$ V(r) = k(1 + \cos(n\phi_0 - \delta)) $$
/// where $k$ is the force constant, `n` the periodicity of the potential, and
/// $\delta$ the equilibrium angle.
#[derive(Clone, Copy)]
pub struct Torsion {
    /// Force constant
    pub k: f64,
    /// Equilibrium value
    pub delta: f64,
    /// Multiplicity of the potential
    pub n: usize,
}

impl Potential for Torsion {
    #[inline]
    fn energy(&self, phi: f64) -> f64 {
        let n = self.n as f64;
        let cos = f64::cos(n * phi - self.delta);
        self.k * (1.0 + cos)
    }

    #[inline]
    fn force(&self, phi: f64) -> f64 {
        let n = self.n as f64;
        let sin = f64::sin(n * phi - self.delta);
        self.k * n * sin
    }
}

impl DihedralPotential for Torsion {}

/******************************************************************************/

#[cfg(test)]
mod tests {
    use super::*;
    use energy::Potential;
    const EPS: f64 = 1e-9;

    #[test]
    fn null() {
        let null = NullPotential;
        assert_eq!(null.energy(2.0), 0.0);
        assert_eq!(null.energy(2.5), 0.0);

        assert_eq!(null.force(2.0), 0.0);
        assert_eq!(null.force(2.5), 0.0);

        let e0 = null.energy(2.0);
        let e1 = null.energy(2.0 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, null.force(2.0), EPS);
    }

    #[test]
    fn lj() {
        let lj = LennardJones{epsilon: 0.8, sigma: 2.0};
        assert_eq!(lj.energy(2.0), 0.0);
        assert_eq!(lj.energy(2.5), -0.6189584744448002);

        assert_approx_eq!(lj.force(f64::powf(2.0, 1.0/6.0) * 2.0), 0.0);
        assert_approx_eq!(lj.force(2.5), -0.95773475733504);

        let e0 = lj.energy(4.0);
        let e1 = lj.energy(4.0 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, lj.force(4.0), 1e-6);
    }

    #[test]
    fn harmonic() {
        let harm = Harmonic{k: 50.0, x0: 2.0};
        assert_eq!(harm.energy(2.0), 0.0);
        assert_eq!(harm.energy(2.5), 6.25);

        assert_eq!(harm.force(2.0), 0.0);
        assert_eq!(harm.force(2.5), -25.0);

        let e0 = harm.energy(2.1);
        let e1 = harm.energy(2.1 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, harm.force(2.1), 1e-6);
    }

    #[test]
    fn cosine_harmonic() {
        let harm = CosineHarmonic::new(50.0, 2.0);
        assert_eq!(harm.energy(2.0), 0.0);
        let dcos = f64::cos(2.5) - f64::cos(2.0);
        assert_eq!(harm.energy(2.5), 0.5 * 50.0 * dcos * dcos);

        assert_eq!(harm.force(2.0), 0.0);
        let dcos = f64::cos(2.5) - f64::cos(2.0);
        assert_eq!(harm.force(2.5), 50.0 * dcos * f64::sin(2.5));

        let e0 = harm.energy(2.3);
        let e1 = harm.energy(2.3 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, harm.force(2.3), 1e-6);
    }

    #[test]
    fn torsion() {
        let torsion = Torsion{k: 5.0, n: 3, delta: 3.0};
        assert_eq!(torsion.energy(1.0), 10.0);
        let energy = 5.0 * (1.0 + f64::cos(3.0 * 1.1 - 3.0));
        assert_eq!(torsion.energy(1.1), energy);

        assert_eq!(torsion.force(1.0), 0.0);

        let e0 = torsion.energy(4.0);
        let e1 = torsion.energy(4.0 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, torsion.force(4.0), 1e-6);
    }
}
<commit_msg>[doc] Example for all the implemented potentials<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license

use energy::Potential;
use energy::{PairPotential, BondPotential, AnglePotential, DihedralPotential};

/// No-op potential.
///
/// The `NullPotential` always returns 0 as energy and force. It should be used
/// to indicate that there is no potential interaction for a given set of
/// particles.
///
/// # Examples
///
/// ```
/// use lumol::energy::Potential;
/// use lumol::energy::NullPotential;
///
/// let potential = NullPotential;
/// assert_eq!(potential.energy(0.1), 0.0);
/// assert_eq!(potential.energy(100000.0), 0.0);
///
/// assert_eq!(potential.force(0.1), 0.0);
/// assert_eq!(potential.force(100000.0), 0.0);
/// ```
#[derive(Clone, Copy)]
pub struct NullPotential;
impl Potential for NullPotential {
    #[inline] fn energy(&self, _: f64) -> f64 {0.0}
    #[inline] fn force(&self, _: f64) -> f64 {0.0}
}

impl PairPotential for NullPotential {}
impl BondPotential for NullPotential {}
impl AnglePotential for NullPotential {}
impl DihedralPotential for NullPotential {}

/// Lennard-Jones potential.
///
/// The following expression of Lennard-Jones potential is used: `V(r) = 4 *
/// epsilon * ((sigma/r)^12 - (sigma/r)^6)` where `sigma` is the Lennard-Jones
/// distance constant, and `epsilon` the Lennard-Jones energetic constant.
///
/// # Examples
///
/// ```
/// use lumol::energy::Potential;
/// use lumol::energy::LennardJones;
///
/// let potential = LennardJones{sigma: 2.0, epsilon: 10.0};
/// assert_eq!(potential.energy(2.0), 0.0);
/// assert_eq!(potential.energy(3.0), -3.203365942785746);
///
/// assert_eq!(potential.force(2.0), 120.0);
/// ```
#[derive(Clone, Copy)]
pub struct LennardJones {
    /// Distance constant of the Lennard-Jones potential
    pub sigma: f64,
    /// Energy constant of the Lennard-Jones potential
    pub epsilon: f64,
}

impl Potential for LennardJones {
    #[inline]
    fn energy(&self, r: f64) -> f64 {
        let s6 = f64::powi(self.sigma/r, 6);
        4.0 * self.epsilon * (f64::powi(s6, 2) - s6)
    }

    #[inline]
    fn force(&self, r: f64) -> f64 {
        let s6 = f64::powi(self.sigma/r, 6);
        -24.0 * self.epsilon * (s6 - 2.0 * f64::powi(s6, 2)) / r
    }
}

impl PairPotential for LennardJones {}

/// Harmonic potential.
///
/// The following energy expression is used: `V(x) = 1/2 * k * (x - x0)^2` where
/// `x0` is the distance equilibrium, and `k` the elastic constant.
///
/// # Examples
///
/// ```
/// use lumol::energy::Potential;
/// use lumol::energy::Harmonic;
///
/// let potential = Harmonic{x0: 2.0, k: 100.0};
/// assert_eq!(potential.energy(2.0), 0.0);
/// assert_eq!(potential.energy(3.0), 50.0);
///
/// assert_eq!(potential.force(2.0), 0.0);
/// assert_eq!(potential.force(1.5), 50.0);
/// ```
#[derive(Clone, Copy)]
pub struct Harmonic {
    /// Spring constant
    pub k: f64,
    /// Equilibrium value
    pub x0: f64,
}

impl Potential for Harmonic {
    #[inline]
    fn energy(&self, x: f64) -> f64 {
        let dx = x - self.x0;
        0.5 * self.k * dx * dx
    }

    #[inline]
    fn force(&self, x: f64) -> f64 {
        self.k * (self.x0 - x)
    }
}

impl PairPotential for Harmonic {}
impl BondPotential for Harmonic {}
impl AnglePotential for Harmonic {}
impl DihedralPotential for Harmonic {}

/// Cosine harmonic potential.
///
/// The following potential expression is used: `V(x) = 1/2 * k * (cos(x) -
/// cos(x0))^2` where `x0` is the distance equilibrium, and `k` the elastic
/// constant.
///
/// # Examples
///
/// ```
/// use lumol::energy::Potential;
/// use lumol::energy::CosineHarmonic;
///
/// let potential = CosineHarmonic::new(/* k */ 100.0, /* x0 */ 2.0);
/// assert_eq!(potential.energy(2.0), 0.0);
/// assert_eq!(potential.energy(3.0), 16.464942078100552);
///
/// assert_eq!(potential.force(2.0), 0.0);
/// ```
#[derive(Clone, Copy)]
pub struct CosineHarmonic {
    /// Spring constant
    k: f64,
    /// Cosine of the equilibrium value
    cos_x0: f64,
}

impl CosineHarmonic {
    /// Create a new `CosineHarmonic` potentials, with elastic constant of `k`
    /// and equilibrium value of `x0`
    pub fn new(k: f64, x0:f64) -> CosineHarmonic {
        CosineHarmonic{k: k, cos_x0: f64::cos(x0)}
    }
}

impl Potential for CosineHarmonic {
    #[inline]
    fn energy(&self, x: f64) -> f64 {
        let dr = f64::cos(x) - self.cos_x0;
        0.5 * self.k * dr * dr
    }

    #[inline]
    fn force(&self, x: f64) -> f64 {
        self.k * (f64::cos(x) - self.cos_x0) * f64::sin(x)
    }
}

impl AnglePotential for CosineHarmonic {}
impl DihedralPotential for CosineHarmonic {}

/// Torsion potential.
///
/// This potential is intended for use with dihedral angles, using a
/// customisable periodicity and multiple minima.
///
/// The following potential expression is used: `V(x) = k * (1 + cos(n * x -
/// delta))` where `k` is the force constant, `n` the periodicity of the
/// potential, and `delta` the equilibrium angle.
///
/// # Examples
///
/// ```
/// use lumol::energy::Potential;
/// use lumol::energy::Torsion;
/// use std::f64::consts::PI;
///
/// let potential = Torsion{delta: PI / 2.0, k: 10.0, n: 3};
/// assert_eq!(potential.energy(PI / 2.0), 0.0);
/// assert_eq!(potential.energy(PI / 3.0), 10.0);
///
/// assert!(potential.force(PI / 2.0).abs() < 1e-12);
/// ```
#[derive(Clone, Copy)]
pub struct Torsion {
    /// Force constant
    pub k: f64,
    /// Equilibrium value
    pub delta: f64,
    /// Multiplicity of the potential
    pub n: usize,
}

impl Potential for Torsion {
    #[inline]
    fn energy(&self, phi: f64) -> f64 {
        let n = self.n as f64;
        let cos = f64::cos(n * phi - self.delta);
        self.k * (1.0 + cos)
    }

    #[inline]
    fn force(&self, phi: f64) -> f64 {
        let n = self.n as f64;
        let sin = f64::sin(n * phi - self.delta);
        self.k * n * sin
    }
}

impl DihedralPotential for Torsion {}

#[cfg(test)]
mod tests {
    use super::*;
    use energy::Potential;
    const EPS: f64 = 1e-9;

    #[test]
    fn null() {
        let null = NullPotential;
        assert_eq!(null.energy(2.0), 0.0);
        assert_eq!(null.energy(2.5), 0.0);

        assert_eq!(null.force(2.0), 0.0);
        assert_eq!(null.force(2.5), 0.0);

        let e0 = null.energy(2.0);
        let e1 = null.energy(2.0 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, null.force(2.0), EPS);
    }

    #[test]
    fn lj() {
        let lj = LennardJones{epsilon: 0.8, sigma: 2.0};
        assert_eq!(lj.energy(2.0), 0.0);
        assert_eq!(lj.energy(2.5), -0.6189584744448002);

        assert_approx_eq!(lj.force(f64::powf(2.0, 1.0/6.0) * 2.0), 0.0);
        assert_approx_eq!(lj.force(2.5), -0.95773475733504);

        let e0 = lj.energy(4.0);
        let e1 = lj.energy(4.0 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, lj.force(4.0), 1e-6);
    }

    #[test]
    fn harmonic() {
        let harm = Harmonic{k: 50.0, x0: 2.0};
        assert_eq!(harm.energy(2.0), 0.0);
        assert_eq!(harm.energy(2.5), 6.25);

        assert_eq!(harm.force(2.0), 0.0);
        assert_eq!(harm.force(2.5), -25.0);

        let e0 = harm.energy(2.1);
        let e1 = harm.energy(2.1 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, harm.force(2.1), 1e-6);
    }

    #[test]
    fn cosine_harmonic() {
        let harm = CosineHarmonic::new(50.0, 2.0);
        assert_eq!(harm.energy(2.0), 0.0);
        let dcos = f64::cos(2.5) - f64::cos(2.0);
        assert_eq!(harm.energy(2.5), 0.5 * 50.0 * dcos * dcos);

        assert_eq!(harm.force(2.0), 0.0);
        let dcos = f64::cos(2.5) - f64::cos(2.0);
        assert_eq!(harm.force(2.5), 50.0 * dcos * f64::sin(2.5));

        let e0 = harm.energy(2.3);
        let e1 = harm.energy(2.3 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, harm.force(2.3), 1e-6);
    }

    #[test]
    fn torsion() {
        let torsion = Torsion{k: 5.0, n: 3, delta: 3.0};
        assert_eq!(torsion.energy(1.0), 10.0);
        let energy = 5.0 * (1.0 + f64::cos(3.0 * 1.1 - 3.0));
        assert_eq!(torsion.energy(1.1), energy);

        assert_eq!(torsion.force(1.0), 0.0);

        let e0 = torsion.energy(4.0);
        let e1 = torsion.energy(4.0 + EPS);
        assert_approx_eq!((e0 - e1)/EPS, torsion.force(4.0), 1e-6);
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::path::PathBuf;
use std::default::Default;
use std::collections::BTreeMap;

use quire::validate as V;
use libc::{uid_t, gid_t};
use rustc_serialize::{Decodable, Decoder};
use builder::commands as cmd;

use build_step::{Step, BuildStep};

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct PacmanRepo {
    pub name: String,
    pub url: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct FileInfo {
    pub name: PathBuf,
    pub contents: String,
}

#[derive(Clone, RustcDecodable, RustcEncodable, Debug)]
pub struct PyFreeze {
    pub freeze_file: PathBuf,
    pub requirements: Option<PathBuf>,
    pub packages: Vec<String>,
}

#[derive(Clone, RustcDecodable, RustcEncodable, Debug)]
pub struct Copy {
    pub source: PathBuf,
    pub path: PathBuf,
    pub owner_uid: Option<uid_t>,
    pub owner_gid: Option<gid_t>,
    pub ignore_regex: String,
}

pub fn builder_validator<'x>() -> V::Enum<'x> {
    V::Enum::new()
    .option("Install", V::Sequence::new(V::Scalar::new()))
    .option("BuildDeps", V::Sequence::new(V::Scalar::new()))
    .option("Container", V::Scalar::new())
    .option("SubConfig", V::Structure::new()
        .member("source", V::Enum::new()
            .option("Directory", V::Nothing)
            .option("Container", V::Scalar::new())
            .option("Git", V::Structure::new()
                .member("url", V::Scalar::new())
                .member("revision", V::Scalar::new().optional())
                .member("branch", V::Scalar::new().optional()))
            .optional()
            .default_tag("Directory"))
        .member("path".to_string(), V::Directory::new()
            .is_absolute(false)
            .default("vagga.yaml"))
        .member("container", V::Scalar::new())
        .member("cache", V::Scalar::new().optional())
        .member("change_dir", V::Scalar::new().optional()))
    .option("Build", V::Structure::new()
        .member("container", V::Scalar::new())
        .member("source".to_string(),
            V::Directory::new().is_absolute(true).default("/"))
        .member("path".to_string(),
            V::Directory::new().is_absolute(true).optional())
        .member("temporary_mount".to_string(),
            V::Directory::new().is_absolute(true).optional()))
    .option("Text", V::Mapping::new(
        V::Directory::new().is_absolute(true),
        V::Scalar::new()))
    .option("Copy", V::Structure::new()
        .member("source", V::Scalar::new())
        .member("path", V::Directory::new().is_absolute(true))
        .member("ignore_regex", V::Scalar::new().default(
            r#"(^|/)\.(git|hg|svn|vagga)($|/)|~$|\.bak$|\.orig$|^#.*#$"#))
        .member("owner_uid", V::Numeric::new().min(0).optional())
        .member("owner_gid", V::Numeric::new().min(0).optional()))

    .option("Ubuntu", V::Scalar::new())
    .option("UbuntuRelease", V::Structure::new()
        .member("version", V::Scalar::new())
        .member("arch", V::Scalar::new().default("amd64"))
        .member("keep_chfn_command", V::Scalar::new().default(false)))
    .option("UbuntuRepo", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("suite", V::Scalar::new())
        .member("components", V::Sequence::new(V::Scalar::new())))
    .option("UbuntuPPA", V::Scalar::new())
    .option("UbuntuUniverse", V::Nothing)
    .option("AptTrust", V::Structure::new()
        .member("server", V::Scalar::new().optional())
        .member("keys", V::Sequence::new(V::Scalar::new())))
    .option("Sh", V::Scalar::new())
    .option("Cmd", V::Sequence::new(V::Scalar::new()))
    .option("Remove", V::Directory::new().is_absolute(true))
    .option("EnsureDir", V::Directory::new().is_absolute(true))
    .option("EmptyDir", V::Directory::new().is_absolute(true))
    .option("CacheDirs", V::Mapping::new(
        V::Directory::new().is_absolute(true),
        V::Scalar::new()))
    .option("Env", V::Mapping::new(
        V::Scalar::new(),
        V::Scalar::new()))
    .option("Depends", V::Scalar::new())
    .option("Git", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("revision", V::Scalar::new().optional())
        .member("branch", V::Scalar::new().optional())
        .member("path", V::Directory::new().is_absolute(true)))
    .option("GitInstall", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("revision", V::Scalar::new().optional())
        .member("branch", V::Scalar::new().optional())
        .member("subdir", V::Directory::new()
            .default(".").is_absolute(false))
        .member("script", V::Scalar::new()
                .default("./configure --prefix=/usr\n\
                          make\n\
                          make install\n")))
    .option("Tar", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("sha256", V::Scalar::new().optional())
        .member("path", V::Directory::new().is_absolute(true).default("/"))
        .member("subdir", V::Directory::new().default("").is_absolute(false)))
    .option("TarInstall", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("sha256", V::Scalar::new().optional())
        .member("subdir", V::Directory::new().optional().is_absolute(false))
        .member("script", V::Scalar::new()
                .default("./configure --prefix=/usr\n\
                          make\n\
                          make install\n")))
    .option("Download", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("path", V::Directory::new().is_absolute(true))
        .member("mode", V::Numeric::new().default(0o644).min(0).max(0o1777)))
    .option("Alpine", V::Scalar::new())

    // Python
    .option("PipConfig", V::Structure::new()
        .member("dependencies", V::Scalar::new().default(false).optional())
        .member("cache_wheels", V::Scalar::new().default(true))
        .member("find_links", V::Sequence::new(V::Scalar::new()))
        .member("index_urls", V::Sequence::new(V::Scalar::new()))
        .member("trusted_hosts", V::Sequence::new(V::Scalar::new()))
        .member("python_exe", V::Scalar::new().optional())
        .member("install_python", V::Scalar::new().default(true)))
    .option("Py2Install", V::Sequence::new(V::Scalar::new()))
    .option("Py2Requirements", V::Scalar::new()
        .default("requirements.txt"))
    .option("Py3Install", V::Sequence::new(V::Scalar::new()))
    .option("Py3Requirements",
        V::Scalar::new().default("requirements.txt"))
    .option("PyFreeze", V::Structure::new()
        .member("freeze_file", V::Scalar::new().default("requirements.txt"))
        .member("requirements", V::Scalar::new().optional())
        .member("packages", V::Sequence::new(V::Scalar::new())))

    // Node.js
    .option("NpmConfig", V::Structure::new()
        .member("npm_exe", V::Scalar::new().default("npm"))
        .member("install_node", V::Scalar::new().default(true)))
    .option("NpmInstall", V::Sequence::new(V::Scalar::new()))
    .option("NpmDependencies", V::Structure::new()
        .member("file", V::Scalar::new().default("package.json"))
        .member("package", V::Scalar::new().default(true))
        .member("dev", V::Scalar::new().default(true))
        .member("peer", V::Scalar::new().default(false))
        .member("bundled", V::Scalar::new().default(true))
        .member("optional", V::Scalar::new().default(false)))

    // Composer
    .option("ComposerConfig", V::Structure::new()
        .member("install_runtime", V::Scalar::new().default(true))
        .member("install_dev", V::Scalar::new().default(false))
        .member("runtime_exe", V::Scalar::new().optional())
        .member("include_path", V::Scalar::new().optional()))
    .option("ComposerInstall", V::Sequence::new(V::Scalar::new()))
    .option("ComposerDependencies", V::Structure::new()
        .member("working_dir", V::Scalar::new().optional())
        .member("dev", V::Scalar::new().default(true))
        .member("prefer", V::Scalar::new().optional())
        .member("ignore_platform_reqs", V::Scalar::new().default(false))
        .member("no_autoloader", V::Scalar::new().default(false))
        .member("no_scripts", V::Scalar::new().default(false))
        .member("no_plugins", V::Scalar::new().default(false))
        .member("optimize_autoloader", V::Scalar::new().default(false))
        .member("classmap_authoritative", V::Scalar::new().default(false)))

    // Ruby
    .option("GemConfig", V::Structure::new()
        .member("install_ruby", V::Scalar::new().default(true))
        .member("gem_exe", V::Scalar::new().optional())
        .member("update_gem", V::Scalar::new().default(true)))
    .option("GemInstall", V::Sequence::new(V::Scalar::new()))
    .option("GemBundle", V::Structure::new()
        .member("gemfile", V::Scalar::new().default("Gemfile"))
        .member("without", V::Sequence::new(V::Scalar::new()))
        .member("trust_policy", V::Scalar::new().optional()))
}

fn step<T: BuildStep + 'static, E>(val: Result<T, E>)
    -> Result<Step, E>
{
    val.map(|x| Step(Rc::new(x) as Rc<BuildStep>))
}

fn decode_step<D: Decoder>(options: &[&str], index: usize, d: &mut D)
    -> Result<Step, D::Error>
{
    match options[index] {
        "Alpine" => step(cmd::alpine::Alpine::decode(d)),
        "Ubuntu" => step(cmd::ubuntu::Ubuntu::decode(d)),
        "UbuntuRepo" => step(cmd::ubuntu::UbuntuRepo::decode(d)),
        "UbuntuRelease" => step(cmd::ubuntu::UbuntuRelease::decode(d)),
        "UbuntuPPA" => step(cmd::ubuntu::UbuntuPPA::decode(d)),
        "UbuntuUniverse" => step(cmd::ubuntu::UbuntuUniverse::decode(d)),
        "AptTrust" => step(cmd::ubuntu::AptTrust::decode(d)),
        "Install" => step(cmd::packaging::Install::decode(d)),
        "BuildDeps" => step(cmd::packaging::BuildDeps::decode(d)),
        "Git" => step(cmd::vcs::Git::decode(d)),
        "GitInstall" => step(cmd::vcs::GitInstall::decode(d)),
        "PipConfig" => step(cmd::pip::PipConfig::decode(d)),
        "Py2Install" => step(cmd::pip::Py2Install::decode(d)),
        "Py2Requirements" => step(cmd::pip::Py2Requirements::decode(d)),
        "Py3Install" => step(cmd::pip::Py3Install::decode(d)),
        "Py3Requirements" => step(cmd::pip::Py3Requirements::decode(d)),
        "Tar" => step(cmd::tarcmd::Tar::decode(d)),
        "TarInstall" => step(cmd::tarcmd::TarInstall::decode(d)),
        "Sh" => step(cmd::generic::Sh::decode(d)),
        "Cmd" => step(cmd::generic::Cmd::decode(d)),
        "Env" => step(cmd::generic::Env::decode(d)),
        "Text" => step(cmd::text::Text::decode(d)),
        "Copy" => step(cmd::copy::Copy::decode(d)),
        "Download" => step(cmd::download::Download::decode(d)),
        "EnsureDir" => step(cmd::dirs::EnsureDir::decode(d)),
        "CacheDirs" => step(cmd::dirs::CacheDirs::decode(d)),
        "EmptyDir" => step(cmd::dirs::EmptyDir::decode(d)),
        "Remove" => step(cmd::dirs::Remove::decode(d)),
        "Depends" => step(cmd::generic::Depends::decode(d)),
        "Container" => step(cmd::subcontainer::Container::decode(d)),
        "Build" => step(cmd::subcontainer::Build::decode(d)),
        "SubConfig" => step(cmd::subcontainer::SubConfig::decode(d)),
        "NpmConfig" => step(cmd::npm::NpmConfig::decode(d)),
        "NpmDependencies" => step(cmd::npm::NpmDependencies::decode(d)),
        "NpmInstall" => step(cmd::npm::NpmInstall::decode(d)),
        "GemInstall" => step(cmd::gem::GemInstall::decode(d)),
        "GemBundle" => step(cmd::gem::GemBundle::decode(d)),
        "GemConfig" => step(cmd::gem::GemConfig::decode(d)),
        step_name => panic!("Step {} is not yet implemented", step_name),
    }
}

impl Decodable for Step {
    fn decode<D: Decoder>(d: &mut D) -> Result<Step, D::Error> {
        // TODO(tailhook) this is just too slow
        //                move it to lazy_static
        let val = builder_validator();
        let options = val.options.iter().map(|&(ref x, _)| &x[..])
            .collect::<Vec<_>>();
        Ok(try!(d.read_enum("BuildStep", |d| {
            d.read_enum_variant(&options, |d, index| {
                decode_step(&options, index, d)
            })
        })))
    }
}
<commit_msg>Add composer commands to config parser dispatch<commit_after>use std::rc::Rc;
use std::path::PathBuf;
use std::default::Default;
use std::collections::BTreeMap;

use quire::validate as V;
use libc::{uid_t, gid_t};
use rustc_serialize::{Decodable, Decoder};
use builder::commands as cmd;

use build_step::{Step, BuildStep};

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct PacmanRepo {
    pub name: String,
    pub url: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct FileInfo {
    pub name: PathBuf,
    pub contents: String,
}

#[derive(Clone, RustcDecodable, RustcEncodable, Debug)]
pub struct PyFreeze {
    pub freeze_file: PathBuf,
    pub requirements: Option<PathBuf>,
    pub packages: Vec<String>,
}

#[derive(Clone, RustcDecodable, RustcEncodable, Debug)]
pub struct Copy {
    pub source: PathBuf,
    pub path: PathBuf,
    pub owner_uid: Option<uid_t>,
    pub owner_gid: Option<gid_t>,
    pub ignore_regex: String,
}

pub fn builder_validator<'x>() -> V::Enum<'x> {
    V::Enum::new()
    .option("Install", V::Sequence::new(V::Scalar::new()))
    .option("BuildDeps", V::Sequence::new(V::Scalar::new()))
    .option("Container", V::Scalar::new())
    .option("SubConfig", V::Structure::new()
        .member("source", V::Enum::new()
            .option("Directory", V::Nothing)
            .option("Container", V::Scalar::new())
            .option("Git", V::Structure::new()
                .member("url", V::Scalar::new())
                .member("revision", V::Scalar::new().optional())
                .member("branch", V::Scalar::new().optional()))
            .optional()
            .default_tag("Directory"))
        .member("path".to_string(), V::Directory::new()
            .is_absolute(false)
            .default("vagga.yaml"))
        .member("container", V::Scalar::new())
        .member("cache", V::Scalar::new().optional())
        .member("change_dir", V::Scalar::new().optional()))
    .option("Build", V::Structure::new()
        .member("container", V::Scalar::new())
        .member("source".to_string(),
            V::Directory::new().is_absolute(true).default("/"))
        .member("path".to_string(),
            V::Directory::new().is_absolute(true).optional())
        .member("temporary_mount".to_string(),
            V::Directory::new().is_absolute(true).optional()))
    .option("Text", V::Mapping::new(
        V::Directory::new().is_absolute(true),
        V::Scalar::new()))
    .option("Copy", V::Structure::new()
        .member("source", V::Scalar::new())
        .member("path", V::Directory::new().is_absolute(true))
        .member("ignore_regex", V::Scalar::new().default(
            r#"(^|/)\.(git|hg|svn|vagga)($|/)|~$|\.bak$|\.orig$|^#.*#$"#))
        .member("owner_uid", V::Numeric::new().min(0).optional())
        .member("owner_gid", V::Numeric::new().min(0).optional()))

    .option("Ubuntu", V::Scalar::new())
    .option("UbuntuRelease", V::Structure::new()
        .member("version", V::Scalar::new())
        .member("arch", V::Scalar::new().default("amd64"))
        .member("keep_chfn_command", V::Scalar::new().default(false)))
    .option("UbuntuRepo", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("suite", V::Scalar::new())
        .member("components", V::Sequence::new(V::Scalar::new())))
    .option("UbuntuPPA", V::Scalar::new())
    .option("UbuntuUniverse", V::Nothing)
    .option("AptTrust", V::Structure::new()
        .member("server", V::Scalar::new().optional())
        .member("keys", V::Sequence::new(V::Scalar::new())))
    .option("Sh", V::Scalar::new())
    .option("Cmd", V::Sequence::new(V::Scalar::new()))
    .option("Remove", V::Directory::new().is_absolute(true))
    .option("EnsureDir", V::Directory::new().is_absolute(true))
    .option("EmptyDir", V::Directory::new().is_absolute(true))
    .option("CacheDirs", V::Mapping::new(
        V::Directory::new().is_absolute(true),
        V::Scalar::new()))
    .option("Env", V::Mapping::new(
        V::Scalar::new(),
        V::Scalar::new()))
    .option("Depends", V::Scalar::new())
    .option("Git", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("revision", V::Scalar::new().optional())
        .member("branch", V::Scalar::new().optional())
        .member("path", V::Directory::new().is_absolute(true)))
    .option("GitInstall", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("revision", V::Scalar::new().optional())
        .member("branch", V::Scalar::new().optional())
        .member("subdir", V::Directory::new()
            .default(".").is_absolute(false))
        .member("script", V::Scalar::new()
                .default("./configure --prefix=/usr\n\
                          make\n\
                          make install\n")))
    .option("Tar", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("sha256", V::Scalar::new().optional())
        .member("path", V::Directory::new().is_absolute(true).default("/"))
        .member("subdir", V::Directory::new().default("").is_absolute(false)))
    .option("TarInstall", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("sha256", V::Scalar::new().optional())
        .member("subdir", V::Directory::new().optional().is_absolute(false))
        .member("script", V::Scalar::new()
                .default("./configure --prefix=/usr\n\
                          make\n\
                          make install\n")))
    .option("Download", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("path", V::Directory::new().is_absolute(true))
        .member("mode", V::Numeric::new().default(0o644).min(0).max(0o1777)))
    .option("Alpine", V::Scalar::new())

    // Python
    .option("PipConfig", V::Structure::new()
        .member("dependencies", V::Scalar::new().default(false).optional())
        .member("cache_wheels", V::Scalar::new().default(true))
        .member("find_links", V::Sequence::new(V::Scalar::new()))
        .member("index_urls", V::Sequence::new(V::Scalar::new()))
        .member("trusted_hosts", V::Sequence::new(V::Scalar::new()))
        .member("python_exe", V::Scalar::new().optional())
        .member("install_python", V::Scalar::new().default(true)))
    .option("Py2Install", V::Sequence::new(V::Scalar::new()))
    .option("Py2Requirements", V::Scalar::new()
        .default("requirements.txt"))
    .option("Py3Install", V::Sequence::new(V::Scalar::new()))
    .option("Py3Requirements",
        V::Scalar::new().default("requirements.txt"))
    .option("PyFreeze", V::Structure::new()
        .member("freeze_file", V::Scalar::new().default("requirements.txt"))
        .member("requirements", V::Scalar::new().optional())
        .member("packages", V::Sequence::new(V::Scalar::new())))

    // Node.js
    .option("NpmConfig", V::Structure::new()
        .member("npm_exe", V::Scalar::new().default("npm"))
        .member("install_node", V::Scalar::new().default(true)))
    .option("NpmInstall", V::Sequence::new(V::Scalar::new()))
    .option("NpmDependencies", V::Structure::new()
        .member("file", V::Scalar::new().default("package.json"))
        .member("package", V::Scalar::new().default(true))
        .member("dev", V::Scalar::new().default(true))
        .member("peer", V::Scalar::new().default(false))
        .member("bundled", V::Scalar::new().default(true))
        .member("optional", V::Scalar::new().default(false)))

    // Composer
    .option("ComposerConfig", V::Structure::new()
        .member("install_runtime", V::Scalar::new().default(true))
        .member("install_dev", V::Scalar::new().default(false))
        .member("runtime_exe", V::Scalar::new().optional())
        .member("include_path", V::Scalar::new().optional()))
    .option("ComposerInstall", V::Sequence::new(V::Scalar::new()))
    .option("ComposerDependencies", V::Structure::new()
        .member("working_dir", V::Scalar::new().optional())
        .member("dev", V::Scalar::new().default(true))
        .member("prefer", V::Scalar::new().optional())
        .member("ignore_platform_reqs", V::Scalar::new().default(false))
        .member("no_autoloader", V::Scalar::new().default(false))
        .member("no_scripts", V::Scalar::new().default(false))
        .member("no_plugins", V::Scalar::new().default(false))
        .member("optimize_autoloader", V::Scalar::new().default(false))
        .member("classmap_authoritative", V::Scalar::new().default(false)))

    // Ruby
    .option("GemConfig", V::Structure::new()
        .member("install_ruby", V::Scalar::new().default(true))
        .member("gem_exe", V::Scalar::new().optional())
        .member("update_gem", V::Scalar::new().default(true)))
    .option("GemInstall", V::Sequence::new(V::Scalar::new()))
    .option("GemBundle", V::Structure::new()
        .member("gemfile", V::Scalar::new().default("Gemfile"))
        .member("without", V::Sequence::new(V::Scalar::new()))
        .member("trust_policy", V::Scalar::new().optional()))
}

fn step<T: BuildStep + 'static, E>(val: Result<T, E>)
    -> Result<Step, E>
{
    val.map(|x| Step(Rc::new(x) as Rc<BuildStep>))
}

fn decode_step<D: Decoder>(options: &[&str], index: usize, d: &mut D)
    -> Result<Step, D::Error>
{
    match options[index] {
        "Alpine" => step(cmd::alpine::Alpine::decode(d)),
        "Ubuntu" => step(cmd::ubuntu::Ubuntu::decode(d)),
        "UbuntuRepo" => step(cmd::ubuntu::UbuntuRepo::decode(d)),
        "UbuntuRelease" => step(cmd::ubuntu::UbuntuRelease::decode(d)),
        "UbuntuPPA" => step(cmd::ubuntu::UbuntuPPA::decode(d)),
        "UbuntuUniverse" => step(cmd::ubuntu::UbuntuUniverse::decode(d)),
        "AptTrust" => step(cmd::ubuntu::AptTrust::decode(d)),
        "Install" => step(cmd::packaging::Install::decode(d)),
        "BuildDeps" => step(cmd::packaging::BuildDeps::decode(d)),
        "Git" => step(cmd::vcs::Git::decode(d)),
        "GitInstall" => step(cmd::vcs::GitInstall::decode(d)),
        "PipConfig" => step(cmd::pip::PipConfig::decode(d)),
        "Py2Install" => step(cmd::pip::Py2Install::decode(d)),
        "Py2Requirements" => step(cmd::pip::Py2Requirements::decode(d)),
        "Py3Install" => step(cmd::pip::Py3Install::decode(d)),
        "Py3Requirements" => step(cmd::pip::Py3Requirements::decode(d)),
        "Tar" => step(cmd::tarcmd::Tar::decode(d)),
        "TarInstall" => step(cmd::tarcmd::TarInstall::decode(d)),
        "Sh" => step(cmd::generic::Sh::decode(d)),
        "Cmd" => step(cmd::generic::Cmd::decode(d)),
        "Env" => step(cmd::generic::Env::decode(d)),
        "Text" => step(cmd::text::Text::decode(d)),
        "Copy" => step(cmd::copy::Copy::decode(d)),
        "Download" => step(cmd::download::Download::decode(d)),
        "EnsureDir" => step(cmd::dirs::EnsureDir::decode(d)),
        "CacheDirs" => step(cmd::dirs::CacheDirs::decode(d)),
        "EmptyDir" => step(cmd::dirs::EmptyDir::decode(d)),
        "Remove" => step(cmd::dirs::Remove::decode(d)),
        "Depends" => step(cmd::generic::Depends::decode(d)),
        "Container" => step(cmd::subcontainer::Container::decode(d)),
        "Build" => step(cmd::subcontainer::Build::decode(d)),
        "SubConfig" => step(cmd::subcontainer::SubConfig::decode(d)),
        "NpmConfig" => step(cmd::npm::NpmConfig::decode(d)),
        "NpmDependencies" => step(cmd::npm::NpmDependencies::decode(d)),
        "NpmInstall" => step(cmd::npm::NpmInstall::decode(d)),
        "GemInstall" => step(cmd::gem::GemInstall::decode(d)),
        "GemBundle" => step(cmd::gem::GemBundle::decode(d)),
        "GemConfig" => step(cmd::gem::GemConfig::decode(d)),
        "ComposerInstall" => step(cmd::composer::ComposerInstall::decode(d)),
        "ComposerDependencies"
        => step(cmd::composer::ComposerDependencies::decode(d)),
        "ComposerConfig" => step(cmd::composer::ComposerConfig::decode(d)),
        step_name => panic!("Step {} is not yet implemented", step_name),
    }
}

impl Decodable for Step {
    fn decode<D: Decoder>(d: &mut D) -> Result<Step, D::Error> {
        // TODO(tailhook) this is just too slow
        //                move it to lazy_static
        let val = builder_validator();
        let options = val.options.iter().map(|&(ref x, _)| &x[..])
            .collect::<Vec<_>>();
        Ok(try!(d.read_enum("BuildStep", |d| {
            d.read_enum_variant(&options, |d, index| {
                decode_step(&options, index, d)
            })
        })))
    }
}
<|endoftext|>


<commit_before>extern crate chroniker;

use chroniker::Timer;

fn main() {
    let timer = Timer::new();

    chroniker::sleep(500);

    println!("Time: {:?}", timer);

    chroniker::sleep(250);

    println!("Time: {:?}", timer);

    chroniker::sleep(250);

    println!("Time: {:?}", timer);

}
<commit_msg>Added comments to the getting_started example<commit_after>extern crate chroniker;

use chroniker::Timer;

//To run this example: cargo run --example getting_started

fn main() {
    //Creates and starts the timer
    let timer = Timer::new();

    //Do some stuff
    chroniker::sleep(250);

    //Print the time it took to run
    println!("Time: {:?}", timer);

    //Do some more operations
    chroniker::sleep(250);

    //Print the results again
    println!("Time: {:?}", timer);

    //Now lets try to reset the results.
    //You can do this by recreating the struct
    //or calling the reset method.
    let mut timer = Timer::new();

    //Do some operations
    chroniker::sleep(250);

    println!("Time: {:?}", timer);

    //Lets reset again
    //Note: Unlike all other functions
    // this requires a mutable timer
    timer.reset();

    //Do some operations
    chroniker::sleep(250);

    println!("Time: {:?}", timer);
}
<|endoftext|>


<commit_before>extern crate config;

use std::collections::HashMap;

fn main() {
    let mut settings = config::Config::default();
    settings
        // Add in `./Settings.toml`
        .merge(config::File::with_name("Settings")).unwrap()
        // Add in settings from the environment (with a prefix of APP)
        // Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key
        .merge(config::Environment::with_prefix("APP")).unwrap();

    // Print out our settings (as a HashMap)
    println!("{:?}",
             settings.deserialize::<HashMap<String, String>>().unwrap());
}
<commit_msg>Update example deprecated method<commit_after>extern crate config;

use std::collections::HashMap;

fn main() {
    let mut settings = config::Config::default();
    settings
        // Add in `./Settings.toml`
        .merge(config::File::with_name("Settings")).unwrap()
        // Add in settings from the environment (with a prefix of APP)
        // Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key
        .merge(config::Environment::with_prefix("APP")).unwrap();

    // Print out our settings (as a HashMap)
    println!("{:?}",
             settings.try_into::<HashMap<String, String>>().unwrap());
}
<|endoftext|>


<commit_before>use alloc::arc::Arc;
use alloc::boxed::Box;
use collections::{BTreeMap, Vec, VecDeque};
use spin::Mutex;

use arch;
use context::file::File;
use context::memory::{Grant, Memory, SharedMemory, Tls};
use scheme::{SchemeNamespace, FileHandle};
use syscall::data::Event;
use sync::{WaitMap, WaitQueue};

/// Unique identifier for a context (i.e. `pid`).
use ::core::sync::atomic::AtomicUsize;
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);

/// The status of a context - used for scheduling
/// See syscall::process::waitpid and the sync module for examples of usage
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Status {
    Runnable,
    Blocked,
    Exited(usize)
}

/// A context, which identifies either a process or a thread
#[derive(Debug)]
pub struct Context {
    /// The ID of this context
    pub id: ContextId,
    /// The ID of the parent context
    pub ppid: ContextId,
    /// The real user id
    pub ruid: u32,
    /// The real group id
    pub rgid: u32,
    /// The real namespace id
    pub rns: SchemeNamespace,
    /// The effective user id
    pub euid: u32,
    /// The effective group id
    pub egid: u32,
    /// The effective namespace id
    pub ens: SchemeNamespace,
    /// Status of context
    pub status: Status,
    /// Context running or not
    pub running: bool,
    /// CPU ID, if locked
    pub cpu_id: Option<usize>,
    /// Context is halting parent
    pub vfork: bool,
    /// Context is being waited on
    pub waitpid: Arc<WaitMap<ContextId, usize>>,
    /// Context should handle pending signals
    pub pending: VecDeque<u8>,
    /// Context should wake up at specified time
    pub wake: Option<(u64, u64)>,
    /// The architecture specific context
    pub arch: arch::context::Context,
    /// Kernel FX - used to store SIMD and FPU registers on context switch
    pub kfx: Option<Box<[u8]>>,
    /// Kernel stack
    pub kstack: Option<Box<[u8]>>,
    /// Executable image
    pub image: Vec<SharedMemory>,
    /// User heap
    pub heap: Option<SharedMemory>,
    /// User stack
    pub stack: Option<Memory>,
    /// User Thread local storage
    pub tls: Option<Tls>,
    /// User grants
    pub grants: Arc<Mutex<Vec<Grant>>>,
    /// The name of the context
    pub name: Arc<Mutex<Vec<u8>>>,
    /// The current working directory
    pub cwd: Arc<Mutex<Vec<u8>>>,
    /// Kernel events
    pub events: Arc<WaitQueue<Event>>,
    /// The process environment
    pub env: Arc<Mutex<BTreeMap<Box<[u8]>, Arc<Mutex<Vec<u8>>>>>>,
    /// The open files in the scheme
    pub files: Arc<Mutex<Vec<Option<File>>>>
}

impl Context {
    pub fn new(id: ContextId) -> Context {
        Context {
            id: id,
            ppid: ContextId::from(0),
            ruid: 0,
            rgid: 0,
            rns: SchemeNamespace::from(0),
            euid: 0,
            egid: 0,
            ens: SchemeNamespace::from(0),
            status: Status::Blocked,
            running: false,
            cpu_id: None,
            vfork: false,
            waitpid: Arc::new(WaitMap::new()),
            pending: VecDeque::new(),
            wake: None,
            arch: arch::context::Context::new(),
            kfx: None,
            kstack: None,
            image: Vec::new(),
            heap: None,
            stack: None,
            tls: None,
            grants: Arc::new(Mutex::new(Vec::new())),
            name: Arc::new(Mutex::new(Vec::new())),
            cwd: Arc::new(Mutex::new(Vec::new())),
            events: Arc::new(WaitQueue::new()),
            env: Arc::new(Mutex::new(BTreeMap::new())),
            files: Arc::new(Mutex::new(Vec::new()))
        }
    }

    /// Make a relative path absolute
    /// Given a cwd of "scheme:/path"
    /// This function will turn "foo" into "scheme:/path/foo"
    /// "/foo" will turn into "scheme:/foo"
    /// "bar:/foo" will be used directly, as it is already absolute
    pub fn canonicalize(&self, path: &[u8]) -> Vec<u8> {
        if path.iter().position(|&b| b == b':').is_none() {
            let cwd = self.cwd.lock();
            if path == b"." {
                cwd.clone()
            } else if path == b".." {
                cwd[..cwd[..cwd.len() - 1]
                                   .iter().rposition(|&b| b == b'/' || b == b':')
                                   .map_or(cwd.len(), |i| i + 1)]
                   .to_vec()
            } else if path.starts_with(b"/") {
                let mut canon = cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec();
                canon.extend_from_slice(&path);
                canon
            } else {
                let mut canon = cwd.clone();
                if ! canon.ends_with(b"/") {
                    canon.push(b'/');
                }
                canon.extend_from_slice(&path);
                // NOTE: assumes the scheme does not include anything like "../" or "./"
                let rparts = canon.split(|&c| c == b'/')
                    .filter(|&part| part != b".")
                    .rev()
                    .scan(0, |nskip, part| {
                        if part == b".." {
                            *nskip += 1;
                            Some(None)
                        } else {
                            if *nskip > 0 {
                                *nskip -= 1;
                                Some(None)
                            } else {
                                Some(Some(part))
                            }
                        }
                    })
                    .filter_map(|x| x)
                    .collect::<Vec<_>>();
                let mut result = rparts
                    .iter()
                    .rev()
                    .fold(Vec::new(), |mut vec, &part| {
                        vec.extend_from_slice(part);
                        vec.push(b'/');
                        vec
                    });
                result.pop(); // remove extra '/'
                result
        } else {
            path.to_vec()
        }
    }

    /// Block the context, and return true if it was runnable before being blocked
    pub fn block(&mut self) -> bool {
        if self.status == Status::Runnable {
            self.status = Status::Blocked;
            true
        } else {
            false
        }
    }

    /// Unblock context, and return true if it was blocked before being marked runnable
    pub fn unblock(&mut self) -> bool {
        if self.status == Status::Blocked {
            self.status = Status::Runnable;
            if let Some(cpu_id) = self.cpu_id {
                if cpu_id != ::cpu_id() {
                    // Send IPI if not on current CPU
                    // TODO: Make this more architecture independent
                    unsafe { arch::device::local_apic::LOCAL_APIC.ipi(cpu_id) };
                }
            }
            true
        } else {
            false
        }
    }

    /// Add a file to the lowest available slot.
    /// Return the file descriptor number or None if no slot was found
    pub fn add_file(&self, file: File) -> Option<FileHandle> {
        let mut files = self.files.lock();
        for (i, mut file_option) in files.iter_mut().enumerate() {
            if file_option.is_none() {
                *file_option = Some(file);
                return Some(FileHandle::from(i));
            }
        }
        let len = files.len();
        if len < super::CONTEXT_MAX_FILES {
            files.push(Some(file));
            Some(FileHandle::from(len))
        } else {
            None
        }
    }

    /// Get a file
    pub fn get_file(&self, i: FileHandle) -> Option<File> {
        let files = self.files.lock();
        if i.into() < files.len() {
            files[i.into()]
        } else {
            None
        }
    }

    /// Insert a file with a specific handle number. This is used by dup2
    /// Return the file descriptor number or None if the slot was not empty, or i was invalid
    pub fn insert_file(&self, i: FileHandle, file: File) -> Option<FileHandle> {
        let mut files = self.files.lock();
        if i.into() < super::CONTEXT_MAX_FILES {
            while i.into() >= files.len() {
                files.push(None);
            }
            if files[i.into()].is_none() {
                files[i.into()] = Some(file);
                Some(i)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Remove a file
    // TODO: adjust files vector to smaller size if possible
    pub fn remove_file(&self, i: FileHandle) -> Option<File> {
        let mut files = self.files.lock();
        if i.into() < files.len() {
            files[i.into()].take()
        } else {
            None
        }
    }
}
<commit_msg>Fix typo and add functionality to more properly handle the parent of the root of the filesystem<commit_after>use alloc::arc::Arc;
use alloc::boxed::Box;
use collections::{BTreeMap, Vec, VecDeque};
use spin::Mutex;

use arch;
use context::file::File;
use context::memory::{Grant, Memory, SharedMemory, Tls};
use scheme::{SchemeNamespace, FileHandle};
use syscall::data::Event;
use sync::{WaitMap, WaitQueue};

/// Unique identifier for a context (i.e. `pid`).
use ::core::sync::atomic::AtomicUsize;
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);

/// The status of a context - used for scheduling
/// See syscall::process::waitpid and the sync module for examples of usage
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Status {
    Runnable,
    Blocked,
    Exited(usize)
}

/// A context, which identifies either a process or a thread
#[derive(Debug)]
pub struct Context {
    /// The ID of this context
    pub id: ContextId,
    /// The ID of the parent context
    pub ppid: ContextId,
    /// The real user id
    pub ruid: u32,
    /// The real group id
    pub rgid: u32,
    /// The real namespace id
    pub rns: SchemeNamespace,
    /// The effective user id
    pub euid: u32,
    /// The effective group id
    pub egid: u32,
    /// The effective namespace id
    pub ens: SchemeNamespace,
    /// Status of context
    pub status: Status,
    /// Context running or not
    pub running: bool,
    /// CPU ID, if locked
    pub cpu_id: Option<usize>,
    /// Context is halting parent
    pub vfork: bool,
    /// Context is being waited on
    pub waitpid: Arc<WaitMap<ContextId, usize>>,
    /// Context should handle pending signals
    pub pending: VecDeque<u8>,
    /// Context should wake up at specified time
    pub wake: Option<(u64, u64)>,
    /// The architecture specific context
    pub arch: arch::context::Context,
    /// Kernel FX - used to store SIMD and FPU registers on context switch
    pub kfx: Option<Box<[u8]>>,
    /// Kernel stack
    pub kstack: Option<Box<[u8]>>,
    /// Executable image
    pub image: Vec<SharedMemory>,
    /// User heap
    pub heap: Option<SharedMemory>,
    /// User stack
    pub stack: Option<Memory>,
    /// User Thread local storage
    pub tls: Option<Tls>,
    /// User grants
    pub grants: Arc<Mutex<Vec<Grant>>>,
    /// The name of the context
    pub name: Arc<Mutex<Vec<u8>>>,
    /// The current working directory
    pub cwd: Arc<Mutex<Vec<u8>>>,
    /// Kernel events
    pub events: Arc<WaitQueue<Event>>,
    /// The process environment
    pub env: Arc<Mutex<BTreeMap<Box<[u8]>, Arc<Mutex<Vec<u8>>>>>>,
    /// The open files in the scheme
    pub files: Arc<Mutex<Vec<Option<File>>>>
}

impl Context {
    pub fn new(id: ContextId) -> Context {
        Context {
            id: id,
            ppid: ContextId::from(0),
            ruid: 0,
            rgid: 0,
            rns: SchemeNamespace::from(0),
            euid: 0,
            egid: 0,
            ens: SchemeNamespace::from(0),
            status: Status::Blocked,
            running: false,
            cpu_id: None,
            vfork: false,
            waitpid: Arc::new(WaitMap::new()),
            pending: VecDeque::new(),
            wake: None,
            arch: arch::context::Context::new(),
            kfx: None,
            kstack: None,
            image: Vec::new(),
            heap: None,
            stack: None,
            tls: None,
            grants: Arc::new(Mutex::new(Vec::new())),
            name: Arc::new(Mutex::new(Vec::new())),
            cwd: Arc::new(Mutex::new(Vec::new())),
            events: Arc::new(WaitQueue::new()),
            env: Arc::new(Mutex::new(BTreeMap::new())),
            files: Arc::new(Mutex::new(Vec::new()))
        }
    }

    /// Make a relative path absolute
    /// Given a cwd of "scheme:/path"
    /// This function will turn "foo" into "scheme:/path/foo"
    /// "/foo" will turn into "scheme:/foo"
    /// "bar:/foo" will be used directly, as it is already absolute
    pub fn canonicalize(&self, path: &[u8]) -> Vec<u8> {
        if path.iter().position(|&b| b == b':').is_none() {
            let cwd = self.cwd.lock();
            if path == b"." {
                cwd.clone()
            } else if path == b".." {
                cwd[..cwd[..cwd.len() - 1]
                                   .iter().rposition(|&b| b == b'/' || b == b':')
                                   .map_or(cwd.len(), |i| i + 1)]
                   .to_vec()
            } else if path.starts_with(b"/") {
                let mut canon = cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec();
                canon.extend_from_slice(&path);
                canon
            } else {
                let mut canon = cwd.clone();
                if ! canon.ends_with(b"/") {
                    canon.push(b'/');
                }
                canon.extend_from_slice(&path);
                // NOTE: assumes the scheme does not include anything like "../" or "./"
                let mut result = {
                    let rparts = canon.split(|&c| c == b'/')
                        .filter(|&part| part != b".")
                        .rev()
                        .scan(0, |nskip, part| {
                            if part == b".." {
                                *nskip += 1;
                                Some(None)
                            } else {
                                if *nskip > 0 {
                                    *nskip -= 1;
                                    Some(None)
                                } else {
                                    Some(Some(part))
                                }
                            }
                        })
                        .filter_map(|x| x)
                        .collect::<Vec<_>>();
                    rparts
                        .iter()
                        .rev()
                        .fold(Vec::new(), |mut vec, &part| {
                            vec.extend_from_slice(part);
                            vec.push(b'/');
                            vec
                        })
                };
                result.pop(); // remove extra '/'
                if result.len() == 0 {
                    // replace with the root of the schema if it's empty
                    let pos = canon.iter()
                                   .position(|&b| b == b':')
                                   .map_or(canon.len(), |p| p + 1);
                    canon.truncate(pos);
                    canon
                } else {
                    result
                }
            }
        } else {
            path.to_vec()
        }
    }

    /// Block the context, and return true if it was runnable before being blocked
    pub fn block(&mut self) -> bool {
        if self.status == Status::Runnable {
            self.status = Status::Blocked;
            true
        } else {
            false
        }
    }

    /// Unblock context, and return true if it was blocked before being marked runnable
    pub fn unblock(&mut self) -> bool {
        if self.status == Status::Blocked {
            self.status = Status::Runnable;
            if let Some(cpu_id) = self.cpu_id {
                if cpu_id != ::cpu_id() {
                    // Send IPI if not on current CPU
                    // TODO: Make this more architecture independent
                    unsafe { arch::device::local_apic::LOCAL_APIC.ipi(cpu_id) };
                }
            }
            true
        } else {
            false
        }
    }

    /// Add a file to the lowest available slot.
    /// Return the file descriptor number or None if no slot was found
    pub fn add_file(&self, file: File) -> Option<FileHandle> {
        let mut files = self.files.lock();
        for (i, mut file_option) in files.iter_mut().enumerate() {
            if file_option.is_none() {
                *file_option = Some(file);
                return Some(FileHandle::from(i));
            }
        }
        let len = files.len();
        if len < super::CONTEXT_MAX_FILES {
            files.push(Some(file));
            Some(FileHandle::from(len))
        } else {
            None
        }
    }

    /// Get a file
    pub fn get_file(&self, i: FileHandle) -> Option<File> {
        let files = self.files.lock();
        if i.into() < files.len() {
            files[i.into()]
        } else {
            None
        }
    }

    /// Insert a file with a specific handle number. This is used by dup2
    /// Return the file descriptor number or None if the slot was not empty, or i was invalid
    pub fn insert_file(&self, i: FileHandle, file: File) -> Option<FileHandle> {
        let mut files = self.files.lock();
        if i.into() < super::CONTEXT_MAX_FILES {
            while i.into() >= files.len() {
                files.push(None);
            }
            if files[i.into()].is_none() {
                files[i.into()] = Some(file);
                Some(i)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Remove a file
    // TODO: adjust files vector to smaller size if possible
    pub fn remove_file(&self, i: FileHandle) -> Option<File> {
        let mut files = self.files.lock();
        if i.into() < files.len() {
            files[i.into()].take()
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>//! An asynchronous RabbitMQ client for proxy engine
//!

use std::io;
use std::sync::Arc;

use amq_protocol::uri::AMQPUri;
use futures::future::Future;
use futures::IntoFuture;
use lapin_futures_rustls::lapin::channel::{Channel, ConfirmSelectOptions};
use lapin_futures_rustls::lapin::client::{Client, ConnectionOptions};
use log::error;
use tokio::executor::spawn;
use tokio_tcp::TcpStream;

use crate::rabbitmq::utils::get_address_to_rabbitmq;

/// Alias for the lapin client with TLS.
pub type LapinClient = Client<TcpStream>;
/// Alias for the lapin channel.
pub type LapinChannel = Channel<TcpStream>;

/// A future-based asynchronous RabbitMQ client.
pub struct RabbitMQClient {
    client: Arc<LapinClient>
}

impl RabbitMQClient {
    /// Initializes the inner fields of RabbitMQ client for future usage.
    pub fn connect(uri: &AMQPUri) -> impl Future<Item=Self, Error=io::Error> + Sync + Send + 'static {
        let address = get_address_to_rabbitmq(uri);
        let uri_inner = uri.clone();

        TcpStream::connect(&address)
            .and_then(|stream| Client::connect(stream, ConnectionOptions::from_uri(uri_inner)))
            .and_then(move |(client, heartbeat)| {
                spawn(heartbeat.map_err(|err| error!("Heartbeat error: {:?}", err)))
                    .into_future()
                    .map(|_| RabbitMQClient { client: Arc::new(client) })
                    .map_err(|error| {
                        error!("Occurred an error during spawning heartbeat future: {:?}", error);
                        io::Error::new(io::ErrorKind::Other, "Spawn error.")
                    })
            })
    }

    /// Returns a lapin channel as future, based on the lapin client instance.
    pub fn get_channel(&self) -> impl Future<Item=LapinChannel, Error=io::Error> + Sync + Send + 'static {
        let client = self.client.clone();
        client.create_confirm_channel(ConfirmSelectOptions::default())
    }
}
<commit_msg>Fixed RabbitMQ client structure after changes in lapin-futures<commit_after>//! An asynchronous RabbitMQ client for proxy engine
//!

use std::sync::Arc;

use amq_protocol::uri::AMQPUri;
use failure::Error;
use futures::future::Future;
use futures::IntoFuture;
use lapin_futures::error::{Error as LapinError};
use lapin_futures_rustls::lapin::channel::{Channel, ConfirmSelectOptions};
use lapin_futures_rustls::lapin::client::{Client, ConnectionOptions};
use log::error;
use tokio::executor::spawn;
use tokio::net::TcpStream;

use crate::rabbitmq::utils::get_address_to_rabbitmq;

/// Alias for the lapin client with TLS.
pub type LapinClient = Client<TcpStream>;
/// Alias for the lapin channel.
pub type LapinChannel = Channel<TcpStream>;

/// A future-based asynchronous RabbitMQ client.
pub struct RabbitMQClient {
    client: Arc<LapinClient>
}

impl RabbitMQClient {
    /// Initializes the inner fields of RabbitMQ client for future usage.
    pub fn connect(uri: &AMQPUri) -> impl Future<Item=Self, Error=Error> + Sync + Send + 'static {
        let address = get_address_to_rabbitmq(uri);
        let uri_inner = uri.clone();

        TcpStream::connect(&address)
            .map_err(Error::from)
            .and_then(|stream| {
                Client::connect(stream, ConnectionOptions::from_uri(uri_inner))
                    .map_err(Error::from)
            })
            .and_then(|(client, heartbeat)| {
                spawn(heartbeat.map_err(|err| error!("Heartbeat error: {:?}", err)))
                    .into_future()
                    .map(|_| RabbitMQClient { client: Arc::new(client) })
                    .map_err(|error| {
                        error!("Occurred an error during spawning heartbeat future: {:?}", error);
                        error
                    })
            })
    }

    /// Returns a lapin channel as future, based on the lapin client instance.
    pub fn get_channel(&self) -> impl Future<Item=LapinChannel, Error=LapinError> + Sync + Send + 'static {
        let client = self.client.clone();
        client.create_confirm_channel(ConfirmSelectOptions::default())
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

macro_rules! mk_iterator_mod {
    {
        modname   = $modname:ident,
        itername  = $itername:ident,
        iteryield = $yield:ty,
        extname   = $extname:ident,
        extfnname = $extfnname:ident,
        fun       = $fun:expr
    } => {
        pub mod $modname {
            use storeid::StoreId;
            #[allow(unused_imports)]
            use store::FileLockEntry;
            use store::Store;
            use error::Result;

            pub struct $itername<'a>(Box<Iterator<Item = StoreId>>, &'a Store);

            impl<'a> Iterator for $itername<'a> {
                type Item = Result<$yield>;

                fn next(&mut self) -> Option<Self::Item> {
                    self.0.next().map(|id| $fun(id, self.1))
                }
            }

            pub trait $extname<'a> {
                fn $extfnname(self, store: &'a Store) -> $itername<'a>;
            }

            impl<'a, I> $extname<'a> for I
                where I: Iterator<Item = StoreId> + 'static
            {
                fn $extfnname(self, store: &'a Store) -> $itername<'a> {
                    $itername(Box::new(self), store)
                }
            }

        }
    }
}

mk_iterator_mod! {
    modname   = create,
    itername  = StoreCreateIterator,
    iteryield = FileLockEntry<'a>,
    extname   = StoreIdCreateIteratorExtension,
    extfnname = into_create_iter,
    fun       = |id: StoreId, store: &'a Store| store.create(id)
}

mk_iterator_mod! {
    modname   = delete,
    itername  = StoreDeleteIterator,
    iteryield = (),
    extname   = StoreIdDeleteIteratorExtension,
    extfnname = into_delete_iter,
    fun       = |id: StoreId, store: &'a Store| store.delete(id)
}

mk_iterator_mod! {
    modname   = get,
    itername  = StoreGetIterator,
    iteryield = Option<FileLockEntry<'a>>,
    extname   = StoreIdGetIteratorExtension,
    extfnname = into_get_iter,
    fun       = |id: StoreId, store: &'a Store| store.get(id)
}

mk_iterator_mod! {
    modname   = retrieve,
    itername  = StoreRetrieveIterator,
    iteryield = FileLockEntry<'a>,
    extname   = StoreIdRetrieveIteratorExtension,
    extfnname = into_retrieve_iter,
    fun       = |id: StoreId, store: &'a Store| store.retrieve(id)
}

<commit_msg>Add iterator extension for iterators over Result<T, E><commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

macro_rules! mk_iterator {
    {
        modname   = $modname:ident,
        itername  = $itername:ident,
        iteryield = $yield:ty,
        extname   = $extname:ident,
        extfnname = $extfnname:ident,
        fun       = $fun:expr
    } => {
        use storeid::StoreId;
        #[allow(unused_imports)]
        use store::FileLockEntry;
        use store::Store;
        use error::Result;

        pub struct $itername<'a>(Box<Iterator<Item = StoreId>>, &'a Store);

        impl<'a> Iterator for $itername<'a> {
            type Item = Result<$yield>;

            fn next(&mut self) -> Option<Self::Item> {
                self.0.next().map(|id| $fun(id, self.1))
            }
        }

        pub trait $extname<'a> {
            fn $extfnname(self, store: &'a Store) -> $itername<'a>;
        }

        impl<'a, I> $extname<'a> for I
            where I: Iterator<Item = StoreId> + 'static
        {
            fn $extfnname(self, store: &'a Store) -> $itername<'a> {
                $itername(Box::new(self), store)
            }
        }
    }
}

use error::StoreError;

pub enum ExtensionError<E> {
    Forwarded(E),
    StoreError(StoreError)
}

macro_rules! mk_iterator_mod {
    {
        modname        = $modname:ident,
        itername       = $itername:ident,
        iteryield      = $yield:ty,
        extname        = $extname:ident,
        extfnname      = $extfnname:ident,
        fun            = $fun:expr,
        resultitername = $resultitername:ident,
        resultextname  = $resultextname:ident
    } => {
        pub mod $modname {
            mk_iterator! {
                modname   = $modname,
                itername  = $itername,
                iteryield = $yield,
                extname   = $extname,
                extfnname = $extfnname,
                fun       = $fun
            }

            use std::result::Result as RResult;

            pub struct $resultitername<'a, I>(I, &'a Store);

            impl<'a, I, E> Iterator for $resultitername<'a, I>
                where I: Iterator<Item = RResult<StoreId, E>>
            {
                type Item = RResult<$yield, $crate::iter::ExtensionError<E>>;

                fn next(&mut self) -> Option<Self::Item> {
                    match self.0.next() {
                        Some(Ok(sid)) => Some($fun(sid, self.1).map_err($crate::iter::ExtensionError::StoreError)),
                        Some(Err(e))  => Some(Err($crate::iter::ExtensionError::Forwarded(e))),
                        None => None,
                    }
                }
            }

            pub trait $resultextname<'a> : Iterator {
                fn $extfnname(self, store: &'a Store) -> $resultitername<'a, Self>
                    where Self: Sized
                {
                    $resultitername(self, store)
                }
            }

            impl<'a, I> $resultextname<'a> for I
                where I: Iterator
            { /* empty */ }
        }
    };

    {
        modname   = $modname:ident,
        itername  = $itername:ident,
        iteryield = $yield:ty,
        extname   = $extname:ident,
        extfnname = $extfnname:ident,
        fun       = $fun:expr
    } => {
        pub mod $modname {
            mk_iterator! {
                modname   = $modname,
                itername  = $itername,
                iteryield = $yield,
                extname   = $extname,
                extfnname = $extfnname,
                fun       = $fun
            }
        }
    }
}

mk_iterator_mod! {
    modname   = create,
    itername  = StoreCreateIterator,
    iteryield = FileLockEntry<'a>,
    extname   = StoreIdCreateIteratorExtension,
    extfnname = into_create_iter,
    fun       = |id: StoreId, store: &'a Store| store.create(id),
    resultitername = StoreCreateResultIterator,
    resultextname  = StoreIdCreateResultIteratorExtension
}

mk_iterator_mod! {
    modname   = delete,
    itername  = StoreDeleteIterator,
    iteryield = (),
    extname   = StoreIdDeleteIteratorExtension,
    extfnname = into_delete_iter,
    fun       = |id: StoreId, store: &'a Store| store.delete(id),
    resultitername = StoreDeleteResultIterator,
    resultextname  = StoreIdDeleteResultIteratorExtension
}

mk_iterator_mod! {
    modname   = get,
    itername  = StoreGetIterator,
    iteryield = Option<FileLockEntry<'a>>,
    extname   = StoreIdGetIteratorExtension,
    extfnname = into_get_iter,
    fun       = |id: StoreId, store: &'a Store| store.get(id),
    resultitername = StoreGetResultIterator,
    resultextname  = StoreIdGetResultIteratorExtension
}

mk_iterator_mod! {
    modname   = retrieve,
    itername  = StoreRetrieveIterator,
    iteryield = FileLockEntry<'a>,
    extname   = StoreIdRetrieveIteratorExtension,
    extfnname = into_retrieve_iter,
    fun       = |id: StoreId, store: &'a Store| store.retrieve(id),
    resultitername = StoreRetrieveResultIterator,
    resultextname  = StoreIdRetrieveResultIteratorExtension
}

#[cfg(test)]
mod compile_test {

    // This module contains code to check whether this actually compiles the way we would like it to
    // compile

    use store::Store;
    use storeid::StoreId;

    #[allow(dead_code)]
    fn store() -> Store {
        unimplemented!()
    }

    #[allow(dead_code)]
    fn test_compile_get() {
        use super::get::StoreIdGetIteratorExtension;

        let store = store();
        let _ = store
            .entries()
            .unwrap()
            .into_get_iter(&store);
    }

    #[allow(dead_code)]
    fn test_compile_get_result() {
        use super::get::StoreIdGetResultIteratorExtension;

        fn to_result(e: StoreId) -> Result<StoreId, ()> {
            Ok(e)
        }

        let store = store();
        let _ = store
            .entries()
            .unwrap()
            .map(to_result)
            .into_get_iter(&store);
    }
}

<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    if let Some(path) = env::args().nth(1) {
        let mut contents = String::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_string(&mut contents) {
                    Ok(_) => println!("Would read and eval here."),
                    Err(_) => println!("Found the file but failed to read it."),
                }
            }
            Err(_) => println!("Failed to open the file for reading."),
        };
    } else {
        println!("Please provide a path to some brainfuck source as the first argument.")
    }
}

mod brainfuck {
    pub type Pointer = usize;

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum Command {
        IncrementPointer,
        DecrementPointer,
        IncrementValue,
        DecrementValue,
        OutputValue,
        InputValue,
        ForwardsTo(Pointer),
        BackwardsTo(Pointer),
    }

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum ReadResult {
        Program(Vec<Command>),
        UnmatchedJump,
    }

    pub fn read(source: &str) -> ReadResult {
        let mut loops: Vec<usize> = vec![];
        let mut loop_closes: usize = 0;
        let mut position: usize = 0;
        let program: Vec<Command> = source
            .chars()
            .filter_map(|token| {
                let command = match token {
                    '>' => Some(Command::IncrementPointer),
                    '<' => Some(Command::DecrementPointer),
                    '+' => Some(Command::IncrementValue),
                    '-' => Some(Command::DecrementValue),
                    '.' => Some(Command::OutputValue),
                    ',' => Some(Command::InputValue),
                    '[' => {
                        loops.push(position);
                        Some(Command::BackwardsTo(position))
                    }
                    ']' => {
                        loop_closes += 1;
                        Some(Command::ForwardsTo(position))
                    }
                    _ => None,
                };

                if command.is_some() {
                    position += 1;
                }

                command
            })
            .collect();

        if loops.len() != loop_closes {
            ReadResult::UnmatchedJump
        } else {
            ReadResult::Program(program)
        }
    }

    // pub fn eval(program: Vec<Command>) {
    // }
}

#[cfg(test)]
mod tests {
    use brainfuck::*;
    use brainfuck::Command::*;
    use brainfuck::ReadResult::*;

    #[test]
    fn read_empty() {
        let source = "";
        let expected = Program(vec![]);
        let actual = read(source);
        assert_eq!(expected, actual);
    }

    #[test]
    fn read_simple() {
        let source = "+>-<.,<.-+>,";
        let expected = Program(vec![IncrementValue,
                                    IncrementPointer,
                                    DecrementValue,
                                    DecrementPointer,
                                    OutputValue,
                                    InputValue,
                                    DecrementPointer,
                                    OutputValue,
                                    DecrementValue,
                                    IncrementValue,
                                    IncrementPointer,
                                    InputValue]);
        let actual = read(source);
        assert_eq!(expected, actual);
    }

    #[test]
    fn read_garbage() {
        let source = ",.+lol,hey.>there<";
        let expected = Program(vec![InputValue,
                                    OutputValue,
                                    IncrementValue,
                                    InputValue,
                                    OutputValue,
                                    IncrementPointer,
                                    DecrementPointer]);
        let actual = read(source);
        assert_eq!(expected, actual);
    }

    #[test]
    fn read_loop() {
        let source = "[->+<]";
        let expected = Program(vec![ForwardsTo(5),
                                    DecrementValue,
                                    IncrementPointer,
                                    IncrementValue,
                                    DecrementPointer,
                                    BackwardsTo(0)]);
        let actual = read(source);
        assert_eq!(expected, actual);
    }

    #[test]
    fn read_bad_loop() {
        let source = "[,.[,.>+-][./.[]]";
        let expected = UnmatchedJump;
        let actual = read(source);
        assert_eq!(expected, actual);
    }
}
<commit_msg>Invert logic, easier to read<commit_after>use std::env;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    if let Some(path) = env::args().nth(1) {
        let mut contents = String::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_string(&mut contents) {
                    Ok(_) => println!("Would read and eval here."),
                    Err(_) => println!("Found the file but failed to read it."),
                }
            }
            Err(_) => println!("Failed to open the file for reading."),
        };
    } else {
        println!("Please provide a path to some brainfuck source as the first argument.")
    }
}

mod brainfuck {
    pub type Pointer = usize;

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum Command {
        IncrementPointer,
        DecrementPointer,
        IncrementValue,
        DecrementValue,
        OutputValue,
        InputValue,
        ForwardsTo(Pointer),
        BackwardsTo(Pointer),
    }

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum ReadResult {
        Program(Vec<Command>),
        UnmatchedJump,
    }

    pub fn read(source: &str) -> ReadResult {
        let mut loops: Vec<usize> = vec![];
        let mut loop_closes: usize = 0;
        let mut position: usize = 0;
        let program: Vec<Command> = source
            .chars()
            .filter_map(|token| {
                let command = match token {
                    '>' => Some(Command::IncrementPointer),
                    '<' => Some(Command::DecrementPointer),
                    '+' => Some(Command::IncrementValue),
                    '-' => Some(Command::DecrementValue),
                    '.' => Some(Command::OutputValue),
                    ',' => Some(Command::InputValue),
                    '[' => {
                        loops.push(position);
                        Some(Command::BackwardsTo(position))
                    }
                    ']' => {
                        loop_closes += 1;
                        Some(Command::ForwardsTo(position))
                    }
                    _ => None,
                };

                if command.is_some() {
                    position += 1;
                }

                command
            })
            .collect();

        if loops.len() == loop_closes {
            ReadResult::Program(program)
        } else {
            ReadResult::UnmatchedJump
        }
    }

    // pub fn eval(program: Vec<Command>) {
    // }
}

#[cfg(test)]
mod tests {
    use brainfuck::*;
    use brainfuck::Command::*;
    use brainfuck::ReadResult::*;

    #[test]
    fn read_empty() {
        let source = "";
        let expected = Program(vec![]);
        let actual = read(source);
        assert_eq!(expected, actual);
    }

    #[test]
    fn read_simple() {
        let source = "+>-<.,<.-+>,";
        let expected = Program(vec![IncrementValue,
                                    IncrementPointer,
                                    DecrementValue,
                                    DecrementPointer,
                                    OutputValue,
                                    InputValue,
                                    DecrementPointer,
                                    OutputValue,
                                    DecrementValue,
                                    IncrementValue,
                                    IncrementPointer,
                                    InputValue]);
        let actual = read(source);
        assert_eq!(expected, actual);
    }

    #[test]
    fn read_garbage() {
        let source = ",.+lol,hey.>there<";
        let expected = Program(vec![InputValue,
                                    OutputValue,
                                    IncrementValue,
                                    InputValue,
                                    OutputValue,
                                    IncrementPointer,
                                    DecrementPointer]);
        let actual = read(source);
        assert_eq!(expected, actual);
    }

    #[test]
    fn read_loop() {
        let source = "[->+<]";
        let expected = Program(vec![ForwardsTo(5),
                                    DecrementValue,
                                    IncrementPointer,
                                    IncrementValue,
                                    DecrementPointer,
                                    BackwardsTo(0)]);
        let actual = read(source);
        assert_eq!(expected, actual);
    }

    #[test]
    fn read_bad_loop() {
        let source = "[,.[,.>+-][./.[]]";
        let expected = UnmatchedJump;
        let actual = read(source);
        assert_eq!(expected, actual);
    }
}
<|endoftext|>