<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// The classification code for the x86_64 ABI is taken from the clay language
// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp

#![allow(non_uppercase_pattern_statics)]

use llvm;
use llvm::{Integer, Pointer, Float, Double};
use llvm::{Struct, Array, Attribute};
use llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
use middle::trans::cabi::{ArgType, FnType};
use middle::trans::context::CrateContext;
use middle::trans::type_::Type;

use std::cmp;

#[deriving(Clone, PartialEq)]
enum RegClass {
    NoClass,
    Int,
    SSEFs,
    SSEFv,
    SSEDs,
    SSEDv,
    SSEInt,
    SSEUp,
    X87,
    X87Up,
    ComplexX87,
    Memory
}

trait TypeMethods {
    fn is_reg_ty(&self) -> bool;
}

impl TypeMethods for Type {
    fn is_reg_ty(&self) -> bool {
        match self.kind() {
            Integer | Pointer | Float | Double => true,
            _ => false
        }
    }
}

impl RegClass {
    fn is_sse(&self) -> bool {
        match *self {
            SSEFs | SSEFv | SSEDs | SSEDv => true,
            _ => false
        }
    }
}

trait ClassList {
    fn is_pass_byval(&self) -> bool;
    fn is_ret_bysret(&self) -> bool;
}

impl<'a> ClassList for &'a [RegClass] {
    fn is_pass_byval(&self) -> bool {
        if self.len() == 0 { return false; }

        let class = self[0];
           class == Memory
        || class == X87
        || class == ComplexX87
    }

    fn is_ret_bysret(&self) -> bool {
        if self.len() == 0 { return false; }

        self[0] == Memory
    }
}

fn classify_ty(ty: Type) -> Vec<RegClass> {
    fn align(off: uint, ty: Type) -> uint {
        let a = ty_align(ty);
        return (off + a - 1u) / a * a;
    }

    fn ty_align(ty: Type) -> uint {
        match ty.kind() {
            Integer => {
                unsafe {
                    ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
                }
            }
            Pointer => 8,
            Float => 4,
            Double => 8,
            Struct => {
              if ty.is_packed() {
                1
              } else {
                let str_tys = ty.field_types();
                str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
              }
            }
            Array => {
                let elt = ty.element_type();
                ty_align(elt)
            }
            _ => fail!("ty_size: unhandled type")
        }
    }

    fn ty_size(ty: Type) -> uint {
        match ty.kind() {
            Integer => {
                unsafe {
                    ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
                }
            }
            Pointer => 8,
            Float => 4,
            Double => 8,
            Struct => {
                let str_tys = ty.field_types();
                if ty.is_packed() {
                    str_tys.iter().fold(0, |s, t| s + ty_size(*t))
                } else {
                    let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
                    align(size, ty)
                }
            }
            Array => {
                let len = ty.array_length();
                let elt = ty.element_type();
                let eltsz = ty_size(elt);
                len * eltsz
            }
            _ => fail!("ty_size: unhandled type")
        }
    }

    fn all_mem(cls: &mut [RegClass]) {
        for elt in cls.mut_iter() {
            *elt = Memory;
        }
    }

    fn unify(cls: &mut [RegClass],
             i: uint,
             newv: RegClass) {
        if cls[i] == newv {
            return;
        } else if cls[i] == NoClass {
            cls[i] = newv;
        } else if newv == NoClass {
            return;
        } else if cls[i] == Memory || newv == Memory {
            cls[i] = Memory;
        } else if cls[i] == Int || newv == Int {
            cls[i] = Int;
        } else if cls[i] == X87 ||
                  cls[i] == X87Up ||
                  cls[i] == ComplexX87 ||
                  newv == X87 ||
                  newv == X87Up ||
                  newv == ComplexX87 {
            cls[i] = Memory;
        } else {
            cls[i] = newv;
        }
    }

    fn classify_struct(tys: &[Type],
                       cls: &mut [RegClass], i: uint,
                       off: uint) {
        let mut field_off = off;
        for ty in tys.iter() {
            field_off = align(field_off, *ty);
            classify(*ty, cls, i, field_off);
            field_off += ty_size(*ty);
        }
    }

    fn classify(ty: Type,
                cls: &mut [RegClass], ix: uint,
                off: uint) {
        let t_align = ty_align(ty);
        let t_size = ty_size(ty);

        let misalign = off % t_align;
        if misalign != 0u {
            let mut i = off / 8u;
            let e = (off + t_size + 7u) / 8u;
            while i < e {
                unify(cls, ix + i, Memory);
                i += 1u;
            }
            return;
        }

        match ty.kind() {
            Integer |
            Pointer => {
                unify(cls, ix + off / 8u, Int);
            }
            Float => {
                if off % 8u == 4u {
                    unify(cls, ix + off / 8u, SSEFv);
                } else {
                    unify(cls, ix + off / 8u, SSEFs);
                }
            }
            Double => {
                unify(cls, ix + off / 8u, SSEDs);
            }
            Struct => {
                classify_struct(ty.field_types().as_slice(), cls, ix, off);
            }
            Array => {
                let len = ty.array_length();
                let elt = ty.element_type();
                let eltsz = ty_size(elt);
                let mut i = 0u;
                while i < len {
                    classify(elt, cls, ix, off + i * eltsz);
                    i += 1u;
                }
            }
            _ => fail!("classify: unhandled type")
        }
    }

    fn fixup(ty: Type, cls: &mut [RegClass]) {
        let mut i = 0u;
        let ty_kind = ty.kind();
        let e = cls.len();
        if cls.len() > 2u && (ty_kind == Struct || ty_kind == Array) {
            if cls[i].is_sse() {
                i += 1u;
                while i < e {
                    if cls[i] != SSEUp {
                        all_mem(cls);
                        return;
                    }
                    i += 1u;
                }
            } else {
                all_mem(cls);
                return
            }
        } else {
            while i < e {
                if cls[i] == Memory {
                    all_mem(cls);
                    return;
                }
                if cls[i] == X87Up {
                    // for darwin
                    // cls[i] = SSEDs;
                    all_mem(cls);
                    return;
                }
                if cls[i] == SSEUp {
                    cls[i] = SSEDv;
                } else if cls[i].is_sse() {
                    i += 1;
                    while i != e && cls[i] == SSEUp { i += 1u; }
                } else if cls[i] == X87 {
                    i += 1;
                    while i != e && cls[i] == X87Up { i += 1u; }
                } else {
                    i += 1;
                }
            }
        }
    }

    let words = (ty_size(ty) + 7) / 8;
    let mut cls = Vec::from_elem(words, NoClass);
    if words > 4 {
        all_mem(cls.as_mut_slice());
        return cls;
    }
    classify(ty, cls.as_mut_slice(), 0, 0);
    fixup(ty, cls.as_mut_slice());
    return cls;
}

fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
    fn llvec_len(cls: &[RegClass]) -> uint {
        let mut len = 1u;
        for c in cls.iter() {
            if *c != SSEUp {
                break;
            }
            len += 1u;
        }
        return len;
    }

    let mut tys = Vec::new();
    let mut i = 0u;
    let e = cls.len();
    while i < e {
        match cls[i] {
            Int => {
                tys.push(Type::i64(ccx));
            }
            SSEFv => {
                let vec_len = llvec_len(cls.tailn(i + 1u));
                let vec_ty = Type::vector(&Type::f32(ccx), (vec_len * 2u) as u64);
                tys.push(vec_ty);
                i += vec_len;
                continue;
            }
            SSEFs => {
                tys.push(Type::f32(ccx));
            }
            SSEDs => {
                tys.push(Type::f64(ccx));
            }
            _ => fail!("llregtype: unhandled class")
        }
        i += 1u;
    }
    return Type::struct_(ccx, tys.as_slice(), false);
}

pub fn compute_abi_info(ccx: &CrateContext,
                        atys: &[Type],
                        rty: Type,
                        ret_def: bool) -> FnType {
    fn x86_64_ty(ccx: &CrateContext,
                 ty: Type,
                 is_mem_cls: |cls: &[RegClass]| -> bool,
                 ind_attr: Attribute)
                 -> ArgType {
        if !ty.is_reg_ty() {
            let cls = classify_ty(ty);
            if is_mem_cls(cls.as_slice()) {
                ArgType::indirect(ty, Some(ind_attr))
            } else {
                ArgType::direct(ty,
                                Some(llreg_ty(ccx, cls.as_slice())),
                                None,
                                None)
            }
        } else {
            let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
            ArgType::direct(ty, None, None, attr)
        }
    }

    let mut arg_tys = Vec::new();
    for t in atys.iter() {
        let ty = x86_64_ty(ccx, *t, |cls| cls.is_pass_byval(), ByValAttribute);
        arg_tys.push(ty);
    }

    let ret_ty = if ret_def {
        x86_64_ty(ccx, rty, |cls| cls.is_ret_bysret(), StructRetAttribute)
    } else {
        ArgType::direct(Type::void(ccx), None, None, None)
    };

    return FnType {
        arg_tys: arg_tys,
        ret_ty: ret_ty,
    };
}
<commit_msg>librustc: Fix field offsets for packed structs.<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// The classification code for the x86_64 ABI is taken from the clay language
// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp

#![allow(non_uppercase_pattern_statics)]

use llvm;
use llvm::{Integer, Pointer, Float, Double};
use llvm::{Struct, Array, Attribute};
use llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
use middle::trans::cabi::{ArgType, FnType};
use middle::trans::context::CrateContext;
use middle::trans::type_::Type;

use std::cmp;

#[deriving(Clone, PartialEq)]
enum RegClass {
    NoClass,
    Int,
    SSEFs,
    SSEFv,
    SSEDs,
    SSEDv,
    SSEInt,
    SSEUp,
    X87,
    X87Up,
    ComplexX87,
    Memory
}

trait TypeMethods {
    fn is_reg_ty(&self) -> bool;
}

impl TypeMethods for Type {
    fn is_reg_ty(&self) -> bool {
        match self.kind() {
            Integer | Pointer | Float | Double => true,
            _ => false
        }
    }
}

impl RegClass {
    fn is_sse(&self) -> bool {
        match *self {
            SSEFs | SSEFv | SSEDs | SSEDv => true,
            _ => false
        }
    }
}

trait ClassList {
    fn is_pass_byval(&self) -> bool;
    fn is_ret_bysret(&self) -> bool;
}

impl<'a> ClassList for &'a [RegClass] {
    fn is_pass_byval(&self) -> bool {
        if self.len() == 0 { return false; }

        let class = self[0];
           class == Memory
        || class == X87
        || class == ComplexX87
    }

    fn is_ret_bysret(&self) -> bool {
        if self.len() == 0 { return false; }

        self[0] == Memory
    }
}

fn classify_ty(ty: Type) -> Vec<RegClass> {
    fn align(off: uint, ty: Type) -> uint {
        let a = ty_align(ty);
        return (off + a - 1u) / a * a;
    }

    fn ty_align(ty: Type) -> uint {
        match ty.kind() {
            Integer => {
                unsafe {
                    ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
                }
            }
            Pointer => 8,
            Float => 4,
            Double => 8,
            Struct => {
              if ty.is_packed() {
                1
              } else {
                let str_tys = ty.field_types();
                str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
              }
            }
            Array => {
                let elt = ty.element_type();
                ty_align(elt)
            }
            _ => fail!("ty_size: unhandled type")
        }
    }

    fn ty_size(ty: Type) -> uint {
        match ty.kind() {
            Integer => {
                unsafe {
                    ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
                }
            }
            Pointer => 8,
            Float => 4,
            Double => 8,
            Struct => {
                let str_tys = ty.field_types();
                if ty.is_packed() {
                    str_tys.iter().fold(0, |s, t| s + ty_size(*t))
                } else {
                    let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
                    align(size, ty)
                }
            }
            Array => {
                let len = ty.array_length();
                let elt = ty.element_type();
                let eltsz = ty_size(elt);
                len * eltsz
            }
            _ => fail!("ty_size: unhandled type")
        }
    }

    fn all_mem(cls: &mut [RegClass]) {
        for elt in cls.mut_iter() {
            *elt = Memory;
        }
    }

    fn unify(cls: &mut [RegClass],
             i: uint,
             newv: RegClass) {
        if cls[i] == newv {
            return;
        } else if cls[i] == NoClass {
            cls[i] = newv;
        } else if newv == NoClass {
            return;
        } else if cls[i] == Memory || newv == Memory {
            cls[i] = Memory;
        } else if cls[i] == Int || newv == Int {
            cls[i] = Int;
        } else if cls[i] == X87 ||
                  cls[i] == X87Up ||
                  cls[i] == ComplexX87 ||
                  newv == X87 ||
                  newv == X87Up ||
                  newv == ComplexX87 {
            cls[i] = Memory;
        } else {
            cls[i] = newv;
        }
    }

    fn classify_struct(tys: &[Type],
                       cls: &mut [RegClass],
                       i: uint,
                       off: uint,
                       packed: bool) {
        let mut field_off = off;
        for ty in tys.iter() {
            if !packed {
                field_off = align(field_off, *ty);
            }
            classify(*ty, cls, i, field_off);
            field_off += ty_size(*ty);
        }
    }

    fn classify(ty: Type,
                cls: &mut [RegClass], ix: uint,
                off: uint) {
        let t_align = ty_align(ty);
        let t_size = ty_size(ty);

        let misalign = off % t_align;
        if misalign != 0u {
            let mut i = off / 8u;
            let e = (off + t_size + 7u) / 8u;
            while i < e {
                unify(cls, ix + i, Memory);
                i += 1u;
            }
            return;
        }

        match ty.kind() {
            Integer |
            Pointer => {
                unify(cls, ix + off / 8u, Int);
            }
            Float => {
                if off % 8u == 4u {
                    unify(cls, ix + off / 8u, SSEFv);
                } else {
                    unify(cls, ix + off / 8u, SSEFs);
                }
            }
            Double => {
                unify(cls, ix + off / 8u, SSEDs);
            }
            Struct => {
                classify_struct(ty.field_types().as_slice(), cls, ix, off, ty.is_packed());
            }
            Array => {
                let len = ty.array_length();
                let elt = ty.element_type();
                let eltsz = ty_size(elt);
                let mut i = 0u;
                while i < len {
                    classify(elt, cls, ix, off + i * eltsz);
                    i += 1u;
                }
            }
            _ => fail!("classify: unhandled type")
        }
    }

    fn fixup(ty: Type, cls: &mut [RegClass]) {
        let mut i = 0u;
        let ty_kind = ty.kind();
        let e = cls.len();
        if cls.len() > 2u && (ty_kind == Struct || ty_kind == Array) {
            if cls[i].is_sse() {
                i += 1u;
                while i < e {
                    if cls[i] != SSEUp {
                        all_mem(cls);
                        return;
                    }
                    i += 1u;
                }
            } else {
                all_mem(cls);
                return
            }
        } else {
            while i < e {
                if cls[i] == Memory {
                    all_mem(cls);
                    return;
                }
                if cls[i] == X87Up {
                    // for darwin
                    // cls[i] = SSEDs;
                    all_mem(cls);
                    return;
                }
                if cls[i] == SSEUp {
                    cls[i] = SSEDv;
                } else if cls[i].is_sse() {
                    i += 1;
                    while i != e && cls[i] == SSEUp { i += 1u; }
                } else if cls[i] == X87 {
                    i += 1;
                    while i != e && cls[i] == X87Up { i += 1u; }
                } else {
                    i += 1;
                }
            }
        }
    }

    let words = (ty_size(ty) + 7) / 8;
    let mut cls = Vec::from_elem(words, NoClass);
    if words > 4 {
        all_mem(cls.as_mut_slice());
        return cls;
    }
    classify(ty, cls.as_mut_slice(), 0, 0);
    fixup(ty, cls.as_mut_slice());
    return cls;
}

fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
    fn llvec_len(cls: &[RegClass]) -> uint {
        let mut len = 1u;
        for c in cls.iter() {
            if *c != SSEUp {
                break;
            }
            len += 1u;
        }
        return len;
    }

    let mut tys = Vec::new();
    let mut i = 0u;
    let e = cls.len();
    while i < e {
        match cls[i] {
            Int => {
                tys.push(Type::i64(ccx));
            }
            SSEFv => {
                let vec_len = llvec_len(cls.tailn(i + 1u));
                let vec_ty = Type::vector(&Type::f32(ccx), (vec_len * 2u) as u64);
                tys.push(vec_ty);
                i += vec_len;
                continue;
            }
            SSEFs => {
                tys.push(Type::f32(ccx));
            }
            SSEDs => {
                tys.push(Type::f64(ccx));
            }
            _ => fail!("llregtype: unhandled class")
        }
        i += 1u;
    }
    return Type::struct_(ccx, tys.as_slice(), false);
}

pub fn compute_abi_info(ccx: &CrateContext,
                        atys: &[Type],
                        rty: Type,
                        ret_def: bool) -> FnType {
    fn x86_64_ty(ccx: &CrateContext,
                 ty: Type,
                 is_mem_cls: |cls: &[RegClass]| -> bool,
                 ind_attr: Attribute)
                 -> ArgType {
        if !ty.is_reg_ty() {
            let cls = classify_ty(ty);
            if is_mem_cls(cls.as_slice()) {
                ArgType::indirect(ty, Some(ind_attr))
            } else {
                ArgType::direct(ty,
                                Some(llreg_ty(ccx, cls.as_slice())),
                                None,
                                None)
            }
        } else {
            let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
            ArgType::direct(ty, None, None, attr)
        }
    }

    let mut arg_tys = Vec::new();
    for t in atys.iter() {
        let ty = x86_64_ty(ccx, *t, |cls| cls.is_pass_byval(), ByValAttribute);
        arg_tys.push(ty);
    }

    let ret_ty = if ret_def {
        x86_64_ty(ccx, rty, |cls| cls.is_ret_bysret(), StructRetAttribute)
    } else {
        ArgType::direct(Type::void(ccx), None, None, None)
    };

    return FnType {
        arg_tys: arg_tys,
        ret_ty: ret_ty,
    };
}
<|endoftext|>


<commit_before>use super::*;
use pact_matching::models::*;
use pact_matching::models::matchingrules::*;
use pact_matching::models::generators::*;
use pact_matching::s;
use std::collections::hash_map::HashMap;
use std::convert::TryFrom;
use futures::future::*;
use log::*;
use reqwest::{RequestBuilder, Client};
use itertools::Itertools;
use http::{Method, HeaderMap, HeaderValue};
use http::method::InvalidMethod;
use http::header::{HeaderName, InvalidHeaderName, InvalidHeaderValue};

#[derive(Debug)]
#[allow(dead_code)]
pub enum ProviderClientError {
    RequestMethodError(String, InvalidMethod),
    RequestHeaderNameError(String, InvalidHeaderName),
    RequestHeaderValueError(String, InvalidHeaderValue),
    RequestBodyError(String),
    ResponseError(String),
    ResponseStatusCodeError(u16),
}

pub fn join_paths(base: &String, path: String) -> String {
    let mut full_path = s!(base.trim_end_matches("/"));
    full_path.push('/');
    full_path.push_str(path.trim_start_matches("/"));
    full_path
}

fn create_native_request(client: &Client, base_url: &String, request: &Request) -> Result<RequestBuilder, ProviderClientError> {
  let url = join_paths(base_url, request.path.clone());
  let mut builder = client.request(Method::from_bytes(
    &request.method.clone().into_bytes()).unwrap_or(Method::GET), &url);

  if let Some(query) = &request.query {
    builder = builder.query(&query.into_iter()
      .sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
      .flat_map(|(k, v)| {
        v.iter().map(|v| (k, v)).collect_vec()
      }).collect_vec());
  }

  if let Some(headers) = &request.headers {
    let mut header_map = HeaderMap::new();
    for (k, vals) in headers {
      for header_value in vals {
        let header_name = HeaderName::try_from(k)
          .map_err(|err| ProviderClientError::RequestHeaderNameError(
            format!("Failed to parse header value: {}", header_value), err))?;
        header_map.append(header_name,  HeaderValue::from_str(header_value.as_str())
          .map_err(|err| ProviderClientError::RequestHeaderValueError(
            format!("Failed to parse header value: {}", header_value), err))?);
      }
    }
    builder = builder.headers(header_map);
  }

  match request.body {
    OptionalBody::Present(ref s) => builder = builder.body(s.clone()),
    OptionalBody::Null => {
      if request.content_type_enum() == DetectedContentType::Json {
        builder = builder.body("null");
      }
    },
    _ => ()
  };

  Ok(builder)
}

fn extract_headers(headers: &HeaderMap) -> Option<HashMap<String, Vec<String>>> {
  if !headers.is_empty() {
    let result = headers.keys()
      .map(|name| {
        let values = headers.get_all(name);
        let parsed_vals: Vec<Result<String, ()>> = values.iter()
          .map(|val| val.to_str()
            .map(|v| v.to_string())
            .map_err(|err| {
              log::warn!("Failed to parse HTTP header value: {}", err);
              ()
            })
          ).collect();
        (name.as_str().into(), parsed_vals.iter().cloned()
          .filter(|val| val.is_ok())
          .map(|val| val.unwrap_or_default())
          .collect())
      })
      .collect();

    Some(result)
  } else {
    None
  }
}

async fn extract_body(response: reqwest::Response) -> Result<OptionalBody, reqwest::Error> {
  let body = response.bytes().await?;
  if body.len() > 0 {
    Ok(OptionalBody::Present(body.to_vec()))
  } else {
    Ok(OptionalBody::Empty)
  }
}

async fn native_response_to_pact_response(
    native_response: reqwest::Response
) -> Result<Response, reqwest::Error> {
  debug!("Received response: {:?}", native_response);

  let status = native_response.status().as_u16();
  let headers = extract_headers(native_response.headers());
  let body = extract_body(native_response).await?;

  let response = Response {
    status,
    headers,
    body,
    matching_rules: MatchingRules::default(),
    generators: Generators::default(),
  };
  info!("Received response: {}", response);
  Ok(response)
}

/// This function makes the actual request to the provider, executing any request filter before
/// executing the request
pub async fn make_provider_request<F: RequestFilterExecutor>(
  provider: &ProviderInfo,
  request: &Request,
  options: &VerificationOptions<F>,
  client: &reqwest::Client
) -> Result<Response, ProviderClientError> {
  let request_filter_option = options.request_filter.as_ref();
  let request = if request_filter_option.is_some() {
    let request_filter = request_filter_option.unwrap();
    info!("Invoking request filter for request");
    request_filter.call(request)
  } else {
    request.clone()
  };

  let base_url = match provider.port {
    Some(port) => format!("{}://{}:{}{}", provider.protocol, provider.host, port, provider.path),
    None => format!("{}://{}{}", provider.protocol, provider.host, provider.path),
  };

  info!("Sending request to provider at {}", base_url);
  debug!("Sending request {}", request);
  let request = create_native_request(client, &base_url, &request)?;

  let response = request.send()
    .and_then(native_response_to_pact_response)
    .await
    .map_err(|err| ProviderClientError::ResponseError(err.to_string().into()))?;

  Ok(response)
}

pub async fn make_state_change_request(
  client: &reqwest::Client,
  state_change_url: &String,
  request: &Request
) -> Result<(), ProviderClientError> {
  log::debug!("Sending {} to state change handler", request);

  let request = create_native_request(client, state_change_url, request)?;
  let result = request.send().await;

  match result {
    Ok(response) => {
      debug!("State change request: {:?}", response);
      if response.status().is_success() {
        Ok(())
      } else {
        Err(ProviderClientError::ResponseStatusCodeError(response.status().as_u16()))
      }
    },
    Err(err) => {
      debug!("State change request failed with error {}", err);
      Err(ProviderClientError::ResponseError(format!("{}", err)))
    }
  }
}

pub fn provider_client_error_to_string(err: ProviderClientError) -> String {
  match err {
    ProviderClientError::RequestMethodError(ref method, _) =>
      format!("Invalid request method: '{}'", method),
    ProviderClientError::RequestHeaderNameError(ref name, _) =>
      format!("Invalid header name: '{}'", name),
    ProviderClientError::RequestHeaderValueError(ref value, _) =>
      format!("Invalid header value: '{}'", value),
    ProviderClientError::RequestBodyError(ref message) =>
      format!("Invalid request body: '{}'", message),
    ProviderClientError::ResponseError(ref message) =>
      format!("Invalid response: {}", message),
    ProviderClientError::ResponseStatusCodeError(ref code) =>
      format!("Invalid status code: {}", code)
  }
}

#[cfg(test)]
mod tests {
  use expectest::prelude::*;
  use expectest::expect;
  use super::{join_paths, create_native_request};
  use pact_matching::s;
  use pact_matching::models::{Request, OptionalBody};
  use maplit::*;
  use itertools::Itertools;

  #[test]
  fn join_paths_test() {
      expect!(join_paths(&s!(""), s!(""))).to(be_equal_to(s!("/")));
      expect!(join_paths(&s!("/"), s!(""))).to(be_equal_to(s!("/")));
      expect!(join_paths(&s!(""), s!("/"))).to(be_equal_to(s!("/")));
      expect!(join_paths(&s!("/"), s!("/"))).to(be_equal_to(s!("/")));
      expect!(join_paths(&s!("/a/b"), s!("/c/d"))).to(be_equal_to(s!("/a/b/c/d")));
  }

  #[test]
  fn convert_request_to_native_request_test() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request::default();
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));
    expect!(request_builder.body()).to(be_none());
  }

  #[test]
  fn convert_request_to_native_request_with_query_parameters() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      query: Some(hashmap!{
        "a".to_string() => vec!["b".to_string()],
        "c".to_string() => vec!["d".to_string(), "e".to_string()]
      }),
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/?a=b&c=d&c=e"));
  }

  #[test]
  fn convert_request_to_native_request_with_headers() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      headers: Some(hashmap! {
        "A".to_string() => vec!["B".to_string()],
        "B".to_string() => vec!["C".to_string(), "D".to_string()]
      }),
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));

    let headers = dbg!(request_builder.headers());
    expect!(headers.len()).to(be_equal_to(3));
    expect!(&headers["A"]).to(be_equal_to("B"));
    expect!(&headers["B"]).to(be_equal_to("C"));
    expect!(headers.get_all("B").iter().map(|v| v.to_str().unwrap()).collect_vec())
      .to(be_equal_to(vec!["C", "D"]));
  }

  #[test]
  fn convert_request_to_native_request_with_body() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      body: OptionalBody::from("body"),
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));
    expect!(request_builder.body().unwrap().as_bytes()).to(be_some().value("body".as_bytes()));
  }

  #[test]
  fn convert_request_to_native_request_with_null_body() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      body: OptionalBody::Null,
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));
    expect!(request_builder.body()).to(be_none());
  }

  #[test]
  fn convert_request_to_native_request_with_json_null_body() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      headers: Some(hashmap! {
        "Content-Type".to_string() => vec!["application/json".to_string()]
      }),
      body: OptionalBody::Null,
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));
    expect!(request_builder.body().unwrap().as_bytes()).to(be_some().value("null".as_bytes()));
  }
}
<commit_msg>Use err.to_string() rather than format!("{}", err)<commit_after>use super::*;
use pact_matching::models::*;
use pact_matching::models::matchingrules::*;
use pact_matching::models::generators::*;
use pact_matching::s;
use std::collections::hash_map::HashMap;
use std::convert::TryFrom;
use futures::future::*;
use log::*;
use reqwest::{RequestBuilder, Client};
use itertools::Itertools;
use http::{Method, HeaderMap, HeaderValue};
use http::method::InvalidMethod;
use http::header::{HeaderName, InvalidHeaderName, InvalidHeaderValue};

#[derive(Debug)]
#[allow(dead_code)]
pub enum ProviderClientError {
    RequestMethodError(String, InvalidMethod),
    RequestHeaderNameError(String, InvalidHeaderName),
    RequestHeaderValueError(String, InvalidHeaderValue),
    RequestBodyError(String),
    ResponseError(String),
    ResponseStatusCodeError(u16),
}

pub fn join_paths(base: &String, path: String) -> String {
    let mut full_path = s!(base.trim_end_matches("/"));
    full_path.push('/');
    full_path.push_str(path.trim_start_matches("/"));
    full_path
}

fn create_native_request(client: &Client, base_url: &String, request: &Request) -> Result<RequestBuilder, ProviderClientError> {
  let url = join_paths(base_url, request.path.clone());
  let mut builder = client.request(Method::from_bytes(
    &request.method.clone().into_bytes()).unwrap_or(Method::GET), &url);

  if let Some(query) = &request.query {
    builder = builder.query(&query.into_iter()
      .sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
      .flat_map(|(k, v)| {
        v.iter().map(|v| (k, v)).collect_vec()
      }).collect_vec());
  }

  if let Some(headers) = &request.headers {
    let mut header_map = HeaderMap::new();
    for (k, vals) in headers {
      for header_value in vals {
        let header_name = HeaderName::try_from(k)
          .map_err(|err| ProviderClientError::RequestHeaderNameError(
            format!("Failed to parse header value: {}", header_value), err))?;
        header_map.append(header_name,  HeaderValue::from_str(header_value.as_str())
          .map_err(|err| ProviderClientError::RequestHeaderValueError(
            format!("Failed to parse header value: {}", header_value), err))?);
      }
    }
    builder = builder.headers(header_map);
  }

  match request.body {
    OptionalBody::Present(ref s) => builder = builder.body(s.clone()),
    OptionalBody::Null => {
      if request.content_type_enum() == DetectedContentType::Json {
        builder = builder.body("null");
      }
    },
    _ => ()
  };

  Ok(builder)
}

fn extract_headers(headers: &HeaderMap) -> Option<HashMap<String, Vec<String>>> {
  if !headers.is_empty() {
    let result = headers.keys()
      .map(|name| {
        let values = headers.get_all(name);
        let parsed_vals: Vec<Result<String, ()>> = values.iter()
          .map(|val| val.to_str()
            .map(|v| v.to_string())
            .map_err(|err| {
              log::warn!("Failed to parse HTTP header value: {}", err);
              ()
            })
          ).collect();
        (name.as_str().into(), parsed_vals.iter().cloned()
          .filter(|val| val.is_ok())
          .map(|val| val.unwrap_or_default())
          .collect())
      })
      .collect();

    Some(result)
  } else {
    None
  }
}

async fn extract_body(response: reqwest::Response) -> Result<OptionalBody, reqwest::Error> {
  let body = response.bytes().await?;
  if body.len() > 0 {
    Ok(OptionalBody::Present(body.to_vec()))
  } else {
    Ok(OptionalBody::Empty)
  }
}

async fn native_response_to_pact_response(
    native_response: reqwest::Response
) -> Result<Response, reqwest::Error> {
  debug!("Received response: {:?}", native_response);

  let status = native_response.status().as_u16();
  let headers = extract_headers(native_response.headers());
  let body = extract_body(native_response).await?;

  let response = Response {
    status,
    headers,
    body,
    matching_rules: MatchingRules::default(),
    generators: Generators::default(),
  };
  info!("Received response: {}", response);
  Ok(response)
}

/// This function makes the actual request to the provider, executing any request filter before
/// executing the request
pub async fn make_provider_request<F: RequestFilterExecutor>(
  provider: &ProviderInfo,
  request: &Request,
  options: &VerificationOptions<F>,
  client: &reqwest::Client
) -> Result<Response, ProviderClientError> {
  let request_filter_option = options.request_filter.as_ref();
  let request = if request_filter_option.is_some() {
    let request_filter = request_filter_option.unwrap();
    info!("Invoking request filter for request");
    request_filter.call(request)
  } else {
    request.clone()
  };

  let base_url = match provider.port {
    Some(port) => format!("{}://{}:{}{}", provider.protocol, provider.host, port, provider.path),
    None => format!("{}://{}{}", provider.protocol, provider.host, provider.path),
  };

  info!("Sending request to provider at {}", base_url);
  debug!("Sending request {}", request);
  let request = create_native_request(client, &base_url, &request)?;

  let response = request.send()
    .and_then(native_response_to_pact_response)
    .await
    .map_err(|err| ProviderClientError::ResponseError(err.to_string().into()))?;

  Ok(response)
}

pub async fn make_state_change_request(
  client: &reqwest::Client,
  state_change_url: &String,
  request: &Request
) -> Result<(), ProviderClientError> {
  log::debug!("Sending {} to state change handler", request);

  let request = create_native_request(client, state_change_url, request)?;
  let result = request.send().await;

  match result {
    Ok(response) => {
      debug!("State change request: {:?}", response);
      if response.status().is_success() {
        Ok(())
      } else {
        Err(ProviderClientError::ResponseStatusCodeError(response.status().as_u16()))
      }
    },
    Err(err) => {
      debug!("State change request failed with error {}", err);
      Err(ProviderClientError::ResponseError(err.to_string()))
    }
  }
}

pub fn provider_client_error_to_string(err: ProviderClientError) -> String {
  match err {
    ProviderClientError::RequestMethodError(ref method, _) =>
      format!("Invalid request method: '{}'", method),
    ProviderClientError::RequestHeaderNameError(ref name, _) =>
      format!("Invalid header name: '{}'", name),
    ProviderClientError::RequestHeaderValueError(ref value, _) =>
      format!("Invalid header value: '{}'", value),
    ProviderClientError::RequestBodyError(ref message) =>
      format!("Invalid request body: '{}'", message),
    ProviderClientError::ResponseError(ref message) =>
      format!("Invalid response: {}", message),
    ProviderClientError::ResponseStatusCodeError(ref code) =>
      format!("Invalid status code: {}", code)
  }
}

#[cfg(test)]
mod tests {
  use expectest::prelude::*;
  use expectest::expect;
  use super::{join_paths, create_native_request};
  use pact_matching::s;
  use pact_matching::models::{Request, OptionalBody};
  use maplit::*;
  use itertools::Itertools;

  #[test]
  fn join_paths_test() {
      expect!(join_paths(&s!(""), s!(""))).to(be_equal_to(s!("/")));
      expect!(join_paths(&s!("/"), s!(""))).to(be_equal_to(s!("/")));
      expect!(join_paths(&s!(""), s!("/"))).to(be_equal_to(s!("/")));
      expect!(join_paths(&s!("/"), s!("/"))).to(be_equal_to(s!("/")));
      expect!(join_paths(&s!("/a/b"), s!("/c/d"))).to(be_equal_to(s!("/a/b/c/d")));
  }

  #[test]
  fn convert_request_to_native_request_test() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request::default();
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));
    expect!(request_builder.body()).to(be_none());
  }

  #[test]
  fn convert_request_to_native_request_with_query_parameters() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      query: Some(hashmap!{
        "a".to_string() => vec!["b".to_string()],
        "c".to_string() => vec!["d".to_string(), "e".to_string()]
      }),
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/?a=b&c=d&c=e"));
  }

  #[test]
  fn convert_request_to_native_request_with_headers() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      headers: Some(hashmap! {
        "A".to_string() => vec!["B".to_string()],
        "B".to_string() => vec!["C".to_string(), "D".to_string()]
      }),
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));

    let headers = dbg!(request_builder.headers());
    expect!(headers.len()).to(be_equal_to(3));
    expect!(&headers["A"]).to(be_equal_to("B"));
    expect!(&headers["B"]).to(be_equal_to("C"));
    expect!(headers.get_all("B").iter().map(|v| v.to_str().unwrap()).collect_vec())
      .to(be_equal_to(vec!["C", "D"]));
  }

  #[test]
  fn convert_request_to_native_request_with_body() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      body: OptionalBody::from("body"),
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));
    expect!(request_builder.body().unwrap().as_bytes()).to(be_some().value("body".as_bytes()));
  }

  #[test]
  fn convert_request_to_native_request_with_null_body() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      body: OptionalBody::Null,
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));
    expect!(request_builder.body()).to(be_none());
  }

  #[test]
  fn convert_request_to_native_request_with_json_null_body() {
    let client = reqwest::Client::new();
    let base_url = "http://example.test:8080".to_string();
    let request = Request {
      headers: Some(hashmap! {
        "Content-Type".to_string() => vec!["application/json".to_string()]
      }),
      body: OptionalBody::Null,
      .. Request::default()
    };
    let request_builder = create_native_request(&client, &base_url, &request).unwrap().build().unwrap();

    expect!(request_builder.method()).to(be_equal_to("GET"));
    expect!(request_builder.url().as_str()).to(be_equal_to("http://example.test:8080/"));
    expect!(request_builder.body().unwrap().as_bytes()).to(be_some().value("null".as_bytes()));
  }
}
<|endoftext|>


<commit_before>//! This is a simple packetized ray tracer example which demonstrates
//! interopability with structs in Rust and ISPC.

#[macro_use]
extern crate ispc;
extern crate image;
extern crate rand;

use rand::Rng;

ispc_module!(rt);

pub use vec3f::Vec3f;
pub use camera::Camera;
pub use geom::{Sphere, Plane, Geometry};
pub use lights::PointLight;
pub use material::Lambertian;

pub mod vec3f;
pub mod camera;
pub mod geom;
pub mod lights;
pub mod material;

pub fn render() {
    let width = 512;
    let height = 512;
    let camera = Camera::new(Vec3f::new(0.0, 0.0, -3.0), Vec3f::new(0.0, 0.0, 0.0),
                             Vec3f::new(0.0, 1.0, 0.0), 60.0, width, height);
    let white_mat = Lambertian::new(Vec3f::new(0.9, 0.9, 0.9));
    let red_mat = Lambertian::new(Vec3f::new(0.8, 0.1, 0.1));
    let blue_mat = Lambertian::new(Vec3f::new(0.1, 0.2, 0.7));
    let sphere = Sphere::new(Vec3f::new(0.0, 0.0, 0.0), 0.5, red_mat);
    let floor = Plane::new(Vec3f::new(0.0, -0.5, 0.0), Vec3f::new(0.0, 1.0, 0.0), white_mat);
    let back_wall = Plane::new(Vec3f::new(0.0, 0.0, 2.0), Vec3f::new(0.0, -0.6, -1.0), blue_mat);
    let light = PointLight::new(Vec3f::new(0.75, 0.75, -2.0), Vec3f::broadcast(10.0));
    let mut framebuffer = vec![0.0; width * height * 3];
    let mut srgb_img_buf = vec![0u8; width * height * 3];
    let mut rng = rand::thread_rng();
    // We need a random seed for each scanline of the image
    let scanline_seeds: Vec<_> = rng.gen_iter::<i32>().take(height).collect();
    unsafe {
        let geom = vec![sphere.ispc_equiv(), floor.ispc_equiv(), back_wall.ispc_equiv()];
        rt::render(&camera as *const Camera, geom.as_ptr(), geom.len() as i32, light.ispc_equiv(),
                   scanline_seeds.as_ptr(), width as i32, height as i32, framebuffer.as_mut_ptr());
        rt::framebuffer_to_srgb(framebuffer.as_ptr(), srgb_img_buf.as_mut_ptr(), width as i32, height as i32);
    }
    match image::save_buffer("rt.png", &srgb_img_buf[..], width as u32, height as u32, image::RGB(8)) {
        Ok(_) => println!("Rendered image saved to rt.png"),
        Err(e) => panic!("Error saving image: {}", e),
    };
}

<commit_msg>Add timing of how long rendering took<commit_after>//! This is a simple packetized ray tracer example which demonstrates
//! interopability with structs in Rust and ISPC.

#[macro_use]
extern crate ispc;
extern crate image;
extern crate rand;

use std::time::Instant;

use rand::Rng;

ispc_module!(rt);

pub use vec3f::Vec3f;
pub use camera::Camera;
pub use geom::{Sphere, Plane, Geometry};
pub use lights::PointLight;
pub use material::Lambertian;

pub mod vec3f;
pub mod camera;
pub mod geom;
pub mod lights;
pub mod material;

pub fn render() {
    let width = 512;
    let height = 512;
    let camera = Camera::new(Vec3f::new(0.0, 0.0, -3.0), Vec3f::new(0.0, 0.0, 0.0),
                             Vec3f::new(0.0, 1.0, 0.0), 60.0, width, height);
    let white_mat = Lambertian::new(Vec3f::new(0.9, 0.9, 0.9));
    let red_mat = Lambertian::new(Vec3f::new(0.8, 0.1, 0.1));
    let blue_mat = Lambertian::new(Vec3f::new(0.1, 0.2, 0.7));
    let sphere = Sphere::new(Vec3f::new(0.0, 0.0, 0.0), 0.5, red_mat);
    let floor = Plane::new(Vec3f::new(0.0, -0.5, 0.0), Vec3f::new(0.0, 1.0, 0.0), white_mat);
    let back_wall = Plane::new(Vec3f::new(0.0, 0.0, 2.0), Vec3f::new(0.0, -0.6, -1.0), blue_mat);
    let light = PointLight::new(Vec3f::new(0.75, 0.75, -2.0), Vec3f::broadcast(10.0));
    let mut framebuffer = vec![0.0; width * height * 3];
    let mut srgb_img_buf = vec![0u8; width * height * 3];
    let mut rng = rand::thread_rng();
    // We need a random seed for each scanline of the image
    let scanline_seeds: Vec<_> = rng.gen_iter::<i32>().take(height).collect();
    unsafe {
        let geom = vec![sphere.ispc_equiv(), floor.ispc_equiv(), back_wall.ispc_equiv()];
        let start = Instant::now();
        rt::render(&camera as *const Camera, geom.as_ptr(), geom.len() as i32, light.ispc_equiv(),
                   scanline_seeds.as_ptr(), width as i32, height as i32, framebuffer.as_mut_ptr());
        let elapsed = start.elapsed();
        println!("Rendering took {}s", elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9);
        rt::framebuffer_to_srgb(framebuffer.as_ptr(), srgb_img_buf.as_mut_ptr(), width as i32, height as i32);
    }
    match image::save_buffer("rt.png", &srgb_img_buf[..], width as u32, height as u32, image::RGB(8)) {
        Ok(_) => println!("Rendered image saved to rt.png"),
        Err(e) => panic!("Error saving image: {}", e),
    };
}

<|endoftext|>


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

use crate::common::types::{
    CliCommand, CliConfig, CliError, CliTypedResult, ConfigSearchMode, ProfileOptions, RestOptions,
};
use aptos_types::account_address::AccountAddress;
use async_trait::async_trait;
use clap::{ArgEnum, Parser};
use serde_json::json;
use std::{
    fmt::{Display, Formatter},
    str::FromStr,
};

#[derive(ArgEnum, Clone, Copy, Debug)]
pub enum ListQuery {
    Balance,
    Modules,
    Resources,
}

impl Display for ListQuery {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let str = match self {
            ListQuery::Balance => "balance",
            ListQuery::Modules => "modules",
            ListQuery::Resources => "resources",
        };
        write!(f, "{}", str)
    }
}

impl FromStr for ListQuery {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "balance" => Ok(ListQuery::Balance),
            "modules" => Ok(ListQuery::Modules),
            "resources" => Ok(ListQuery::Resources),
            _ => Err("Invalid query. Valid values are modules, resources"),
        }
    }
}

/// Command to list resources, modules, or other items owned by an address
///
#[derive(Debug, Parser)]
pub struct ListAccount {
    /// Address of the account you want to list resources/modules for
    #[clap(long, parse(try_from_str=crate::common::types::load_account_arg))]
    pub(crate) account: Option<AccountAddress>,

    /// Type of items to list: [balance, resources, modules]
    #[clap(long, default_value_t = ListQuery::Resources)]
    pub(crate) query: ListQuery,

    #[clap(flatten)]
    pub(crate) rest_options: RestOptions,
    #[clap(flatten)]
    pub(crate) profile_options: ProfileOptions,
}

#[async_trait]
impl CliCommand<Vec<serde_json::Value>> for ListAccount {
    fn command_name(&self) -> &'static str {
        "ListAccount"
    }

    // TODO: Format this in a reasonable way while providing all information
    async fn execute(self) -> CliTypedResult<Vec<serde_json::Value>> {
        let account = if let Some(account) = self.account {
            account
        } else if let Some(Some(account)) = CliConfig::load_profile(
            &self.profile_options.profile,
            ConfigSearchMode::CurrentDirAndParents,
        )?
        .map(|p| p.account)
        {
            account
        } else {
            return Err(CliError::CommandArgumentError(
                "Please provide an account using --account or run aptos init".to_string(),
            ));
        };

        let client = self.rest_options.client(&self.profile_options.profile)?;
        let map_err_func = |err: anyhow::Error| CliError::ApiError(err.to_string());
        let response = match self.query {
            ListQuery::Balance => vec![
                client
                    .get_account_resource(
                        account,
                        "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
                    )
                    .await
                    .map_err(map_err_func)?
                    .into_inner()
                    .unwrap()
                    .data,
            ],
            ListQuery::Modules => client
                .get_account_modules(account)
                .await
                .map_err(map_err_func)?
                .into_inner()
                .iter()
                .cloned()
                .map(|module| module.try_parse_abi().unwrap())
                .map(|module| json!(module))
                .collect::<Vec<serde_json::Value>>(),
            ListQuery::Resources => client
                .get_account_resources(account)
                .await
                .map_err(map_err_func)?
                .into_inner()
                .iter()
                .map(|json| json.data.clone())
                .collect::<Vec<serde_json::Value>>(),
        };

        Ok(response)
    }
}
<commit_msg>[aptos-cli] Add move type to list resources API<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::common::types::{
    CliCommand, CliConfig, CliError, CliTypedResult, ConfigSearchMode, ProfileOptions, RestOptions,
};
use aptos_types::account_address::AccountAddress;
use async_trait::async_trait;
use clap::{ArgEnum, Parser};
use serde_json::json;
use std::{
    fmt::{Display, Formatter},
    str::FromStr,
};

#[derive(ArgEnum, Clone, Copy, Debug)]
pub enum ListQuery {
    Balance,
    Modules,
    Resources,
}

impl Display for ListQuery {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let str = match self {
            ListQuery::Balance => "balance",
            ListQuery::Modules => "modules",
            ListQuery::Resources => "resources",
        };
        write!(f, "{}", str)
    }
}

impl FromStr for ListQuery {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "balance" => Ok(ListQuery::Balance),
            "modules" => Ok(ListQuery::Modules),
            "resources" => Ok(ListQuery::Resources),
            _ => Err("Invalid query. Valid values are modules, resources"),
        }
    }
}

/// Command to list resources, modules, or other items owned by an address
///
#[derive(Debug, Parser)]
pub struct ListAccount {
    /// Address of the account you want to list resources/modules for
    #[clap(long, parse(try_from_str=crate::common::types::load_account_arg))]
    pub(crate) account: Option<AccountAddress>,

    /// Type of items to list: [balance, resources, modules]
    #[clap(long, default_value_t = ListQuery::Resources)]
    pub(crate) query: ListQuery,

    #[clap(flatten)]
    pub(crate) rest_options: RestOptions,
    #[clap(flatten)]
    pub(crate) profile_options: ProfileOptions,
}

#[async_trait]
impl CliCommand<Vec<serde_json::Value>> for ListAccount {
    fn command_name(&self) -> &'static str {
        "ListAccount"
    }

    // TODO: Format this in a reasonable way while providing all information
    async fn execute(self) -> CliTypedResult<Vec<serde_json::Value>> {
        let account = if let Some(account) = self.account {
            account
        } else if let Some(Some(account)) = CliConfig::load_profile(
            &self.profile_options.profile,
            ConfigSearchMode::CurrentDirAndParents,
        )?
        .map(|p| p.account)
        {
            account
        } else {
            return Err(CliError::CommandArgumentError(
                "Please provide an account using --account or run aptos init".to_string(),
            ));
        };

        let client = self.rest_options.client(&self.profile_options.profile)?;
        let map_err_func = |err: anyhow::Error| CliError::ApiError(err.to_string());
        let response = match self.query {
            ListQuery::Balance => vec![
                client
                    .get_account_resource(
                        account,
                        "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
                    )
                    .await
                    .map_err(map_err_func)?
                    .into_inner()
                    .unwrap()
                    .data,
            ],
            ListQuery::Modules => client
                .get_account_modules(account)
                .await
                .map_err(map_err_func)?
                .into_inner()
                .iter()
                .cloned()
                .map(|module| module.try_parse_abi().unwrap())
                .map(|module| json!(module))
                .collect::<Vec<serde_json::Value>>(),
            ListQuery::Resources => client
                .get_account_resources(account)
                .await
                .map_err(map_err_func)?
                .into_inner()
                .iter()
                .map(|resource| {
                    let mut map = serde_json::Map::new();
                    map.insert(resource.resource_type.to_string(), resource.data.clone());
                    serde_json::Value::Object(map)
                })
                .collect::<Vec<serde_json::Value>>(),
        };

        Ok(response)
    }
}
<|endoftext|>


<commit_before>//! A small TCP server to handle collection of diagnostics information in a
//! cross-platform way for the `cargo fix` command.

use std::env;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, JoinHandle};

use failure::{Error, ResultExt};
use serde_json;

use util::{Config, ProcessBuilder};
use util::errors::CargoResult;

const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
const PLEASE_REPORT_THIS_BUG: &str =
    "\
     This likely indicates a bug in either rustc or cargo itself,\n\
     and we would appreciate a bug report! You're likely to see \n\
     a number of compiler warnings after this message which cargo\n\
     attempted to fix but failed. If you could open an issue at\n\
     https://github.com/rust-lang/cargo/issues\n\
     quoting the full output of this command we'd be very appreciative!\n\n\
     ";

#[derive(Deserialize, Serialize)]
pub enum Message {
    Fixing {
        file: String,
        fixes: usize,
    },
    FixFailed {
        files: Vec<String>,
        krate: Option<String>,
    },
    ReplaceFailed {
        file: String,
        message: String,
    },
}

impl Message {
    pub fn fixing(file: &str, num: usize) -> Message {
        Message::Fixing {
            file: file.into(),
            fixes: num,
        }
    }

    pub fn post(&self) -> Result<(), Error> {
        let addr = env::var(DIAGNOSICS_SERVER_VAR)
            .context("diagnostics collector misconfigured")?;
        let mut client =
            TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?;

        let s = serde_json::to_string(self).context("failed to serialize message")?;
        client
            .write_all(s.as_bytes())
            .context("failed to write message to diagnostics target")?;
        client
            .shutdown(Shutdown::Write)
            .context("failed to shutdown")?;

        let mut tmp = Vec::new();
        client
            .read_to_end(&mut tmp)
            .context("failed to receive a disconnect")?;

        Ok(())
    }

    pub fn print_to(&self, config: &Config) -> CargoResult<()> {
        match self {
            Message::Fixing { file, fixes } => {
                let msg = if *fixes == 1 { "fix" } else { "fixes" };
                let msg = format!("{} ({} {})", file, fixes, msg);
                config.shell().status("Fixing", msg)
            }
            Message::ReplaceFailed { file, message } => {
                let msg = format!("error applying suggestions to `{}`\n", file);
                config.shell().warn(&msg)?;
                write!(
                    config.shell().err(),
                    "The full error message was:\n\n> {}",
                    message,
                )?;
                write!(config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::FixFailed { files, krate } => {
                if let Some(ref krate) = *krate {
                    config.shell().warn(&format!(
                        "failed to automatically apply fixes suggested by rustc \
                         to crate `{}`",
                        krate,
                    ))?;
                } else {
                    config.shell().warn(
                        "failed to automatically apply fixes suggested by rustc"
                    )?;
                }
                if !files.is_empty() {
                    writeln!(
                        config.shell().err(),
                        "\nafter fixes were automatically applied the compiler \
                         reported errors within these files:\n"
                    )?;
                    for file in files {
                        writeln!(config.shell().err(), "  * {}", file)?;
                    }
                    writeln!(config.shell().err())?;
                }
                write!(config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
        }

    }
}

#[derive(Debug)]
pub struct RustfixDiagnosticServer {
    listener: TcpListener,
    addr: SocketAddr,
}

pub struct StartedServer {
    addr: SocketAddr,
    done: Arc<AtomicBool>,
    thread: Option<JoinHandle<()>>,
}

impl RustfixDiagnosticServer {
    pub fn new() -> Result<Self, Error> {
        let listener = TcpListener::bind("127.0.0.1:0")
            .with_context(|_| "failed to bind TCP listener to manage locking")?;
        let addr = listener.local_addr()?;

        Ok(RustfixDiagnosticServer { listener, addr })
    }

    pub fn configure(&self, process: &mut ProcessBuilder) {
        process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string());
    }

    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>
    where
        F: Fn(Message) + Send + 'static,
    {
        let addr = self.addr;
        let done = Arc::new(AtomicBool::new(false));
        let done2 = done.clone();
        let thread = thread::spawn(move || {
            self.run(&on_message, &done2);
        });

        Ok(StartedServer {
            addr,
            thread: Some(thread),
            done,
        })
    }

    fn run(self, on_message: &Fn(Message), done: &AtomicBool) {
        while let Ok((client, _)) = self.listener.accept() {
            let mut client = BufReader::new(client);
            match serde_json::from_reader(client) {
                Ok(message) => on_message(message),
                Err(e) => warn!("invalid diagnostics message: {}", e),
            }
            if done.load(Ordering::SeqCst) {
                break
            }
        }
    }
}

impl Drop for StartedServer {
    fn drop(&mut self) {
        self.done.store(true, Ordering::SeqCst);
        // Ignore errors here as this is largely best-effort
        if TcpStream::connect(&self.addr).is_err() {
            return;
        }
        drop(self.thread.take().unwrap().join());
    }
}
<commit_msg>Fix a formatting of a cargo fix message<commit_after>//! A small TCP server to handle collection of diagnostics information in a
//! cross-platform way for the `cargo fix` command.

use std::env;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, JoinHandle};

use failure::{Error, ResultExt};
use serde_json;

use util::{Config, ProcessBuilder};
use util::errors::CargoResult;

const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
const PLEASE_REPORT_THIS_BUG: &str =
    "\
     This likely indicates a bug in either rustc or cargo itself,\n\
     and we would appreciate a bug report! You're likely to see \n\
     a number of compiler warnings after this message which cargo\n\
     attempted to fix but failed. If you could open an issue at\n\
     https://github.com/rust-lang/cargo/issues\n\
     quoting the full output of this command we'd be very appreciative!\n\n\
     ";

#[derive(Deserialize, Serialize)]
pub enum Message {
    Fixing {
        file: String,
        fixes: usize,
    },
    FixFailed {
        files: Vec<String>,
        krate: Option<String>,
    },
    ReplaceFailed {
        file: String,
        message: String,
    },
}

impl Message {
    pub fn fixing(file: &str, num: usize) -> Message {
        Message::Fixing {
            file: file.into(),
            fixes: num,
        }
    }

    pub fn post(&self) -> Result<(), Error> {
        let addr = env::var(DIAGNOSICS_SERVER_VAR)
            .context("diagnostics collector misconfigured")?;
        let mut client =
            TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?;

        let s = serde_json::to_string(self).context("failed to serialize message")?;
        client
            .write_all(s.as_bytes())
            .context("failed to write message to diagnostics target")?;
        client
            .shutdown(Shutdown::Write)
            .context("failed to shutdown")?;

        let mut tmp = Vec::new();
        client
            .read_to_end(&mut tmp)
            .context("failed to receive a disconnect")?;

        Ok(())
    }

    pub fn print_to(&self, config: &Config) -> CargoResult<()> {
        match self {
            Message::Fixing { file, fixes } => {
                let msg = if *fixes == 1 { "fix" } else { "fixes" };
                let msg = format!("{} ({} {})", file, fixes, msg);
                config.shell().status("Fixing", msg)
            }
            Message::ReplaceFailed { file, message } => {
                let msg = format!("error applying suggestions to `{}`\n", file);
                config.shell().warn(&msg)?;
                write!(
                    config.shell().err(),
                    "The full error message was:\n\n> {}\n\n",
                    message,
                )?;
                write!(config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::FixFailed { files, krate } => {
                if let Some(ref krate) = *krate {
                    config.shell().warn(&format!(
                        "failed to automatically apply fixes suggested by rustc \
                         to crate `{}`",
                        krate,
                    ))?;
                } else {
                    config.shell().warn(
                        "failed to automatically apply fixes suggested by rustc"
                    )?;
                }
                if !files.is_empty() {
                    writeln!(
                        config.shell().err(),
                        "\nafter fixes were automatically applied the compiler \
                         reported errors within these files:\n"
                    )?;
                    for file in files {
                        writeln!(config.shell().err(), "  * {}", file)?;
                    }
                    writeln!(config.shell().err())?;
                }
                write!(config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
        }

    }
}

#[derive(Debug)]
pub struct RustfixDiagnosticServer {
    listener: TcpListener,
    addr: SocketAddr,
}

pub struct StartedServer {
    addr: SocketAddr,
    done: Arc<AtomicBool>,
    thread: Option<JoinHandle<()>>,
}

impl RustfixDiagnosticServer {
    pub fn new() -> Result<Self, Error> {
        let listener = TcpListener::bind("127.0.0.1:0")
            .with_context(|_| "failed to bind TCP listener to manage locking")?;
        let addr = listener.local_addr()?;

        Ok(RustfixDiagnosticServer { listener, addr })
    }

    pub fn configure(&self, process: &mut ProcessBuilder) {
        process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string());
    }

    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>
    where
        F: Fn(Message) + Send + 'static,
    {
        let addr = self.addr;
        let done = Arc::new(AtomicBool::new(false));
        let done2 = done.clone();
        let thread = thread::spawn(move || {
            self.run(&on_message, &done2);
        });

        Ok(StartedServer {
            addr,
            thread: Some(thread),
            done,
        })
    }

    fn run(self, on_message: &Fn(Message), done: &AtomicBool) {
        while let Ok((client, _)) = self.listener.accept() {
            let mut client = BufReader::new(client);
            match serde_json::from_reader(client) {
                Ok(message) => on_message(message),
                Err(e) => warn!("invalid diagnostics message: {}", e),
            }
            if done.load(Ordering::SeqCst) {
                break
            }
        }
    }
}

impl Drop for StartedServer {
    fn drop(&mut self) {
        self.done.store(true, Ordering::SeqCst);
        // Ignore errors here as this is largely best-effort
        if TcpStream::connect(&self.addr).is_err() {
            return;
        }
        drop(self.thread.take().unwrap().join());
    }
}
<|endoftext|>


<commit_before>// run-pass
#![feature(const_discriminant, test)]
#![allow(dead_code)]

use std::mem::{discriminant, Discriminant};
use std::hint::black_box;

enum Test {
    A(u8),
    B,
    C { a: u8, b: u8 },
}

const TEST_A: Discriminant<Test> = discriminant(&Test::A(5));
const TEST_A_OTHER: Discriminant<Test> = discriminant(&Test::A(17));
const TEST_B: Discriminant<Test> = discriminant(&Test::B);

enum Void {}

enum SingleVariant {
    V,
    Never(Void),
}

const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);

fn main() {
    assert_eq!(TEST_A, TEST_A_OTHER);
    assert_eq!(TEST_A, discriminant(black_box(&Test::A(17))));
    assert_eq!(TEST_B, discriminant(black_box(&Test::B)));
    assert_ne!(TEST_A, TEST_B);
    assert_ne!(TEST_B, discriminant(black_box(&Test::C { a: 42, b: 7 })));

    assert_eq!(TEST_V, discriminant(black_box(&SingleVariant::V)));
}
<commit_msg>Separate feature flags<commit_after>// run-pass
#![feature(const_discriminant)]
#![feature(test)]
#![allow(dead_code)]

use std::mem::{discriminant, Discriminant};
use std::hint::black_box;

enum Test {
    A(u8),
    B,
    C { a: u8, b: u8 },
}

const TEST_A: Discriminant<Test> = discriminant(&Test::A(5));
const TEST_A_OTHER: Discriminant<Test> = discriminant(&Test::A(17));
const TEST_B: Discriminant<Test> = discriminant(&Test::B);

enum Void {}

enum SingleVariant {
    V,
    Never(Void),
}

const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);

fn main() {
    assert_eq!(TEST_A, TEST_A_OTHER);
    assert_eq!(TEST_A, discriminant(black_box(&Test::A(17))));
    assert_eq!(TEST_B, discriminant(black_box(&Test::B)));
    assert_ne!(TEST_A, TEST_B);
    assert_ne!(TEST_B, discriminant(black_box(&Test::C { a: 42, b: 7 })));

    assert_eq!(TEST_V, discriminant(black_box(&SingleVariant::V)));
}
<|endoftext|>


<commit_before>// run-pass

#[allow(unreachable_code)]
fn main() {
    assert!(true, "Failed: {:?}", panic!("assert! evaluated format expressions"));
    debug_assert!(true, "Failed: {:?}", panic!("debug_assert! evaluated format expressions"));
    assert_eq!(1, 1, "Failed: {:?}", panic!("assert_eq! evaluated format expressions"));
    debug_assert_eq!(1, 1, "Failed: {:?}", panic!("debug_assert_eq! evaluated format expressions"));
    assert_ne!(1, 2, "Failed: {:?}", panic!("assert_ne! evaluated format expressions"));
    debug_assert_ne!(1, 2, "Failed: {:?}", panic!("debug_assert_ne! evaluated format expressions"));
}
<commit_msg>Ensure debug_assert! tests get run<commit_after>// run-pass
// compile-flags: -C debug_assertions=yes

#[allow(unreachable_code)]
fn main() {
    assert!(true, "Failed: {:?}", panic!("assert! evaluated format expressions"));
    debug_assert!(true, "Failed: {:?}", panic!("debug_assert! evaluated format expressions"));
    assert_eq!(1, 1, "Failed: {:?}", panic!("assert_eq! evaluated format expressions"));
    debug_assert_eq!(1, 1, "Failed: {:?}", panic!("debug_assert_eq! evaluated format expressions"));
    assert_ne!(1, 2, "Failed: {:?}", panic!("assert_ne! evaluated format expressions"));
    debug_assert_ne!(1, 2, "Failed: {:?}", panic!("debug_assert_ne! evaluated format expressions"));
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Gamma and derived distributions.

use core::num::Float;

use {Rng, Open01};
use super::normal::StandardNormal;
use super::{IndependentSample, Sample, Exp};

/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
/// The density function of this distribution is
///
/// ```text
/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
/// ```
///
/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
/// scale and both `k` and `θ` are strictly positive.
///
/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
/// falling back to directly sampling from an Exponential for `shape
/// == 1`, and using the boosting technique described in [1] for
/// `shape < 1`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{IndependentSample, Gamma};
///
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.ind_sample(&mut rand::task_rng());
/// println!("{} is from a Gamma(2, 5) distribution", v);
/// ```
///
/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000),
/// 363-372. DOI:[10.1145/358407.358414](http://doi.acm.org/10.1145/358407.358414)
pub struct Gamma {
    repr: GammaRepr,
}

enum GammaRepr {
    Large(GammaLargeShape),
    One(Exp),
    Small(GammaSmallShape)
}

// These two helpers could be made public, but saving the
// match-on-Gamma-enum branch from using them directly (e.g. if one
// knows that the shape is always > 1) doesn't appear to be much
// faster.

/// Gamma distribution where the shape parameter is less than 1.
///
/// Note, samples from this require a compulsory floating-point `pow`
/// call, which makes it significantly slower than sampling from a
/// gamma distribution where the shape parameter is greater than or
/// equal to 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaSmallShape {
    inv_shape: f64,
    large_shape: GammaLargeShape
}

/// Gamma distribution where the shape parameter is larger than 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaLargeShape {
    scale: f64,
    c: f64,
    d: f64
}

impl Gamma {
    /// Construct an object representing the `Gamma(shape, scale)`
    /// distribution.
    ///
    /// Fails if `shape <= 0` or `scale <= 0`.
    pub fn new(shape: f64, scale: f64) -> Gamma {
        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
        assert!(scale > 0.0, "Gamma::new called with scale <= 0");

        let repr = match shape {
            1.0        => One(Exp::new(1.0 / scale)),
            0.0 .. 1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
            _          => Large(GammaLargeShape::new_raw(shape, scale))
        };
        Gamma { repr: repr }
    }
}

impl GammaSmallShape {
    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
        GammaSmallShape {
            inv_shape: 1. / shape,
            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
        }
    }
}

impl GammaLargeShape {
    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
        let d = shape - 1. / 3.;
        GammaLargeShape {
            scale: scale,
            c: 1. / (9. * d).sqrt(),
            d: d
        }
    }
}

impl Sample<f64> for Gamma {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl Sample<f64> for GammaSmallShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl Sample<f64> for GammaLargeShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}

impl IndependentSample<f64> for Gamma {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            Small(ref g) => g.ind_sample(rng),
            One(ref g) => g.ind_sample(rng),
            Large(ref g) => g.ind_sample(rng),
        }
    }
}
impl IndependentSample<f64> for GammaSmallShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let Open01(u) = rng.gen::<Open01<f64>>();

        self.large_shape.ind_sample(rng) * u.powf(self.inv_shape)
    }
}
impl IndependentSample<f64> for GammaLargeShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        loop {
            let StandardNormal(x) = rng.gen::<StandardNormal>();
            let v_cbrt = 1.0 + self.c * x;
            if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
                continue
            }

            let v = v_cbrt * v_cbrt * v_cbrt;
            let Open01(u) = rng.gen::<Open01<f64>>();

            let x_sqr = x * x;
            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
                u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
                return self.d * v * self.scale
            }
        }
    }
}

/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
/// freedom.
///
/// For `k > 0` integral, this distribution is the sum of the squares
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterisation `χ²(k) = Gamma(k/2,
/// 2)`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{ChiSquared, IndependentSample};
///
/// let chi = ChiSquared::new(11.0);
/// let v = chi.ind_sample(&mut rand::task_rng());
/// println!("{} is from a χ²(11) distribution", v)
/// ```
pub struct ChiSquared {
    repr: ChiSquaredRepr,
}

enum ChiSquaredRepr {
    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
    // e.g. when alpha = 1/2 as it would be for this case, so special-
    // casing and using the definition of N(0,1)^2 is faster.
    DoFExactlyOne,
    DoFAnythingElse(Gamma),
}

impl ChiSquared {
    /// Create a new chi-squared distribution with degrees-of-freedom
    /// `k`. Fails if `k < 0`.
    pub fn new(k: f64) -> ChiSquared {
        let repr = if k == 1.0 {
            DoFExactlyOne
        } else {
            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
        };
        ChiSquared { repr: repr }
    }
}
impl Sample<f64> for ChiSquared {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for ChiSquared {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            DoFExactlyOne => {
                // k == 1 => N(0,1)^2
                let StandardNormal(norm) = rng.gen::<StandardNormal>();
                norm * norm
            }
            DoFAnythingElse(ref g) => g.ind_sample(rng)
        }
    }
}

/// The Fisher F distribution `F(m, n)`.
///
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{FisherF, IndependentSample};
///
/// let f = FisherF::new(2.0, 32.0);
/// let v = f.ind_sample(&mut rand::task_rng());
/// println!("{} is from an F(2, 32) distribution", v)
/// ```
pub struct FisherF {
    numer: ChiSquared,
    denom: ChiSquared,
    // denom_dof / numer_dof so that this can just be a straight
    // multiplication, rather than a division.
    dof_ratio: f64,
}

impl FisherF {
    /// Create a new `FisherF` distribution, with the given
    /// parameter. Fails if either `m` or `n` are not positive.
    pub fn new(m: f64, n: f64) -> FisherF {
        assert!(m > 0.0, "FisherF::new called with `m < 0`");
        assert!(n > 0.0, "FisherF::new called with `n < 0`");

        FisherF {
            numer: ChiSquared::new(m),
            denom: ChiSquared::new(n),
            dof_ratio: n / m
        }
    }
}
impl Sample<f64> for FisherF {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for FisherF {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
    }
}

/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{StudentT, IndependentSample};
///
/// let t = StudentT::new(11.0);
/// let v = t.ind_sample(&mut rand::task_rng());
/// println!("{} is from a t(11) distribution", v)
/// ```
pub struct StudentT {
    chi: ChiSquared,
    dof: f64
}

impl StudentT {
    /// Create a new Student t distribution with `n` degrees of
    /// freedom. Fails if `n <= 0`.
    pub fn new(n: f64) -> StudentT {
        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
        StudentT {
            chi: ChiSquared::new(n),
            dof: n
        }
    }
}
impl Sample<f64> for StudentT {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for StudentT {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let StandardNormal(norm) = rng.gen::<StandardNormal>();
        norm * (self.dof / self.chi.ind_sample(rng)).sqrt()
    }
}

#[cfg(test)]
mod test {
    use std::prelude::*;

    use distributions::{Sample, IndependentSample};
    use super::{ChiSquared, StudentT, FisherF};

    #[test]
    fn test_chi_squared_one() {
        let mut chi = ChiSquared::new(1.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_small() {
        let mut chi = ChiSquared::new(0.5);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_large() {
        let mut chi = ChiSquared::new(30.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    #[should_fail]
    fn test_chi_squared_invalid_dof() {
        ChiSquared::new(-1.0);
    }

    #[test]
    fn test_f() {
        let mut f = FisherF::new(2.0, 32.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            f.sample(&mut rng);
            f.ind_sample(&mut rng);
        }
    }

    #[test]
    fn test_t() {
        let mut t = StudentT::new(11.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            t.sample(&mut rng);
            t.ind_sample(&mut rng);
        }
    }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use std::prelude::*;
    use self::test::Bencher;
    use std::mem::size_of;
    use distributions::IndependentSample;
    use super::Gamma;

    #[bench]
    fn bench_gamma_large_shape(b: &mut Bencher) {
        let gamma = Gamma::new(10., 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in range(0, ::RAND_BENCH_N) {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }

    #[bench]
    fn bench_gamma_small_shape(b: &mut Bencher) {
        let gamma = Gamma::new(0.1, 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in range(0, ::RAND_BENCH_N) {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }
}
<commit_msg>Add a ton of ignore-lexer-test<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// ignore-lexer-test FIXME #15679

//! The Gamma and derived distributions.

use core::num::Float;

use {Rng, Open01};
use super::normal::StandardNormal;
use super::{IndependentSample, Sample, Exp};

/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
/// The density function of this distribution is
///
/// ```text
/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
/// ```
///
/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
/// scale and both `k` and `θ` are strictly positive.
///
/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
/// falling back to directly sampling from an Exponential for `shape
/// == 1`, and using the boosting technique described in [1] for
/// `shape < 1`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{IndependentSample, Gamma};
///
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.ind_sample(&mut rand::task_rng());
/// println!("{} is from a Gamma(2, 5) distribution", v);
/// ```
///
/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000),
/// 363-372. DOI:[10.1145/358407.358414](http://doi.acm.org/10.1145/358407.358414)
pub struct Gamma {
    repr: GammaRepr,
}

enum GammaRepr {
    Large(GammaLargeShape),
    One(Exp),
    Small(GammaSmallShape)
}

// These two helpers could be made public, but saving the
// match-on-Gamma-enum branch from using them directly (e.g. if one
// knows that the shape is always > 1) doesn't appear to be much
// faster.

/// Gamma distribution where the shape parameter is less than 1.
///
/// Note, samples from this require a compulsory floating-point `pow`
/// call, which makes it significantly slower than sampling from a
/// gamma distribution where the shape parameter is greater than or
/// equal to 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaSmallShape {
    inv_shape: f64,
    large_shape: GammaLargeShape
}

/// Gamma distribution where the shape parameter is larger than 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaLargeShape {
    scale: f64,
    c: f64,
    d: f64
}

impl Gamma {
    /// Construct an object representing the `Gamma(shape, scale)`
    /// distribution.
    ///
    /// Fails if `shape <= 0` or `scale <= 0`.
    pub fn new(shape: f64, scale: f64) -> Gamma {
        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
        assert!(scale > 0.0, "Gamma::new called with scale <= 0");

        let repr = match shape {
            1.0        => One(Exp::new(1.0 / scale)),
            0.0 .. 1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
            _          => Large(GammaLargeShape::new_raw(shape, scale))
        };
        Gamma { repr: repr }
    }
}

impl GammaSmallShape {
    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
        GammaSmallShape {
            inv_shape: 1. / shape,
            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
        }
    }
}

impl GammaLargeShape {
    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
        let d = shape - 1. / 3.;
        GammaLargeShape {
            scale: scale,
            c: 1. / (9. * d).sqrt(),
            d: d
        }
    }
}

impl Sample<f64> for Gamma {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl Sample<f64> for GammaSmallShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl Sample<f64> for GammaLargeShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}

impl IndependentSample<f64> for Gamma {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            Small(ref g) => g.ind_sample(rng),
            One(ref g) => g.ind_sample(rng),
            Large(ref g) => g.ind_sample(rng),
        }
    }
}
impl IndependentSample<f64> for GammaSmallShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let Open01(u) = rng.gen::<Open01<f64>>();

        self.large_shape.ind_sample(rng) * u.powf(self.inv_shape)
    }
}
impl IndependentSample<f64> for GammaLargeShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        loop {
            let StandardNormal(x) = rng.gen::<StandardNormal>();
            let v_cbrt = 1.0 + self.c * x;
            if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
                continue
            }

            let v = v_cbrt * v_cbrt * v_cbrt;
            let Open01(u) = rng.gen::<Open01<f64>>();

            let x_sqr = x * x;
            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
                u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
                return self.d * v * self.scale
            }
        }
    }
}

/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
/// freedom.
///
/// For `k > 0` integral, this distribution is the sum of the squares
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterisation `χ²(k) = Gamma(k/2,
/// 2)`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{ChiSquared, IndependentSample};
///
/// let chi = ChiSquared::new(11.0);
/// let v = chi.ind_sample(&mut rand::task_rng());
/// println!("{} is from a χ²(11) distribution", v)
/// ```
pub struct ChiSquared {
    repr: ChiSquaredRepr,
}

enum ChiSquaredRepr {
    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
    // e.g. when alpha = 1/2 as it would be for this case, so special-
    // casing and using the definition of N(0,1)^2 is faster.
    DoFExactlyOne,
    DoFAnythingElse(Gamma),
}

impl ChiSquared {
    /// Create a new chi-squared distribution with degrees-of-freedom
    /// `k`. Fails if `k < 0`.
    pub fn new(k: f64) -> ChiSquared {
        let repr = if k == 1.0 {
            DoFExactlyOne
        } else {
            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
        };
        ChiSquared { repr: repr }
    }
}
impl Sample<f64> for ChiSquared {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for ChiSquared {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            DoFExactlyOne => {
                // k == 1 => N(0,1)^2
                let StandardNormal(norm) = rng.gen::<StandardNormal>();
                norm * norm
            }
            DoFAnythingElse(ref g) => g.ind_sample(rng)
        }
    }
}

/// The Fisher F distribution `F(m, n)`.
///
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{FisherF, IndependentSample};
///
/// let f = FisherF::new(2.0, 32.0);
/// let v = f.ind_sample(&mut rand::task_rng());
/// println!("{} is from an F(2, 32) distribution", v)
/// ```
pub struct FisherF {
    numer: ChiSquared,
    denom: ChiSquared,
    // denom_dof / numer_dof so that this can just be a straight
    // multiplication, rather than a division.
    dof_ratio: f64,
}

impl FisherF {
    /// Create a new `FisherF` distribution, with the given
    /// parameter. Fails if either `m` or `n` are not positive.
    pub fn new(m: f64, n: f64) -> FisherF {
        assert!(m > 0.0, "FisherF::new called with `m < 0`");
        assert!(n > 0.0, "FisherF::new called with `n < 0`");

        FisherF {
            numer: ChiSquared::new(m),
            denom: ChiSquared::new(n),
            dof_ratio: n / m
        }
    }
}
impl Sample<f64> for FisherF {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for FisherF {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
    }
}

/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{StudentT, IndependentSample};
///
/// let t = StudentT::new(11.0);
/// let v = t.ind_sample(&mut rand::task_rng());
/// println!("{} is from a t(11) distribution", v)
/// ```
pub struct StudentT {
    chi: ChiSquared,
    dof: f64
}

impl StudentT {
    /// Create a new Student t distribution with `n` degrees of
    /// freedom. Fails if `n <= 0`.
    pub fn new(n: f64) -> StudentT {
        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
        StudentT {
            chi: ChiSquared::new(n),
            dof: n
        }
    }
}
impl Sample<f64> for StudentT {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for StudentT {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let StandardNormal(norm) = rng.gen::<StandardNormal>();
        norm * (self.dof / self.chi.ind_sample(rng)).sqrt()
    }
}

#[cfg(test)]
mod test {
    use std::prelude::*;

    use distributions::{Sample, IndependentSample};
    use super::{ChiSquared, StudentT, FisherF};

    #[test]
    fn test_chi_squared_one() {
        let mut chi = ChiSquared::new(1.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_small() {
        let mut chi = ChiSquared::new(0.5);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_large() {
        let mut chi = ChiSquared::new(30.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    #[should_fail]
    fn test_chi_squared_invalid_dof() {
        ChiSquared::new(-1.0);
    }

    #[test]
    fn test_f() {
        let mut f = FisherF::new(2.0, 32.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            f.sample(&mut rng);
            f.ind_sample(&mut rng);
        }
    }

    #[test]
    fn test_t() {
        let mut t = StudentT::new(11.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            t.sample(&mut rng);
            t.ind_sample(&mut rng);
        }
    }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use std::prelude::*;
    use self::test::Bencher;
    use std::mem::size_of;
    use distributions::IndependentSample;
    use super::Gamma;

    #[bench]
    fn bench_gamma_large_shape(b: &mut Bencher) {
        let gamma = Gamma::new(10., 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in range(0, ::RAND_BENCH_N) {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }

    #[bench]
    fn bench_gamma_small_shape(b: &mut Bencher) {
        let gamma = Gamma::new(0.1, 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in range(0, ::RAND_BENCH_N) {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }
}
<|endoftext|>