<commit_before>//! Functionality for precompiled accounts.

use bigint::{Address, Gas};

use errors::MachineError;
use ::{Memory, Machine, MachineStatus};

use std::str::FromStr;
use std::cmp::min;

use sha2::Sha256;
use sha3::Keccak256;
use ripemd160::Ripemd160;
use secp256k1::{SECP256K1, RecoverableSignature, Message, RecoveryId, Error};
use digest::{Digest, FixedOutput};

fn gas_div_ceil(a: Gas, b: Gas) -> Gas {
    if a % b == Gas::zero() {
        a / b
    } else {
        a / b + Gas::from(1u64)
    }
}

pub fn is_precompiled(address: Address) -> bool {
    let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
    let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
    let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
    let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

    address == ecrec_address ||
        address == sha256_address ||
        address == rip160_address ||
        address == id_address
}

impl<M: Memory + Default> Machine<M> {
    /// Step a precompiled runtime. This function returns true if the
    /// runtime is indeed a precompiled address. Otherwise return
    /// false with state unchanged.
    pub fn step_precompiled(&mut self) -> bool {
        let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
        let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
        let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
        let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

        if self.state.context.address == id_address {
            self.step_precompiled_id();
            return true;
        } else if self.state.context.address == rip160_address {
            self.step_precompiled_rip160();
            return true;
        } else if self.state.context.address == sha256_address {
            self.step_precompiled_sha256();
            return true;
        } else if self.state.context.address == ecrec_address {
            self.step_precompiled_ecrec();
            return true;
        } else {
            return false;
        }
    }

    fn step_precompiled_id(&mut self) {
        let gas = Gas::from(15u64) +
            Gas::from(3u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                           Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            self.state.out = self.state.context.data.clone();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_rip160(&mut self) {
        let gas = Gas::from(600u64) +
            Gas::from(120u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                             Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut ripemd = Ripemd160::default();
            ripemd.input(&self.state.context.data);
            let fixed = ripemd.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..20 {
                result[i + 12] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_sha256(&mut self) {
        let gas = Gas::from(60u64) +
            Gas::from(12u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                            Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut sha2 = Sha256::default();
            sha2.input(&self.state.context.data);
            let fixed = sha2.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..32 {
                result[i] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_ecrec(&mut self) {
        let gas = Gas::from(3000u64);
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut data = [0u8; 128];
            for i in 0..min(self.state.context.data.len(), 128) {
                data[i] = self.state.context.data[i];
            }
            match kececrec(&data) {
                Ok(mut ret) => {
                    for i in 0..12 {
                        ret[i] = 0u8;
                    }
                    self.state.out = ret.as_ref().into();
                },
                Err(_) => (),
            }
            self.status = MachineStatus::ExitedOk;
        }
    }
}

fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
    let message = Message::from_slice(&data[0..32])?;
    let recid_raw = match data[63] {
        27 | 28 if data[32..63] == [0; 31] => data[63] - 27,
        _ => return Err(Error::InvalidRecoveryId),
    };
    let recid = RecoveryId::from_i32(recid_raw as i32)?;
    let sig = RecoverableSignature::from_compact(&SECP256K1, &data[64..128], recid)?;
    let recovered = SECP256K1.recover(&message, &sig)?;
    let key = recovered.serialize_vec(&SECP256K1, false);

    let ret_generic = Keccak256::digest(&key[1..65]);
    let mut ret = [0u8; 32];

    for i in 0..32 {
        ret[i] = ret_generic[i];
    }

    Ok(ret)
}
<commit_msg>core: remove never used fn is_precompiled<commit_after>//! Functionality for precompiled accounts.

use bigint::{Address, Gas};

use errors::MachineError;
use ::{Memory, Machine, MachineStatus};

use std::str::FromStr;
use std::cmp::min;

use sha2::Sha256;
use sha3::Keccak256;
use ripemd160::Ripemd160;
use secp256k1::{SECP256K1, RecoverableSignature, Message, RecoveryId, Error};
use digest::{Digest, FixedOutput};

fn gas_div_ceil(a: Gas, b: Gas) -> Gas {
    if a % b == Gas::zero() {
        a / b
    } else {
        a / b + Gas::from(1u64)
    }
}

impl<M: Memory + Default> Machine<M> {
    /// Step a precompiled runtime. This function returns true if the
    /// runtime is indeed a precompiled address. Otherwise return
    /// false with state unchanged.
    pub fn step_precompiled(&mut self) -> bool {
        let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
        let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
        let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
        let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

        if self.state.context.address == id_address {
            self.step_precompiled_id();
            return true;
        } else if self.state.context.address == rip160_address {
            self.step_precompiled_rip160();
            return true;
        } else if self.state.context.address == sha256_address {
            self.step_precompiled_sha256();
            return true;
        } else if self.state.context.address == ecrec_address {
            self.step_precompiled_ecrec();
            return true;
        } else {
            return false;
        }
    }

    fn step_precompiled_id(&mut self) {
        let gas = Gas::from(15u64) +
            Gas::from(3u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                           Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            self.state.out = self.state.context.data.clone();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_rip160(&mut self) {
        let gas = Gas::from(600u64) +
            Gas::from(120u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                             Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut ripemd = Ripemd160::default();
            ripemd.input(&self.state.context.data);
            let fixed = ripemd.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..20 {
                result[i + 12] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_sha256(&mut self) {
        let gas = Gas::from(60u64) +
            Gas::from(12u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                            Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut sha2 = Sha256::default();
            sha2.input(&self.state.context.data);
            let fixed = sha2.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..32 {
                result[i] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_ecrec(&mut self) {
        let gas = Gas::from(3000u64);
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut data = [0u8; 128];
            for i in 0..min(self.state.context.data.len(), 128) {
                data[i] = self.state.context.data[i];
            }
            match kececrec(&data) {
                Ok(mut ret) => {
                    for i in 0..12 {
                        ret[i] = 0u8;
                    }
                    self.state.out = ret.as_ref().into();
                },
                Err(_) => (),
            }
            self.status = MachineStatus::ExitedOk;
        }
    }
}

fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
    let message = Message::from_slice(&data[0..32])?;
    let recid_raw = match data[63] {
        27 | 28 if data[32..63] == [0; 31] => data[63] - 27,
        _ => return Err(Error::InvalidRecoveryId),
    };
    let recid = RecoveryId::from_i32(recid_raw as i32)?;
    let sig = RecoverableSignature::from_compact(&SECP256K1, &data[64..128], recid)?;
    let recovered = SECP256K1.recover(&message, &sig)?;
    let key = recovered.serialize_vec(&SECP256K1, false);

    let ret_generic = Keccak256::digest(&key[1..65]);
    let mut ret = [0u8; 32];

    for i in 0..32 {
        ret[i] = ret_generic[i];
    }

    Ok(ret)
}
<|endoftext|>


<commit_before>#[link(name = "compress")];
#[deny(warnings)];
#[deny(missing_doc)];

//! dox (placeholder)

extern mod extra;

//mod flate;
pub mod lz4;
<commit_msg>Using new pkgid syntax<commit_after>#[pkgid = "compress"];
#[deny(warnings)];
#[deny(missing_doc)];

//! dox (placeholder)

extern mod extra;

//mod flate;
pub mod lz4;
<|endoftext|>


<commit_before>// Copyright 2014 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.

/*!
Syntax extension to generate FourCCs.

Once loaded, fourcc!() is called with a single 4-character string,
and an optional ident that is either `big`, `little`, or `target`.
The ident represents endianness, and specifies in which direction
the characters should be read. If the ident is omitted, it is assumed
to be `big`, i.e. left-to-right order. It returns a u32.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(syntax)]
extern crate fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!");
    assert_eq!(val, 0xC0FFEE21u32);
    let little_val = fourcc!("foo ", little);
    assert_eq!(little_val, 0x21EEFFC0u32);
}
 ```

# References

* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC)

*/

#[crate_id = "fourcc#0.10-pre"];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
      html_root_url = "http://static.rust-lang.org/doc/master")];

#[feature(macro_registrar, managed_boxes)];

extern crate syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("fourcc"),
        NormalTT(~BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
    let (expr, endian) = parse_tts(cx, tts);

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "little" => true,
            "big" => false,
            "target" => target_endian_little(cx, sp),
            _ => {
                cx.span_err(span, "invalid endian directive in fourcc!");
                target_endian_little(cx, sp)
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                if s.get().char_len() != 4 {
                    cx.span_err(expr.span, "string literal with len != 4 in fourcc!");
                }
                s
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in fourcc!");
                return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
        }
    };

    let mut val = 0u32;
    for codepoint in s.get().chars().take(4) {
        let byte = if codepoint as u32 > 0xFF {
            cx.span_err(expr.span, "fourcc! literal character out of range 0-255");
            0u8
        } else {
            codepoint as u8
        };

        val = if little {
            (val >> 8) | ((byte as u32) << 24)
        } else {
            (val << 8) | (byte as u32)
        };
    }
    let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
    MRExpr(e)
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
                                               .map(|x| (*x).clone())
                                               .collect());
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
    let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
        ast::LitStr(InternedString::new("little"), ast::CookedStr));
    contains(cx.cfg().as_slice(), meta)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<commit_msg>Add #[deny(deprecated_owned_vector)] to several modules.<commit_after>// Copyright 2014 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.

/*!
Syntax extension to generate FourCCs.

Once loaded, fourcc!() is called with a single 4-character string,
and an optional ident that is either `big`, `little`, or `target`.
The ident represents endianness, and specifies in which direction
the characters should be read. If the ident is omitted, it is assumed
to be `big`, i.e. left-to-right order. It returns a u32.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(syntax)]
extern crate fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!");
    assert_eq!(val, 0xC0FFEE21u32);
    let little_val = fourcc!("foo ", little);
    assert_eq!(little_val, 0x21EEFFC0u32);
}
 ```

# References

* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC)

*/

#[crate_id = "fourcc#0.10-pre"];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
      html_root_url = "http://static.rust-lang.org/doc/master")];

#[deny(deprecated_owned_vector)];
#[feature(macro_registrar, managed_boxes)];

extern crate syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("fourcc"),
        NormalTT(~BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
    let (expr, endian) = parse_tts(cx, tts);

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "little" => true,
            "big" => false,
            "target" => target_endian_little(cx, sp),
            _ => {
                cx.span_err(span, "invalid endian directive in fourcc!");
                target_endian_little(cx, sp)
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                if s.get().char_len() != 4 {
                    cx.span_err(expr.span, "string literal with len != 4 in fourcc!");
                }
                s
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in fourcc!");
                return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
        }
    };

    let mut val = 0u32;
    for codepoint in s.get().chars().take(4) {
        let byte = if codepoint as u32 > 0xFF {
            cx.span_err(expr.span, "fourcc! literal character out of range 0-255");
            0u8
        } else {
            codepoint as u8
        };

        val = if little {
            (val >> 8) | ((byte as u32) << 24)
        } else {
            (val << 8) | (byte as u32)
        };
    }
    let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
    MRExpr(e)
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
                                               .map(|x| (*x).clone())
                                               .collect());
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
    let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
        ast::LitStr(InternedString::new("little"), ast::CookedStr));
    contains(cx.cfg().as_slice(), meta)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<|endoftext|>


<commit_before>#![crate_id = "compress#0.1"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![comment = "Various compression algorithms written in rust."]
#![deny(missing_doc)]
#![feature(macro_rules, phase)]

//! dox (placeholder)

#[phase(plugin, link)]
extern crate log;
extern crate debug;

#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate test;

/// Public exports
pub use Adler32 = self::checksum::adler::State32;

/// Checksum algorithms
// http://en.wikipedia.org/wiki/Checksum
pub mod checksum {
    pub mod adler;
}

pub mod bwt;
pub mod flate;
pub mod lz4;
pub mod zlib;

/// Entropy coder family
// http://en.wikipedia.org/wiki/Entropy_encoding
pub mod entropy {
    pub mod ari;
}
<commit_msg>crate_id => crate_name<commit_after>#![crate_name = "compress#0.1"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![comment = "Various compression algorithms written in rust."]
#![deny(missing_doc)]
#![feature(macro_rules, phase)]

//! dox (placeholder)

#[phase(plugin, link)]
extern crate log;
extern crate debug;

#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate test;

/// Public exports
pub use Adler32 = self::checksum::adler::State32;

/// Checksum algorithms
// http://en.wikipedia.org/wiki/Checksum
pub mod checksum {
    pub mod adler;
}

pub mod bwt;
pub mod flate;
pub mod lz4;
pub mod zlib;

/// Entropy coder family
// http://en.wikipedia.org/wiki/Entropy_encoding
pub mod entropy {
    pub mod ari;
}
<|endoftext|>


<commit_before>extern crate sled;
extern crate coco;
extern crate rand;
extern crate quickcheck;

use std::collections::HashMap;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};

use quickcheck::{Arbitrary, Gen, QuickCheck, StdGen};
use coco::epoch::Ptr;

use sled::*;

type PageID = usize;

#[derive(Clone)]
pub struct TestMaterializer;

impl Materializer for TestMaterializer {
    type PageFrag = Vec<usize>;
    type Recovery = ();

    fn merge(&self, frags: &[&Vec<usize>]) -> Vec<usize> {
        let mut consolidated = vec![];
        for &frag in frags.iter() {
            let mut frag = frag.clone();
            consolidated.append(&mut frag);
        }

        consolidated
    }

    fn recover(&self, _: &Vec<usize>) -> Option<()> {
        None
    }
}

#[test]
fn test_cache() {
    let conf = Config::default().cache_capacity(40).cache_bits(0);

    let mut pc = PageCache::new(TestMaterializer, conf.clone());
    pc.recover();

    let mut keys = HashMap::new();
    for _ in 0..2 {
        let (id, key) = pc.allocate();
        let key = pc.set(id, key, vec![0]).unwrap();
        keys.insert(id, key);
    }

    for i in 0..1000 {
        let id = i as usize % 2;
        let (_, key) = pc.get(id).unwrap();
        let key = pc.merge(id, key, vec![i]).unwrap();
        keys.insert(id, key);
    }
}

#[test]
fn basic_recovery() {
    let conf = Config::default().flush_every_ms(None);

    let mut pc = PageCache::new(TestMaterializer, conf.clone());
    pc.recover();
    let (id, key) = pc.allocate();
    let key = pc.set(id, key, vec![1]).unwrap();
    let key = pc.merge(id, key, vec![2]).unwrap();
    let _key = pc.merge(id, key, vec![3]).unwrap();
    let (consolidated, _) = pc.get(id).unwrap();
    assert_eq!(consolidated, vec![1, 2, 3]);
    drop(pc);

    let mut pc2 = PageCache::new(TestMaterializer, conf.clone());
    pc2.recover();
    let (consolidated2, key) = pc2.get(id).unwrap();
    assert_eq!(consolidated, consolidated2);

    pc2.merge(id, key, vec![4]).unwrap();
    drop(pc2);

    let mut pc3 = PageCache::new(TestMaterializer, conf.clone());
    pc3.recover();
    let (consolidated3, _key) = pc3.get(id).unwrap();
    assert_eq!(consolidated3, vec![1, 2, 3, 4]);
    pc3.free(id);
    drop(pc3);

    let mut pc4 = PageCache::new(TestMaterializer, conf.clone());
    pc4.recover();
    let res = pc4.get(id);
    assert!(res.is_none());
}

#[derive(Debug, Clone)]
enum Op {
    Set(PageID, usize),
    Merge(PageID, usize),
    Get(PageID),
    Free(PageID),
    Allocate,
    Restart,
}

impl Arbitrary for Op {
    fn arbitrary<G: Gen>(g: &mut G) -> Op {
        if g.gen_weighted_bool(10) {
            return Op::Restart;
        }

        let choice = g.gen_range(0, 5);

        static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
        COUNTER.compare_and_swap(0, 1, Ordering::SeqCst);

        let pid = (g.gen::<u8>() % 8) as PageID;

        match choice {
            0 => Op::Set(pid, COUNTER.fetch_add(1, Ordering::Relaxed)),
            1 => Op::Merge(pid, COUNTER.fetch_add(1, Ordering::Relaxed)),
            2 => Op::Get(pid),
            3 => Op::Free(pid),
            4 => Op::Allocate,
            _ => panic!("impossible choice"),
        }
    }
}

#[derive(Debug, Clone)]
struct OpVec {
    ops: Vec<Op>,
}

impl Arbitrary for OpVec {
    fn arbitrary<G: Gen>(g: &mut G) -> OpVec {
        let mut ops = vec![];
        for _ in 0..g.gen_range(1, 50) {
            let op = Op::arbitrary(g);
            ops.push(op);

        }
        OpVec {
            ops: ops,
        }
    }

    fn shrink(&self) -> Box<Iterator<Item = OpVec>> {
        let mut smaller = vec![];
        for i in 0..self.ops.len() {
            let mut clone = self.clone();
            clone.ops.remove(i);
            smaller.push(clone);
        }

        let mut clone = self.clone();
        let mut lowered = false;
        for op in clone.ops.iter_mut() {
            match *op {
                Op::Set(ref mut pid, _) |
                Op::Merge(ref mut pid, _) |
                Op::Get(ref mut pid) |
                Op::Free(ref mut pid) if *pid > 0 => {
                    lowered = true;
                    *pid -= 1;
                }
                _ => {}
            }
        }
        if lowered {
            smaller.push(clone);
        }

        Box::new(smaller.into_iter())
    }
}

fn prop_pagecache_works(ops: OpVec, cache_fixup_threshold: u8) -> bool {
    use self::Op::*;
    let config = Config::default()
        .io_buf_size(1024 * 8)
        .cache_bits(0)
        .cache_capacity(40)
        .cache_fixup_threshold(cache_fixup_threshold as usize);

    let mut pc = PageCache::new(TestMaterializer, config.clone());
    pc.recover();

    let mut reference: HashMap<PageID, Vec<usize>> = HashMap::new();

    let bad_addr = 1 << std::mem::align_of::<Vec<usize>>().trailing_zeros();
    let bad_ptr = unsafe { Ptr::from_raw(bad_addr as *mut _) };

    for op in ops.ops.into_iter() {
        match op {
            Set(pid, c) => {
                let present = reference.contains_key(&pid);

                if present {
                    let ref mut existing = reference.get_mut(&pid).unwrap();
                    let old_key = if existing.is_empty() {
                        Ptr::null().into()
                    } else {
                        let (_, old_key) = pc.get(pid).unwrap();
                        old_key
                    };

                    pc.set(pid, old_key.clone(), vec![c]).unwrap();
                    existing.clear();
                    existing.push(c);
                } else {
                    let res = pc.set(pid, bad_ptr.into(), vec![c]);
                    assert_eq!(res, Err(None));
                }
            }
            Merge(pid, c) => {
                let present = reference.contains_key(&pid);

                if present {
                    let ref mut existing = reference.get_mut(&pid).unwrap();
                    let old_key = if existing.is_empty() {
                        Ptr::null().into()
                    } else {
                        let (_, old_key) = pc.get(pid).unwrap();
                        old_key
                    };

                    pc.merge(pid, old_key.clone(), vec![c]).unwrap();
                    existing.push(c);
                } else {
                    let res = pc.merge(pid, bad_ptr.into(), vec![c]);
                    assert_eq!(res, Err(None));
                }
            }
            Get(pid) => {
                let r = reference.get(&pid).cloned();
                let a = pc.get(pid).map(|(a, _)| a);
                if let Some(ref s) = r {
                    if s.is_empty() {
                        assert_eq!(a, None);
                    } else {
                        assert_eq!(r, a);
                        let values = a.unwrap();
                        values.iter().fold(0, |acc, cur| {
                            if *cur <= acc {
                                panic!("out of order page fragments in page!");
                            }
                            *cur
                        });
                    }
                } else {
                    assert_eq!(None, a);
                }
            }
            Free(pid) => {
                pc.free(pid);
                reference.remove(&pid);
            }
            Allocate => {
                let (pid, _key) = pc.allocate();
                reference.insert(pid, vec![]);
            }
            Restart => {
                drop(pc);
                pc = PageCache::new(TestMaterializer, config.clone());
                pc.recover();
            }
        }
    }

    true
}

#[test]
fn quickcheck_pagecache_works() {
    QuickCheck::new()
        .gen(StdGen::new(rand::thread_rng(), 1))
        .tests(50)
        .max_tests(100)
        .quickcheck(prop_pagecache_works as fn(OpVec, u8) -> bool);
}

#[test]
fn test_pagecache_bug_1() {
    // postmortem: this happened because `PageCache::page_in` assumed
    // at least one update had been stored for a retrieved page.
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Get(0)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_2() {
    // postmortem: historically needed to "seed" a page by writing
    // a compacting base to it. changed the snapshot and page-in code
    // to allow a merge being the first update to hit a page.
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Restart, Merge(0, 1)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_3() {
    // postmortem: this was a mismatch in semantics in the test harness itself
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Get(0)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_4() {
    // postmortem: previously this caused a panic, we shouldn't break
    // when the user asks us to mutate non-existant pages!
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Merge(98, 1)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_5() {
    // postmortem: this was a mismatch in semantics in the test harness itself
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Merge(132, 1), Set(132, 1)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_6() {
    // postmortem: the test wasn't actually recording changes to the reference page...
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Set(0, 53), Set(0, 54)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_7() {
    // postmortem: the test wasn't correctly recording the replacement effect of a set
    // in the reference page
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Merge(0, 201), Set(0, 208), Get(0)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_8() {
    // postmortem: page_in messed up the stack ordering when storing a merged stack
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![
                Allocate,
                Set(0, 188),
                Allocate,
                Merge(1, 196),
                Merge(1, 198),
                Merge(1, 200),
                Merge(0, 201),
                Get(1),
            ],
        },
        0,
    );
}

fn _test_pagecache_bug_() {
    // postmortem: TEMPLATE
    // use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![],
        },
        0,
    );
}
<commit_msg>add failing pagecache test<commit_after>extern crate sled;
extern crate coco;
extern crate rand;
extern crate quickcheck;

use std::collections::HashMap;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};

use quickcheck::{Arbitrary, Gen, QuickCheck, StdGen};
use coco::epoch::Ptr;

use sled::*;

type PageID = usize;

#[derive(Clone)]
pub struct TestMaterializer;

impl Materializer for TestMaterializer {
    type PageFrag = Vec<usize>;
    type Recovery = ();

    fn merge(&self, frags: &[&Vec<usize>]) -> Vec<usize> {
        let mut consolidated = vec![];
        for &frag in frags.iter() {
            let mut frag = frag.clone();
            consolidated.append(&mut frag);
        }

        consolidated
    }

    fn recover(&self, _: &Vec<usize>) -> Option<()> {
        None
    }
}

#[test]
fn test_cache() {
    let conf = Config::default().cache_capacity(40).cache_bits(0);

    let mut pc = PageCache::new(TestMaterializer, conf.clone());
    pc.recover();

    let mut keys = HashMap::new();
    for _ in 0..2 {
        let (id, key) = pc.allocate();
        let key = pc.set(id, key, vec![0]).unwrap();
        keys.insert(id, key);
    }

    for i in 0..1000 {
        let id = i as usize % 2;
        let (_, key) = pc.get(id).unwrap();
        let key = pc.merge(id, key, vec![i]).unwrap();
        keys.insert(id, key);
    }
}

#[test]
fn basic_recovery() {
    let conf = Config::default().flush_every_ms(None);

    let mut pc = PageCache::new(TestMaterializer, conf.clone());
    pc.recover();
    let (id, key) = pc.allocate();
    let key = pc.set(id, key, vec![1]).unwrap();
    let key = pc.merge(id, key, vec![2]).unwrap();
    let _key = pc.merge(id, key, vec![3]).unwrap();
    let (consolidated, _) = pc.get(id).unwrap();
    assert_eq!(consolidated, vec![1, 2, 3]);
    drop(pc);

    let mut pc2 = PageCache::new(TestMaterializer, conf.clone());
    pc2.recover();
    let (consolidated2, key) = pc2.get(id).unwrap();
    assert_eq!(consolidated, consolidated2);

    pc2.merge(id, key, vec![4]).unwrap();
    drop(pc2);

    let mut pc3 = PageCache::new(TestMaterializer, conf.clone());
    pc3.recover();
    let (consolidated3, _key) = pc3.get(id).unwrap();
    assert_eq!(consolidated3, vec![1, 2, 3, 4]);
    pc3.free(id);
    drop(pc3);

    let mut pc4 = PageCache::new(TestMaterializer, conf.clone());
    pc4.recover();
    let res = pc4.get(id);
    assert!(res.is_none());
}

#[derive(Debug, Clone)]
enum Op {
    Set(PageID, usize),
    Merge(PageID, usize),
    Get(PageID),
    Free(PageID),
    Allocate,
    Restart,
}

impl Arbitrary for Op {
    fn arbitrary<G: Gen>(g: &mut G) -> Op {
        if g.gen_weighted_bool(10) {
            return Op::Restart;
        }

        let choice = g.gen_range(0, 5);

        static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
        COUNTER.compare_and_swap(0, 1, Ordering::SeqCst);

        let pid = (g.gen::<u8>() % 8) as PageID;

        match choice {
            0 => Op::Set(pid, COUNTER.fetch_add(1, Ordering::Relaxed)),
            1 => Op::Merge(pid, COUNTER.fetch_add(1, Ordering::Relaxed)),
            2 => Op::Get(pid),
            3 => Op::Free(pid),
            4 => Op::Allocate,
            _ => panic!("impossible choice"),
        }
    }
}

#[derive(Debug, Clone)]
struct OpVec {
    ops: Vec<Op>,
}

impl Arbitrary for OpVec {
    fn arbitrary<G: Gen>(g: &mut G) -> OpVec {
        let mut ops = vec![];
        for _ in 0..g.gen_range(1, 50) {
            let op = Op::arbitrary(g);
            ops.push(op);

        }
        OpVec {
            ops: ops,
        }
    }

    fn shrink(&self) -> Box<Iterator<Item = OpVec>> {
        let mut smaller = vec![];
        for i in 0..self.ops.len() {
            let mut clone = self.clone();
            clone.ops.remove(i);
            smaller.push(clone);
        }

        let mut clone = self.clone();
        let mut lowered = false;
        for op in clone.ops.iter_mut() {
            match *op {
                Op::Set(ref mut pid, _) |
                Op::Merge(ref mut pid, _) |
                Op::Get(ref mut pid) |
                Op::Free(ref mut pid) if *pid > 0 => {
                    lowered = true;
                    *pid -= 1;
                }
                _ => {}
            }
        }
        if lowered {
            smaller.push(clone);
        }

        Box::new(smaller.into_iter())
    }
}

fn prop_pagecache_works(ops: OpVec, cache_fixup_threshold: u8) -> bool {
    use self::Op::*;
    let config = Config::default()
        .io_buf_size(1024 * 8)
        .cache_bits(0)
        .cache_capacity(40)
        .cache_fixup_threshold(cache_fixup_threshold as usize);

    let mut pc = PageCache::new(TestMaterializer, config.clone());
    pc.recover();

    let mut reference: HashMap<PageID, Vec<usize>> = HashMap::new();

    let bad_addr = 1 << std::mem::align_of::<Vec<usize>>().trailing_zeros();
    let bad_ptr = unsafe { Ptr::from_raw(bad_addr as *mut _) };

    for op in ops.ops.into_iter() {
        match op {
            Set(pid, c) => {
                let present = reference.contains_key(&pid);

                if present {
                    let ref mut existing = reference.get_mut(&pid).unwrap();
                    let old_key = if existing.is_empty() {
                        Ptr::null().into()
                    } else {
                        let (_, old_key) = pc.get(pid).unwrap();
                        old_key
                    };

                    pc.set(pid, old_key.clone(), vec![c]).unwrap();
                    existing.clear();
                    existing.push(c);
                } else {
                    let res = pc.set(pid, bad_ptr.into(), vec![c]);
                    assert_eq!(res, Err(None));
                }
            }
            Merge(pid, c) => {
                let present = reference.contains_key(&pid);

                if present {
                    let ref mut existing = reference.get_mut(&pid).unwrap();
                    let old_key = if existing.is_empty() {
                        Ptr::null().into()
                    } else {
                        let (_, old_key) = pc.get(pid).unwrap();
                        old_key
                    };

                    pc.merge(pid, old_key.clone(), vec![c]).unwrap();
                    existing.push(c);
                } else {
                    let res = pc.merge(pid, bad_ptr.into(), vec![c]);
                    assert_eq!(res, Err(None));
                }
            }
            Get(pid) => {
                let r = reference.get(&pid).cloned();
                let a = pc.get(pid).map(|(a, _)| a);
                if let Some(ref s) = r {
                    if s.is_empty() {
                        assert_eq!(a, None);
                    } else {
                        assert_eq!(r, a);
                        let values = a.unwrap();
                        values.iter().fold(0, |acc, cur| {
                            if *cur <= acc {
                                panic!("out of order page fragments in page!");
                            }
                            *cur
                        });
                    }
                } else {
                    assert_eq!(None, a);
                }
            }
            Free(pid) => {
                pc.free(pid);
                reference.remove(&pid);
            }
            Allocate => {
                let (pid, _key) = pc.allocate();
                reference.insert(pid, vec![]);
            }
            Restart => {
                drop(pc);
                pc = PageCache::new(TestMaterializer, config.clone());
                pc.recover();
            }
        }
    }

    true
}

#[test]
fn quickcheck_pagecache_works() {
    QuickCheck::new()
        .gen(StdGen::new(rand::thread_rng(), 1))
        .tests(50)
        .max_tests(100)
        .quickcheck(prop_pagecache_works as fn(OpVec, u8) -> bool);
}

#[test]
fn test_pagecache_bug_1() {
    // postmortem: this happened because `PageCache::page_in` assumed
    // at least one update had been stored for a retrieved page.
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Get(0)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_2() {
    // postmortem: historically needed to "seed" a page by writing
    // a compacting base to it. changed the snapshot and page-in code
    // to allow a merge being the first update to hit a page.
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Restart, Merge(0, 1)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_3() {
    // postmortem: this was a mismatch in semantics in the test harness itself
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Get(0)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_4() {
    // postmortem: previously this caused a panic, we shouldn't break
    // when the user asks us to mutate non-existant pages!
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Merge(98, 1)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_5() {
    // postmortem: this was a mismatch in semantics in the test harness itself
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Merge(132, 1), Set(132, 1)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_6() {
    // postmortem: the test wasn't actually recording changes to the reference page...
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Set(0, 53), Set(0, 54)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_7() {
    // postmortem: the test wasn't correctly recording the replacement effect of a set
    // in the reference page
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![Allocate, Merge(0, 201), Set(0, 208), Get(0)],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_8() {
    // postmortem: page_in messed up the stack ordering when storing a merged stack
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![
                Allocate,
                Set(0, 188),
                Allocate,
                Merge(1, 196),
                Merge(1, 198),
                Merge(1, 200),
                Merge(0, 201),
                Get(1),
            ],
        },
        0,
    );
}

#[test]
fn test_pagecache_bug_9() {
    // postmortem:
    use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![
                Allocate,
                Allocate,
                Merge(1, 208),
                Merge(1, 211),
                Merge(0, 212),
                Set(0, 213),
                Set(1, 214),
            ],
        },
        0,
    );
}

fn _test_pagecache_bug_() {
    // postmortem: TEMPLATE
    // use Op::*;
    prop_pagecache_works(
        OpVec {
            ops: vec![],
        },
        0,
    );
}
<|endoftext|>


<commit_before>//! Tests for cargo's help output.

use cargo_test_support::registry::Package;
use cargo_test_support::{basic_manifest, cargo_exe, cargo_process, paths, process, project};
use std::fs;
use std::path::Path;
use std::str::from_utf8;

#[cargo_test]
fn help() {
    cargo_process("").run();
    cargo_process("help").run();
    cargo_process("-h").run();
    cargo_process("help build").run();
    cargo_process("build -h").run();
    cargo_process("help help").run();
    // Ensure that help output goes to stdout, not stderr.
    cargo_process("search --help").with_stderr("").run();
    cargo_process("search --help")
        .with_stdout_contains("[..] --frozen [..]")
        .run();
}

#[cargo_test]
fn help_external_subcommand() {
    // Check that `help external-subcommand` forwards the --help flag to the
    // given subcommand.
    Package::new("cargo-fake-help", "1.0.0")
        .file(
            "src/main.rs",
            r#"
            fn main() {
                if ::std::env::args().nth(2) == Some(String::from("--help")) {
                    println!("fancy help output");
                }
            }
            "#,
        )
        .publish();
    cargo_process("install cargo-fake-help").run();
    cargo_process("help fake-help")
        .with_stdout("fancy help output\n")
        .run();
}

#[cargo_test]
fn z_flags_help() {
    // Test that the output of `cargo -Z help` shows a different help screen with
    // all the `-Z` flags.
    cargo_process("-Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();
}

fn help_with_man(display_command: &str) {
    // Build a "man" process that just echoes the contents.
    let p = project()
        .at(display_command)
        .file("Cargo.toml", &basic_manifest(display_command, "1.0.0"))
        .file(
            "src/main.rs",
            &r#"
                fn main() {
                    eprintln!("custom __COMMAND__");
                    let path = std::env::args().skip(1).next().unwrap();
                    let mut f = std::fs::File::open(path).unwrap();
                    std::io::copy(&mut f, &mut std::io::stdout()).unwrap();
                }
            "#
            .replace("__COMMAND__", display_command),
        )
        .build();
    p.cargo("build").run();

    help_with_man_and_path(display_command, "build", "build", &p.target_debug_dir());
}

fn help_with_man_and_path(
    display_command: &str,
    subcommand: &str,
    actual_subcommand: &str,
    path: &Path,
) {
    let contents = if display_command == "man" {
        fs::read_to_string(format!("src/etc/man/cargo-{}.1", actual_subcommand)).unwrap()
    } else {
        fs::read_to_string(format!(
            "src/doc/man/generated_txt/cargo-{}.txt",
            actual_subcommand
        ))
        .unwrap()
    };

    let output = process(&cargo_exe())
        .arg("help")
        .arg(subcommand)
        .env("PATH", path)
        .exec_with_output()
        .unwrap();
    assert!(output.status.success());
    let stderr = from_utf8(&output.stderr).unwrap();
    if display_command.is_empty() {
        assert_eq!(stderr, "");
    } else {
        assert_eq!(stderr, format!("custom {}\n", display_command));
    }
    let stdout = from_utf8(&output.stdout).unwrap();
    assert_eq!(stdout, contents);
}

#[cargo_test]
fn help_man() {
    // Checks that `help command` displays the man page using the given command.
    help_with_man("man");
    help_with_man("less");
    help_with_man("more");

    // Check with no commands in PATH.
    help_with_man_and_path("", "build", "build", Path::new(""));
}

#[cargo_test]
fn help_alias() {
    // Check that `help some_alias` will resolve.
    help_with_man_and_path("", "b", "build", Path::new(""));

    let config = paths::root().join(".cargo/config");
    fs::create_dir_all(config.parent().unwrap()).unwrap();
    fs::write(
        config,
        r#"
            [alias]
            my-alias = ["build", "--release"]
        "#,
    )
    .unwrap();
    help_with_man_and_path("", "my-alias", "build", Path::new(""));
}

#[cargo_test]
fn alias_z_flag_help() {
    cargo_process("build -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("run -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("check -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("test -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("b -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("r -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("c -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("t -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();
}
<commit_msg>Update help::help_alias() to assert the new behavior<commit_after>//! Tests for cargo's help output.

use cargo_test_support::registry::Package;
use cargo_test_support::{basic_manifest, cargo_exe, cargo_process, paths, process, project};
use std::fs;
use std::path::Path;
use std::str::from_utf8;

#[cargo_test]
fn help() {
    cargo_process("").run();
    cargo_process("help").run();
    cargo_process("-h").run();
    cargo_process("help build").run();
    cargo_process("build -h").run();
    cargo_process("help help").run();
    // Ensure that help output goes to stdout, not stderr.
    cargo_process("search --help").with_stderr("").run();
    cargo_process("search --help")
        .with_stdout_contains("[..] --frozen [..]")
        .run();
}

#[cargo_test]
fn help_external_subcommand() {
    // Check that `help external-subcommand` forwards the --help flag to the
    // given subcommand.
    Package::new("cargo-fake-help", "1.0.0")
        .file(
            "src/main.rs",
            r#"
            fn main() {
                if ::std::env::args().nth(2) == Some(String::from("--help")) {
                    println!("fancy help output");
                }
            }
            "#,
        )
        .publish();
    cargo_process("install cargo-fake-help").run();
    cargo_process("help fake-help")
        .with_stdout("fancy help output\n")
        .run();
}

#[cargo_test]
fn z_flags_help() {
    // Test that the output of `cargo -Z help` shows a different help screen with
    // all the `-Z` flags.
    cargo_process("-Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();
}

fn help_with_man(display_command: &str) {
    // Build a "man" process that just echoes the contents.
    let p = project()
        .at(display_command)
        .file("Cargo.toml", &basic_manifest(display_command, "1.0.0"))
        .file(
            "src/main.rs",
            &r#"
                fn main() {
                    eprintln!("custom __COMMAND__");
                    let path = std::env::args().skip(1).next().unwrap();
                    let mut f = std::fs::File::open(path).unwrap();
                    std::io::copy(&mut f, &mut std::io::stdout()).unwrap();
                }
            "#
            .replace("__COMMAND__", display_command),
        )
        .build();
    p.cargo("build").run();

    help_with_man_and_path(display_command, "build", "build", &p.target_debug_dir());
}

fn help_with_man_and_path(
    display_command: &str,
    subcommand: &str,
    actual_subcommand: &str,
    path: &Path,
) {
    let contents = if display_command == "man" {
        fs::read_to_string(format!("src/etc/man/cargo-{}.1", actual_subcommand)).unwrap()
    } else {
        fs::read_to_string(format!(
            "src/doc/man/generated_txt/cargo-{}.txt",
            actual_subcommand
        ))
        .unwrap()
    };

    let output = process(&cargo_exe())
        .arg("help")
        .arg(subcommand)
        .env("PATH", path)
        .exec_with_output()
        .unwrap();
    assert!(output.status.success());
    let stderr = from_utf8(&output.stderr).unwrap();
    if display_command.is_empty() {
        assert_eq!(stderr, "");
    } else {
        assert_eq!(stderr, format!("custom {}\n", display_command));
    }
    let stdout = from_utf8(&output.stdout).unwrap();
    assert_eq!(stdout, contents);
}

fn help_with_stdout_and_path(subcommand: &str, path: &Path) -> String {
    let output = process(&cargo_exe())
        .arg("help")
        .arg(subcommand)
        .env("PATH", path)
        .exec_with_output()
        .unwrap();
    assert!(output.status.success());
    let stderr = from_utf8(&output.stderr).unwrap();
    assert_eq!(stderr, "");
    let stdout = from_utf8(&output.stdout).unwrap();
    stdout.to_string()
}

#[cargo_test]
fn help_man() {
    // Checks that `help command` displays the man page using the given command.
    help_with_man("man");
    help_with_man("less");
    help_with_man("more");

    // Check with no commands in PATH.
    help_with_man_and_path("", "build", "build", Path::new(""));
}

#[cargo_test]
fn help_alias() {
    // Check that `help some_alias` will resolve.
    let out = help_with_stdout_and_path("b", Path::new(""));
    assert_eq!(out, "'b' is aliased to 'build'\n");

    let config = paths::root().join(".cargo/config");
    fs::create_dir_all(config.parent().unwrap()).unwrap();
    fs::write(
        config,
        r#"
            [alias]
            my-alias = ["build", "--release"]
        "#,
    )
    .unwrap();
    let out = help_with_stdout_and_path("my-alias", Path::new(""));
    assert_eq!(out, "'my-alias' is aliased to 'build --release'\n");
}

#[cargo_test]
fn alias_z_flag_help() {
    cargo_process("build -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("run -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("check -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("test -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("b -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("r -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("c -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();

    cargo_process("t -Z help")
        .with_stdout_contains(
            "    -Z allow-features[..]-- Allow *only* the listed unstable features",
        )
        .run();
}
<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![forbid(unsafe_code)]
#![deny(missing_docs)]

mod render;

pub use roff;

use render::subcommand_heading;
use roff::{roman, Roff};
use std::io::Write;

/// A manual page as constructed from a clap::App.
pub struct Man<'a> {
    app: clap::App<'a>,
    title: String,
    section: String,
    date: String,
    source: String,
    manual: String,
}

impl<'a> Man<'a> {
    /// Create a new manual page.
    pub fn new(mut app: clap::App<'a>) -> Self {
        app._build_all();
        let title = app.get_name().to_owned();
        let section = "1".to_owned();
        let date = "".to_owned();
        let source = format!(
            "{} {}",
            app.get_name(),
            app.get_version().unwrap_or_default()
        );
        let manual = "".to_owned();
        Self {
            app,
            title,
            section,
            date,
            source,
            manual,
        }
    }

    /// Override the default title
    pub fn title(mut self, title: impl Into<String>) -> Self {
        self.title = title.into();
        self
    }

    /// Override the default section
    pub fn section(mut self, section: impl Into<String>) -> Self {
        self.section = section.into();
        self
    }

    /// Override the default date
    pub fn date(mut self, date: impl Into<String>) -> Self {
        self.date = date.into();
        self
    }

    /// Override the default source
    pub fn source(mut self, source: impl Into<String>) -> Self {
        self.source = source.into();
        self
    }

    /// Override the default manual
    pub fn manual(mut self, manual: impl Into<String>) -> Self {
        self.manual = manual.into();
        self
    }

    /// Render a manual page into writer.
    pub fn render(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_title(&mut roff);
        self._render_name_section(&mut roff);
        self._render_synopsis_section(&mut roff);
        self._render_description_section(&mut roff);

        if app_has_arguments(&self.app) {
            self._render_options_section(&mut roff);
        }

        if app_has_subcommands(&self.app) {
            self._render_subcommands_section(&mut roff);
        }

        if self.app.get_after_long_help().is_some() || self.app.get_after_help().is_some() {
            self._render_extra_section(&mut roff);
        }

        if app_has_version(&self.app) {
            self._render_version_section(&mut roff);
        }

        if self.app.get_author().is_some() {
            self._render_authors_section(&mut roff);
        }

        roff.to_writer(w)
    }

    /// Render the title into the writer.
    pub fn render_title(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_title(&mut roff);
        roff.to_writer(w)
    }

    fn _render_title(&self, roff: &mut Roff) {
        roff.control("TH", self.title_args());
    }

    // Turn metadata into arguments for a .TH macro.
    fn title_args(&self) -> Vec<&str> {
        vec![
            &self.title,
            &self.section,
            &self.date,
            &self.source,
            &self.manual,
        ]
    }

    /// Render the NAME section into the writer.
    pub fn render_name_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_name_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_name_section(&self, roff: &mut Roff) {
        roff.control("SH", ["NAME"]);
        render::about(roff, &self.app);
    }

    /// Render the SYNOPSIS section into the writer.
    pub fn render_synopsis_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_synopsis_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_synopsis_section(&self, roff: &mut Roff) {
        roff.control("SH", ["SYNOPSIS"]);
        render::synopsis(roff, &self.app);
    }

    /// Render the DESCRIPTION section into the writer.
    pub fn render_description_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_description_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_description_section(&self, roff: &mut Roff) {
        roff.control("SH", ["DESCRIPTION"]);
        render::description(roff, &self.app);
    }

    /// Render the OPTIONS section into the writer.
    pub fn render_options_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_options_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_options_section(&self, roff: &mut Roff) {
        roff.control("SH", ["OPTIONS"]);
        render::options(roff, &self.app);
    }

    /// Render the SUBCOMMANDS section into the writer.
    pub fn render_subcommands_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_subcommands_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_subcommands_section(&self, roff: &mut Roff) {
        let heading = subcommand_heading(&self.app);
        roff.control("SH", [heading.as_str()]);
        render::subcommands(roff, &self.app, &self.section);
    }

    /// Render the EXTRA section into the writer.
    pub fn render_extra_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_extra_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_extra_section(&self, roff: &mut Roff) {
        roff.control("SH", ["EXTRA"]);
        render::after_help(roff, &self.app);
    }

    /// Render the VERSION section into the writer.
    pub fn render_version_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_version_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_version_section(&self, roff: &mut Roff) {
        let version = roman(&render::version(&self.app));
        roff.control("SH", ["VERSION"]);
        roff.text([version]);
    }

    /// Render the AUTHORS section into the writer.
    pub fn render_authors_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_authors_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_authors_section(&self, roff: &mut Roff) {
        let author = roman(self.app.get_author().unwrap_or_default());
        roff.control("SH", ["AUTHORS"]);
        roff.text([author]);
    }
}

// Does the application have a version?
fn app_has_version(app: &clap::App) -> bool {
    app.get_version()
        .or_else(|| app.get_long_version())
        .is_some()
}

// Does the application have any command line arguments?
fn app_has_arguments(app: &clap::App) -> bool {
    app.get_arguments()
        .any(|i| !i.is_set(clap::ArgSettings::Hidden))
}

// Does the application have any subcommands?
fn app_has_subcommands(app: &clap::App) -> bool {
    app.get_subcommands()
        .any(|i| !i.is_set(clap::AppSettings::Hidden))
}
<commit_msg>docs: Expand doc comments<commit_after>#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![forbid(unsafe_code)]
#![deny(missing_docs)]

mod render;

pub use roff;

use render::subcommand_heading;
use roff::{roman, Roff};
use std::io::Write;

/// A manpage writer
pub struct Man<'a> {
    app: clap::App<'a>,
    title: String,
    section: String,
    date: String,
    source: String,
    manual: String,
}

/// Build a [`Man`]
impl<'a> Man<'a> {
    /// Create a new manual page.
    pub fn new(mut app: clap::App<'a>) -> Self {
        app._build_all();
        let title = app.get_name().to_owned();
        let section = "1".to_owned();
        let date = "".to_owned();
        let source = format!(
            "{} {}",
            app.get_name(),
            app.get_version().unwrap_or_default()
        );
        let manual = "".to_owned();
        Self {
            app,
            title,
            section,
            date,
            source,
            manual,
        }
    }

    /// Override the default man page title, written in all caps
    pub fn title(mut self, title: impl Into<String>) -> Self {
        self.title = title.into();
        self
    }

    /// Override the default section this man page is placed in
    ///
    /// Common values:
    ///
    // - `"1"`: User Commands
    // - `"2"`: System Calls
    // - `"3"`: C Library Functions
    // - `"4"`: Devices and Special Files
    // - `"5"`: File Formats and Conventions
    // - `"6"`: Games et. al.
    // - `"7"`: Miscellanea
    // - `"8"`: System Administration tools and Daemons
    pub fn section(mut self, section: impl Into<String>) -> Self {
        self.section = section.into();
        self
    }

    /// Override the default date for the last non-trivial change to this man page
    ///
    /// Dates should be written in the form `YYYY-MM-DD`.
    pub fn date(mut self, date: impl Into<String>) -> Self {
        self.date = date.into();
        self
    }

    /// Override the default source your command
    ///
    /// For those few man-pages pages in Sections 1 and 8, probably you just want to write GNU.
    pub fn source(mut self, source: impl Into<String>) -> Self {
        self.source = source.into();
        self
    }

    /// Override the default manual this page is a member of
    pub fn manual(mut self, manual: impl Into<String>) -> Self {
        self.manual = manual.into();
        self
    }
}

/// Generate ROFF output
impl<'a> Man<'a> {
    /// Render a full manual page into the writer.
    ///
    /// If customization is needed, you can call the individual sections you want and mix them into
    /// your own ROFF content.
    pub fn render(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_title(&mut roff);
        self._render_name_section(&mut roff);
        self._render_synopsis_section(&mut roff);
        self._render_description_section(&mut roff);

        if app_has_arguments(&self.app) {
            self._render_options_section(&mut roff);
        }

        if app_has_subcommands(&self.app) {
            self._render_subcommands_section(&mut roff);
        }

        if self.app.get_after_long_help().is_some() || self.app.get_after_help().is_some() {
            self._render_extra_section(&mut roff);
        }

        if app_has_version(&self.app) {
            self._render_version_section(&mut roff);
        }

        if self.app.get_author().is_some() {
            self._render_authors_section(&mut roff);
        }

        roff.to_writer(w)
    }

    /// Render the title into the writer.
    pub fn render_title(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_title(&mut roff);
        roff.to_writer(w)
    }

    fn _render_title(&self, roff: &mut Roff) {
        roff.control("TH", self.title_args());
    }

    // Turn metadata into arguments for a .TH macro.
    fn title_args(&self) -> Vec<&str> {
        vec![
            &self.title,
            &self.section,
            &self.date,
            &self.source,
            &self.manual,
        ]
    }

    /// Render the NAME section into the writer.
    pub fn render_name_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_name_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_name_section(&self, roff: &mut Roff) {
        roff.control("SH", ["NAME"]);
        render::about(roff, &self.app);
    }

    /// Render the SYNOPSIS section into the writer.
    pub fn render_synopsis_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_synopsis_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_synopsis_section(&self, roff: &mut Roff) {
        roff.control("SH", ["SYNOPSIS"]);
        render::synopsis(roff, &self.app);
    }

    /// Render the DESCRIPTION section into the writer.
    pub fn render_description_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_description_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_description_section(&self, roff: &mut Roff) {
        roff.control("SH", ["DESCRIPTION"]);
        render::description(roff, &self.app);
    }

    /// Render the OPTIONS section into the writer.
    pub fn render_options_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_options_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_options_section(&self, roff: &mut Roff) {
        roff.control("SH", ["OPTIONS"]);
        render::options(roff, &self.app);
    }

    /// Render the SUBCOMMANDS section into the writer.
    pub fn render_subcommands_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_subcommands_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_subcommands_section(&self, roff: &mut Roff) {
        let heading = subcommand_heading(&self.app);
        roff.control("SH", [heading.as_str()]);
        render::subcommands(roff, &self.app, &self.section);
    }

    /// Render the EXTRA section into the writer.
    pub fn render_extra_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_extra_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_extra_section(&self, roff: &mut Roff) {
        roff.control("SH", ["EXTRA"]);
        render::after_help(roff, &self.app);
    }

    /// Render the VERSION section into the writer.
    pub fn render_version_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_version_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_version_section(&self, roff: &mut Roff) {
        let version = roman(&render::version(&self.app));
        roff.control("SH", ["VERSION"]);
        roff.text([version]);
    }

    /// Render the AUTHORS section into the writer.
    pub fn render_authors_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_authors_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_authors_section(&self, roff: &mut Roff) {
        let author = roman(self.app.get_author().unwrap_or_default());
        roff.control("SH", ["AUTHORS"]);
        roff.text([author]);
    }
}

// Does the application have a version?
fn app_has_version(app: &clap::App) -> bool {
    app.get_version()
        .or_else(|| app.get_long_version())
        .is_some()
}

// Does the application have any command line arguments?
fn app_has_arguments(app: &clap::App) -> bool {
    app.get_arguments()
        .any(|i| !i.is_set(clap::ArgSettings::Hidden))
}

// Does the application have any subcommands?
fn app_has_subcommands(app: &clap::App) -> bool {
    app.get_subcommands()
        .any(|i| !i.is_set(clap::AppSettings::Hidden))
}
<|endoftext|>


<commit_before>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

// This is a macro that routinely comes in handy
#[macro_export]
macro_rules! impl_array_newtype {
    ($thing:ident, $ty:ty, $len:expr) => {
        impl Copy for $thing {}

        impl $thing {
            #[inline]
            /// Converts the object to a raw pointer for FFI interfacing
            pub fn as_ptr(&self) -> *const $ty {
                let &$thing(ref dat) = self;
                dat.as_ptr()
            }

            #[inline]
            /// Converts the object to a mutable raw pointer for FFI interfacing
            pub fn as_mut_ptr(&mut self) -> *mut $ty {
                let &mut $thing(ref mut dat) = self;
                dat.as_mut_ptr()
            }

            #[inline]
            /// Returns the length of the object as an array
            pub fn len(&self) -> usize { $len }

            #[inline]
            /// Returns whether the object as an array is empty
            pub fn is_empty(&self) -> bool { false }
        }

        impl PartialEq for $thing {
            #[inline]
            fn eq(&self, other: &$thing) -> bool {
                &self[..] == &other[..]
            }
        }

        impl Eq for $thing {}

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

        impl Ord for $thing {
            #[inline]
            fn cmp(&self, other: &$thing) -> ::core::cmp::Ordering {
                self[..].cmp(&other[..])
            }
        }

        impl Clone for $thing {
            #[inline]
            fn clone(&self) -> $thing {
                let &$thing(ref dat) = self;
                $thing(dat.clone())
            }
        }

        impl ::core::ops::Index<usize> for $thing {
            type Output = $ty;

            #[inline]
            fn index(&self, index: usize) -> &$ty {
                let &$thing(ref dat) = self;
                &dat[index]
            }
        }

        impl ::core::ops::Index<::core::ops::Range<usize>> for $thing {
            type Output = [$ty];

            #[inline]
            fn index(&self, index: ::core::ops::Range<usize>) -> &[$ty] {
                let &$thing(ref dat) = self;
                &dat[index]
            }
        }

        impl ::core::ops::Index<::core::ops::RangeTo<usize>> for $thing {
            type Output = [$ty];

            #[inline]
            fn index(&self, index: ::core::ops::RangeTo<usize>) -> &[$ty] {
                let &$thing(ref dat) = self;
                &dat[index]
            }
        }

        impl ::core::ops::Index<::core::ops::RangeFrom<usize>> for $thing {
            type Output = [$ty];

            #[inline]
            fn index(&self, index: ::core::ops::RangeFrom<usize>) -> &[$ty] {
                let &$thing(ref dat) = self;
                &dat[index]
            }
        }

        impl ::core::ops::Index<::core::ops::RangeFull> for $thing {
            type Output = [$ty];

            #[inline]
            fn index(&self, _: ::core::ops::RangeFull) -> &[$ty] {
                let &$thing(ref dat) = self;
                &dat[..]
            }
        }
        impl ::CPtr for $thing {
            type Target = $ty;
            fn as_c_ptr(&self) -> *const Self::Target {
                if self.is_empty() {
                    ::core::ptr::null()
                } else {
                    self.as_ptr()
                }
            }

            fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
                if self.is_empty() {
                    ::core::ptr::null::<Self::Target>() as *mut _
                } else {
                    self.as_mut_ptr()
                }
            }
        }
    }
}

#[macro_export]
macro_rules! impl_raw_debug {
    ($thing:ident) => {
        impl ::core::fmt::Debug for $thing {
            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
                for i in self[..].iter().cloned() {
                    write!(f, "{:02x}", i)?;
                }
                Ok(())
            }
        }
     }
}
<commit_msg>Expose the underlying array in addition to a ptr to the same<commit_after>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

// This is a macro that routinely comes in handy
#[macro_export]
macro_rules! impl_array_newtype {
    ($thing:ident, $ty:ty, $len:expr) => {
        impl Copy for $thing {}

        impl $thing {
            #[inline]
            /// Converts the object to a raw pointer for FFI interfacing
            pub fn as_ptr(&self) -> *const $ty {
                let &$thing(ref dat) = self;
                dat.as_ptr()
            }

            #[inline]
            /// Converts the object to a mutable raw pointer for FFI interfacing
            pub fn as_mut_ptr(&mut self) -> *mut $ty {
                let &mut $thing(ref mut dat) = self;
                dat.as_mut_ptr()
            }

            #[inline]
            /// Gets a reference to the underlying array
            pub fn as_ref(&self) -> &[$ty; $len] {
                let &$thing(ref dat) = self;
                dat
            }

            #[inline]
            /// Returns the length of the object as an array
            pub fn len(&self) -> usize { $len }

            #[inline]
            /// Returns whether the object as an array is empty
            pub fn is_empty(&self) -> bool { false }
        }

        impl PartialEq for $thing {
            #[inline]
            fn eq(&self, other: &$thing) -> bool {
                &self[..] == &other[..]
            }
        }

        impl Eq for $thing {}

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

        impl Ord for $thing {
            #[inline]
            fn cmp(&self, other: &$thing) -> ::core::cmp::Ordering {
                self[..].cmp(&other[..])
            }
        }

        impl Clone for $thing {
            #[inline]
            fn clone(&self) -> $thing {
                let &$thing(ref dat) = self;
                $thing(dat.clone())
            }
        }

        impl ::core::ops::Index<usize> for $thing {
            type Output = $ty;

            #[inline]
            fn index(&self, index: usize) -> &$ty {
                let &$thing(ref dat) = self;
                &dat[index]
            }
        }

        impl ::core::ops::Index<::core::ops::Range<usize>> for $thing {
            type Output = [$ty];

            #[inline]
            fn index(&self, index: ::core::ops::Range<usize>) -> &[$ty] {
                let &$thing(ref dat) = self;
                &dat[index]
            }
        }

        impl ::core::ops::Index<::core::ops::RangeTo<usize>> for $thing {
            type Output = [$ty];

            #[inline]
            fn index(&self, index: ::core::ops::RangeTo<usize>) -> &[$ty] {
                let &$thing(ref dat) = self;
                &dat[index]
            }
        }

        impl ::core::ops::Index<::core::ops::RangeFrom<usize>> for $thing {
            type Output = [$ty];

            #[inline]
            fn index(&self, index: ::core::ops::RangeFrom<usize>) -> &[$ty] {
                let &$thing(ref dat) = self;
                &dat[index]
            }
        }

        impl ::core::ops::Index<::core::ops::RangeFull> for $thing {
            type Output = [$ty];

            #[inline]
            fn index(&self, _: ::core::ops::RangeFull) -> &[$ty] {
                let &$thing(ref dat) = self;
                &dat[..]
            }
        }
        impl ::CPtr for $thing {
            type Target = $ty;
            fn as_c_ptr(&self) -> *const Self::Target {
                if self.is_empty() {
                    ::core::ptr::null()
                } else {
                    self.as_ptr()
                }
            }

            fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
                if self.is_empty() {
                    ::core::ptr::null::<Self::Target>() as *mut _
                } else {
                    self.as_mut_ptr()
                }
            }
        }
    }
}

#[macro_export]
macro_rules! impl_raw_debug {
    ($thing:ident) => {
        impl ::core::fmt::Debug for $thing {
            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
                for i in self[..].iter().cloned() {
                    write!(f, "{:02x}", i)?;
                }
                Ok(())
            }
        }
     }
}
<|endoftext|>


<commit_before>//! Types and functions related to bindgen annotation comments.
//!
//! Users can add annotations in doc comments to types that they would like to
//! replace other types with, mark as opaque, etc. This module deals with all of
//! that stuff.

use clang;

/// What kind of accessor should we provide for a field?
#[derive(Copy, PartialEq, Clone, Debug)]
pub enum FieldAccessorKind {
    /// No accessor.
    None,
    /// Plain accessor.
    Regular,
    /// Unsafe accessor.
    Unsafe,
    /// Immutable accessor.
    Immutable,
}

/// Annotations for a given item, or a field.
#[derive(Clone, PartialEq, Debug)]
pub struct Annotations {
    /// Whether this item is marked as opaque. Only applies to types.
    opaque: bool,
    /// Whether this item should be hidden from the output. Only applies to
    /// types.
    hide: bool,
    /// Whether this type should be replaced by another. The name is a
    /// namespace-aware path.
    use_instead_of: Option<Vec<String>>,
    /// Manually disable deriving copy/clone on this type. Only applies to
    /// struct or union types.
    disallow_copy: bool,
    /// Whether fields should be marked as private or not. You can set this on
    /// structs (it will apply to all the fields), or individual fields.
    private_fields: Option<bool>,
    /// The kind of accessor this field will have. Also can be applied to
    /// structs so all the fields inside share it by default.
    accessor_kind: Option<FieldAccessorKind>,
}

fn parse_accessor(s: &str) -> FieldAccessorKind {
    match s {
        "false" => FieldAccessorKind::None,
        "unsafe" => FieldAccessorKind::Unsafe,
        "immutable" => FieldAccessorKind::Immutable,
        _ => FieldAccessorKind::Regular,
    }
}

impl Default for Annotations {
    fn default() -> Self {
        Annotations {
            opaque: false,
            hide: false,
            use_instead_of: None,
            disallow_copy: false,
            private_fields: None,
            accessor_kind: None,
        }
    }
}

impl Annotations {
    /// Construct new annotations for the given cursor and its bindgen comments
    /// (if any).
    pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
        let mut anno = Annotations::default();
        let mut matched_one = false;
        anno.parse(&cursor.comment(), &mut matched_one);

        if matched_one { Some(anno) } else { None }
    }

    /// Should this type be hidden?
    pub fn hide(&self) -> bool {
        self.hide
    }

    /// Should this type be opaque?
    pub fn opaque(&self) -> bool {
        self.opaque
    }

    /// For a given type, indicates the type it should replace.
    ///
    /// For example, in the following code:
    ///
    /// ```cpp
    ///
    /// /** <div rustbindgen replaces="Bar"></div> */
    /// struct Foo { int x; };
    ///
    /// struct Bar { char foo; };
    /// ```
    ///
    /// the generated code would look something like:
    ///
    /// ```
    /// /** <div rustbindgen replaces="Bar"></div> */
    /// struct Bar {
    ///     x: ::std::os::raw::c_int,
    /// };
    /// ```
    ///
    /// That is, code for `Foo` is used to generate `Bar`.
    pub fn use_instead_of(&self) -> Option<&[String]> {
        self.use_instead_of.as_ref().map(|s| &**s)
    }

    /// Should we avoid implementing the `Copy` trait?
    pub fn disallow_copy(&self) -> bool {
        self.disallow_copy
    }

    /// Should the fields be private?
    pub fn private_fields(&self) -> Option<bool> {
        self.private_fields
    }

    /// What kind of accessors should we provide for this type's fields?
    pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
        self.accessor_kind
    }

    fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
        use clang_sys::CXComment_HTMLStartTag;
        if comment.kind() == CXComment_HTMLStartTag &&
           comment.get_tag_name() == "div" &&
           comment.get_tag_attrs()
            .next()
            .map_or(false, |attr| attr.name == "rustbindgen") {
            *matched = true;
            for attr in comment.get_tag_attrs() {
                match attr.name.as_str() {
                    "opaque" => self.opaque = true,
                    "hide" => self.hide = true,
                    "nocopy" => self.disallow_copy = true,
                    "replaces" => {
                        self.use_instead_of = Some(attr.value
                            .split("::")
                            .map(Into::into)
                            .collect())
                    }
                    "private" => {
                        self.private_fields = Some(attr.value != "false")
                    }
                    "accessor" => {
                        self.accessor_kind = Some(parse_accessor(&attr.value))
                    }
                    _ => {}
                }
            }
        }

        for child in comment.get_children() {
            self.parse(&child, matched);
        }
    }
}
<commit_msg>ir: Add an annotation API to constify enum variants.<commit_after>//! Types and functions related to bindgen annotation comments.
//!
//! Users can add annotations in doc comments to types that they would like to
//! replace other types with, mark as opaque, etc. This module deals with all of
//! that stuff.

use clang;

/// What kind of accessor should we provide for a field?
#[derive(Copy, PartialEq, Clone, Debug)]
pub enum FieldAccessorKind {
    /// No accessor.
    None,
    /// Plain accessor.
    Regular,
    /// Unsafe accessor.
    Unsafe,
    /// Immutable accessor.
    Immutable,
}

/// Annotations for a given item, or a field.
#[derive(Clone, PartialEq, Debug)]
pub struct Annotations {
    /// Whether this item is marked as opaque. Only applies to types.
    opaque: bool,
    /// Whether this item should be hidden from the output. Only applies to
    /// types.
    hide: bool,
    /// Whether this type should be replaced by another. The name is a
    /// namespace-aware path.
    use_instead_of: Option<Vec<String>>,
    /// Manually disable deriving copy/clone on this type. Only applies to
    /// struct or union types.
    disallow_copy: bool,
    /// Whether fields should be marked as private or not. You can set this on
    /// structs (it will apply to all the fields), or individual fields.
    private_fields: Option<bool>,
    /// The kind of accessor this field will have. Also can be applied to
    /// structs so all the fields inside share it by default.
    accessor_kind: Option<FieldAccessorKind>,
    /// Whether this enum variant should be constified.
    ///
    /// This is controlled by the `constant` attribute, this way:
    ///
    /// ```cpp
    /// enum Foo {
    ///     Bar = 0, //< <div rustbindgen constant></div>
    ///     Baz = 0,
    /// };
    /// ```
    ///
    /// In that case, bindgen will generate a constant for `Bar` instead of
    /// `Baz`.
    constify_enum_variant: bool,
}

fn parse_accessor(s: &str) -> FieldAccessorKind {
    match s {
        "false" => FieldAccessorKind::None,
        "unsafe" => FieldAccessorKind::Unsafe,
        "immutable" => FieldAccessorKind::Immutable,
        _ => FieldAccessorKind::Regular,
    }
}

impl Default for Annotations {
    fn default() -> Self {
        Annotations {
            opaque: false,
            hide: false,
            use_instead_of: None,
            disallow_copy: false,
            private_fields: None,
            accessor_kind: None,
            constify_enum_variant: false,
        }
    }
}

impl Annotations {
    /// Construct new annotations for the given cursor and its bindgen comments
    /// (if any).
    pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
        let mut anno = Annotations::default();
        let mut matched_one = false;
        anno.parse(&cursor.comment(), &mut matched_one);

        if matched_one { Some(anno) } else { None }
    }

    /// Should this type be hidden?
    pub fn hide(&self) -> bool {
        self.hide
    }

    /// Should this type be opaque?
    pub fn opaque(&self) -> bool {
        self.opaque
    }

    /// For a given type, indicates the type it should replace.
    ///
    /// For example, in the following code:
    ///
    /// ```cpp
    ///
    /// /** <div rustbindgen replaces="Bar"></div> */
    /// struct Foo { int x; };
    ///
    /// struct Bar { char foo; };
    /// ```
    ///
    /// the generated code would look something like:
    ///
    /// ```
    /// /** <div rustbindgen replaces="Bar"></div> */
    /// struct Bar {
    ///     x: ::std::os::raw::c_int,
    /// };
    /// ```
    ///
    /// That is, code for `Foo` is used to generate `Bar`.
    pub fn use_instead_of(&self) -> Option<&[String]> {
        self.use_instead_of.as_ref().map(|s| &**s)
    }

    /// Should we avoid implementing the `Copy` trait?
    pub fn disallow_copy(&self) -> bool {
        self.disallow_copy
    }

    /// Should the fields be private?
    pub fn private_fields(&self) -> Option<bool> {
        self.private_fields
    }

    /// What kind of accessors should we provide for this type's fields?
    pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
        self.accessor_kind
    }

    fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
        use clang_sys::CXComment_HTMLStartTag;
        if comment.kind() == CXComment_HTMLStartTag &&
           comment.get_tag_name() == "div" &&
           comment.get_tag_attrs()
            .next()
            .map_or(false, |attr| attr.name == "rustbindgen") {
            *matched = true;
            for attr in comment.get_tag_attrs() {
                match attr.name.as_str() {
                    "opaque" => self.opaque = true,
                    "hide" => self.hide = true,
                    "nocopy" => self.disallow_copy = true,
                    "replaces" => {
                        self.use_instead_of = Some(attr.value
                            .split("::")
                            .map(Into::into)
                            .collect())
                    }
                    "private" => {
                        self.private_fields = Some(attr.value != "false")
                    }
                    "accessor" => {
                        self.accessor_kind = Some(parse_accessor(&attr.value))
                    }
                    "constant" => self.constify_enum_variant = true,
                    _ => {}
                }
            }
        }

        for child in comment.get_children() {
            self.parse(&child, matched);
        }
    }

    /// Returns whether we've parsed a "constant" attribute.
    pub fn constify_enum_variant(&self) -> bool {
        self.constify_enum_variant
    }
}
<|endoftext|>