<commit_before>//! Contains x86-specific types

pub use arch::arch_builder::x86::*;
use arch::DetailsArchInsn;
use capstone_sys::{x86_op_mem, x86_op_type, cs_x86, cs_x86_op};
use instruction::{RegId, RegIdInt};
use std::convert::From;
use std::{cmp, fmt, slice};

pub use capstone_sys::x86_insn_group as X86InsnGroup;
pub use capstone_sys::x86_insn as X86Insn;
pub use capstone_sys::x86_reg as X86Reg;

pub use capstone_sys::x86_avx_bcast as X86AvxBcast;
pub use capstone_sys::x86_sse_cc as X86SseCC;
pub use capstone_sys::x86_avx_cc as X86AvxCC;
pub use capstone_sys::x86_avx_rm as X86AvxRm;

use capstone_sys::cs_x86_op__bindgen_ty_1;

/// Contains X86-specific details for an instruction
pub struct X86InsnDetail<'a>(pub(crate) &'a cs_x86);

impl X86OperandType {
    fn new(op_type: x86_op_type, value: cs_x86_op__bindgen_ty_1) -> X86OperandType {
        use self::x86_op_type::*;
        use self::X86OperandType::*;

        match op_type {
            X86_OP_REG => Reg(RegId(unsafe { value.reg } as RegIdInt)),
            X86_OP_IMM => Imm(unsafe { value.imm }),
            X86_OP_MEM => Mem(X86OpMem(unsafe { value.mem })),
            X86_OP_FP => Fp(unsafe { value.fp }),
            X86_OP_INVALID => Invalid,
        }
    }
}

/// X86 operand
#[derive(Clone, Debug, PartialEq)]
pub struct X86Operand {
    /// Operand size
    pub size: u8,

    /// AVX broadcast
    pub avx_bcast: X86AvxBcast,

    /// AVX zero opmask
    pub avx_zero_opmask: bool,

    /// Operand type
    pub op_type: X86OperandType,
}

/// X86 operand
#[derive(Clone, Debug, PartialEq)]
pub enum X86OperandType {
    /// Register
    Reg(RegId),

    /// Immediate
    Imm(i64),

    /// Memory
    Mem(X86OpMem),

    /// Floating point
    Fp(f64),

    /// Invalid
    Invalid,
}

/// X86 memory operand
#[derive(Debug, Copy, Clone)]
pub struct X86OpMem(pub(crate) x86_op_mem);

impl<'a> X86InsnDetail<'a> {
    /// Instruction prefix bytes
    pub fn prefix(&self) -> &[u8; 4] {
        &self.0.prefix
    }

    /// Opcode bytes
    pub fn opcode(&self) -> &[u8; 4] {
        &self.0.opcode
    }

    /// REX
    pub fn rex(&self) -> u8 {
        self.0.rex
    }

    /// Address size
    pub fn addr_size(&self) -> u8 {
        self.0.addr_size
    }

    /// MODRM
    pub fn modrm(&self) -> u8 {
        self.0.modrm
    }

    /// SIB (Scaled Index Byte)
    pub fn sib(&self) -> u8 {
        self.0.sib
    }

    /// Disp
    pub fn disp(&self) -> i32 {
        self.0.disp
    }

    /// Scaled Index Byte (SIB) index
    pub fn sib_index(&self) -> RegId {
        RegId(self.0.sib_index as RegIdInt)
    }

    /// Scaled Index Byte (SIB) scale
    pub fn sib_scale(&self) -> i8 {
        self.0.sib_scale
    }

    /// Scaled Index Byte (SIB) scale
    pub fn sib_base(&self) -> RegId {
        RegId(self.0.sib_base as RegIdInt)
    }

    /// Streaming SIMD Extensions (SSE) condition  codes
    pub fn sse_cc(&self) -> X86SseCC {
        self.0.sse_cc
    }

    /// Advanced Vector Extensions (AVX) condition  codes
    pub fn avx_cc(&self) -> X86AvxCC {
        self.0.avx_cc
    }

    /// Advanced Vector Extensions (AVX) sae
    pub fn avx_sae(&self) -> bool {
        self.0.avx_sae
    }

    /// Advanced Vector Extensions (AVX) rm
    pub fn avx_rm(&self) -> X86AvxRm {
        self.0.avx_rm
    }
}

impl_PartialEq_repr_fields!(X86InsnDetail<'a> [ 'a ];
    prefix, opcode, rex, addr_size, modrm, sib, disp, sib_index, sib_scale, sib_base, sse_cc,
    avx_cc, avx_sae, avx_rm, operands
);

impl X86OpMem {
    /// Segment
    fn segment(&self) -> u32 {
        self.0.segment as u32
    }

    /// Base register
    fn base(&self) -> RegId {
        RegId(self.0.base as RegIdInt)
    }

    /// Index register
    fn index(&self) -> RegId {
        RegId(self.0.index as RegIdInt)
    }

    /// Scale
    fn scale(&self) -> i32 {
        self.0.scale as i32
    }

    /// Display
    fn disp(&self) -> i64 {
        self.0.disp
    }
}

impl_PartialEq_repr_fields!(X86OpMem;
    segment, base, index, scale, disp
);

impl cmp::Eq for X86OpMem {}

impl Default for X86Operand {
    fn default() -> Self {
        X86Operand {
            size: 0,
            avx_bcast: X86AvxBcast::X86_AVX_BCAST_INVALID,
            avx_zero_opmask: false,
            op_type: X86OperandType::Invalid
        }
    }
}

impl<'a> From<&'a cs_x86_op> for X86Operand {
    fn from(op: &cs_x86_op) -> X86Operand {
        let op_type = X86OperandType::new(op.type_, op.__bindgen_anon_1);
        X86Operand {
            size: op.size,
            avx_bcast: op.avx_bcast,
            avx_zero_opmask: op.avx_zero_opmask,
            op_type,
        }
    }
}

def_arch_details_struct!(
    InsnDetail = X86InsnDetail;
    Operand = X86Operand;
    OperandIterator = X86OperandIterator;
    OperandIteratorLife = X86OperandIterator<'a>;
    [ pub struct X86OperandIterator<'a>(slice::Iter<'a, cs_x86_op>); ]
    cs_arch_op = cs_x86_op;
    cs_arch = cs_x86;
);

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

    #[test]
    fn test_x86_op_type() {
        use super::x86_op_type::*;
        use super::X86OperandType::*;

        fn t(
            op_type_value: (x86_op_type, cs_x86_op__bindgen_ty_1),
            expected_op_type: X86OperandType,
        ) {
            let (op_type, op_value) = op_type_value;
            let op_type = X86OperandType::new(op_type, op_value);
            assert_eq!(expected_op_type, op_type);
        }

        t(
            (X86_OP_INVALID, cs_x86_op__bindgen_ty_1 { reg: 0 }),
            Invalid,
        );
        t(
            (X86_OP_REG, cs_x86_op__bindgen_ty_1 { reg: 0 }),
            Reg(RegId(0)),
        );
    }

    #[test]
    fn test_x86_op_eq() {
        use std::f64;

        let a1 = X86Operand {
            op_type: X86OperandType::Fp(1.0),
            ..Default::default()
        };
        let a2 = X86Operand {
            op_type: X86OperandType::Fp(f64::NAN),
            ..Default::default()
        };

        assert_eq!(a1, a1.clone());
        assert_ne!(a1, a2.clone());
    }

    #[test]
    fn test_x86_insn_eq() {
        fn t_eq(a: &cs_x86, b: &cs_x86) {
            assert_eq!(X86InsnDetail(a), X86InsnDetail(b))
        }
        fn t_ne(a: &cs_x86, b: &cs_x86) {
            assert_ne!(X86InsnDetail(a), X86InsnDetail(b))
        }

        let a1 = cs_x86 {
            prefix: [0, 0, 0, 0],
            opcode: [0, 0, 0, 0],
            rex: 0,
            addr_size: 0,
            modrm: 0,
            sib: 0,
            disp: 0,
            sib_index: x86_reg::X86_REG_INVALID,
            sib_scale: 0,
            sib_base: x86_reg::X86_REG_INVALID,
            sse_cc: x86_sse_cc::X86_SSE_CC_INVALID,
            avx_cc: x86_avx_cc::X86_AVX_CC_INVALID,
            avx_sae: false,
            avx_rm: x86_avx_rm::X86_AVX_RM_INVALID,
            op_count: 0,
            operands: [ cs_x86_op {
                type_: x86_op_type::X86_OP_INVALID,
                __bindgen_anon_1: cs_x86_op__bindgen_ty_1 { reg: x86_reg::X86_REG_INVALID },
                size: 0,
                avx_bcast: x86_avx_bcast::X86_AVX_BCAST_INVALID,
                avx_zero_opmask: false,

            }
            ; 8]

        };
        let mut a2 = a1.clone();
        a2.operands[1].type_ = x86_op_type::X86_OP_REG;
        let a1_clone = cs_x86 {
            ..a1
        };
        let a3 = cs_x86 {
            rex: 1,
            ..a1
        };
        let op_count_differ = cs_x86 {
            op_count: 1,
            ..a1
        };
        let mut op1_differ = op_count_differ.clone();
        op1_differ.operands[0].avx_bcast = x86_avx_bcast::X86_AVX_BCAST_2;

        t_eq(&a1, &a1);
        t_eq(&a1, &a2);
        t_eq(&a1, &a1_clone);
        t_ne(&a1, &a3);
        t_ne(&a1, &op_count_differ);
        t_ne(&op_count_differ, &op1_differ);
    }
}
<commit_msg>Make X86OpMem methods public<commit_after>//! Contains x86-specific types

pub use arch::arch_builder::x86::*;
use arch::DetailsArchInsn;
use capstone_sys::{x86_op_mem, x86_op_type, cs_x86, cs_x86_op};
use instruction::{RegId, RegIdInt};
use std::convert::From;
use std::{cmp, fmt, slice};

pub use capstone_sys::x86_insn_group as X86InsnGroup;
pub use capstone_sys::x86_insn as X86Insn;
pub use capstone_sys::x86_reg as X86Reg;

pub use capstone_sys::x86_avx_bcast as X86AvxBcast;
pub use capstone_sys::x86_sse_cc as X86SseCC;
pub use capstone_sys::x86_avx_cc as X86AvxCC;
pub use capstone_sys::x86_avx_rm as X86AvxRm;

use capstone_sys::cs_x86_op__bindgen_ty_1;

/// Contains X86-specific details for an instruction
pub struct X86InsnDetail<'a>(pub(crate) &'a cs_x86);

impl X86OperandType {
    fn new(op_type: x86_op_type, value: cs_x86_op__bindgen_ty_1) -> X86OperandType {
        use self::x86_op_type::*;
        use self::X86OperandType::*;

        match op_type {
            X86_OP_REG => Reg(RegId(unsafe { value.reg } as RegIdInt)),
            X86_OP_IMM => Imm(unsafe { value.imm }),
            X86_OP_MEM => Mem(X86OpMem(unsafe { value.mem })),
            X86_OP_FP => Fp(unsafe { value.fp }),
            X86_OP_INVALID => Invalid,
        }
    }
}

/// X86 operand
#[derive(Clone, Debug, PartialEq)]
pub struct X86Operand {
    /// Operand size
    pub size: u8,

    /// AVX broadcast
    pub avx_bcast: X86AvxBcast,

    /// AVX zero opmask
    pub avx_zero_opmask: bool,

    /// Operand type
    pub op_type: X86OperandType,
}

/// X86 operand
#[derive(Clone, Debug, PartialEq)]
pub enum X86OperandType {
    /// Register
    Reg(RegId),

    /// Immediate
    Imm(i64),

    /// Memory
    Mem(X86OpMem),

    /// Floating point
    Fp(f64),

    /// Invalid
    Invalid,
}

/// X86 memory operand
#[derive(Debug, Copy, Clone)]
pub struct X86OpMem(pub(crate) x86_op_mem);

impl<'a> X86InsnDetail<'a> {
    /// Instruction prefix bytes
    pub fn prefix(&self) -> &[u8; 4] {
        &self.0.prefix
    }

    /// Opcode bytes
    pub fn opcode(&self) -> &[u8; 4] {
        &self.0.opcode
    }

    /// REX
    pub fn rex(&self) -> u8 {
        self.0.rex
    }

    /// Address size
    pub fn addr_size(&self) -> u8 {
        self.0.addr_size
    }

    /// MODRM
    pub fn modrm(&self) -> u8 {
        self.0.modrm
    }

    /// SIB (Scaled Index Byte)
    pub fn sib(&self) -> u8 {
        self.0.sib
    }

    /// Disp
    pub fn disp(&self) -> i32 {
        self.0.disp
    }

    /// Scaled Index Byte (SIB) index
    pub fn sib_index(&self) -> RegId {
        RegId(self.0.sib_index as RegIdInt)
    }

    /// Scaled Index Byte (SIB) scale
    pub fn sib_scale(&self) -> i8 {
        self.0.sib_scale
    }

    /// Scaled Index Byte (SIB) scale
    pub fn sib_base(&self) -> RegId {
        RegId(self.0.sib_base as RegIdInt)
    }

    /// Streaming SIMD Extensions (SSE) condition  codes
    pub fn sse_cc(&self) -> X86SseCC {
        self.0.sse_cc
    }

    /// Advanced Vector Extensions (AVX) condition  codes
    pub fn avx_cc(&self) -> X86AvxCC {
        self.0.avx_cc
    }

    /// Advanced Vector Extensions (AVX) sae
    pub fn avx_sae(&self) -> bool {
        self.0.avx_sae
    }

    /// Advanced Vector Extensions (AVX) rm
    pub fn avx_rm(&self) -> X86AvxRm {
        self.0.avx_rm
    }
}

impl_PartialEq_repr_fields!(X86InsnDetail<'a> [ 'a ];
    prefix, opcode, rex, addr_size, modrm, sib, disp, sib_index, sib_scale, sib_base, sse_cc,
    avx_cc, avx_sae, avx_rm, operands
);

impl X86OpMem {
    /// Segment
    pub fn segment(&self) -> u32 {
        self.0.segment as u32
    }

    /// Base register
    pub fn base(&self) -> RegId {
        RegId(self.0.base as RegIdInt)
    }

    /// Index register
    pub fn index(&self) -> RegId {
        RegId(self.0.index as RegIdInt)
    }

    /// Scale
    pub fn scale(&self) -> i32 {
        self.0.scale as i32
    }

    /// Display
    pub fn disp(&self) -> i64 {
        self.0.disp
    }
}

impl_PartialEq_repr_fields!(X86OpMem;
    segment, base, index, scale, disp
);

impl cmp::Eq for X86OpMem {}

impl Default for X86Operand {
    fn default() -> Self {
        X86Operand {
            size: 0,
            avx_bcast: X86AvxBcast::X86_AVX_BCAST_INVALID,
            avx_zero_opmask: false,
            op_type: X86OperandType::Invalid
        }
    }
}

impl<'a> From<&'a cs_x86_op> for X86Operand {
    fn from(op: &cs_x86_op) -> X86Operand {
        let op_type = X86OperandType::new(op.type_, op.__bindgen_anon_1);
        X86Operand {
            size: op.size,
            avx_bcast: op.avx_bcast,
            avx_zero_opmask: op.avx_zero_opmask,
            op_type,
        }
    }
}

def_arch_details_struct!(
    InsnDetail = X86InsnDetail;
    Operand = X86Operand;
    OperandIterator = X86OperandIterator;
    OperandIteratorLife = X86OperandIterator<'a>;
    [ pub struct X86OperandIterator<'a>(slice::Iter<'a, cs_x86_op>); ]
    cs_arch_op = cs_x86_op;
    cs_arch = cs_x86;
);

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

    #[test]
    fn test_x86_op_type() {
        use super::x86_op_type::*;
        use super::X86OperandType::*;

        fn t(
            op_type_value: (x86_op_type, cs_x86_op__bindgen_ty_1),
            expected_op_type: X86OperandType,
        ) {
            let (op_type, op_value) = op_type_value;
            let op_type = X86OperandType::new(op_type, op_value);
            assert_eq!(expected_op_type, op_type);
        }

        t(
            (X86_OP_INVALID, cs_x86_op__bindgen_ty_1 { reg: 0 }),
            Invalid,
        );
        t(
            (X86_OP_REG, cs_x86_op__bindgen_ty_1 { reg: 0 }),
            Reg(RegId(0)),
        );
    }

    #[test]
    fn test_x86_op_eq() {
        use std::f64;

        let a1 = X86Operand {
            op_type: X86OperandType::Fp(1.0),
            ..Default::default()
        };
        let a2 = X86Operand {
            op_type: X86OperandType::Fp(f64::NAN),
            ..Default::default()
        };

        assert_eq!(a1, a1.clone());
        assert_ne!(a1, a2.clone());
    }

    #[test]
    fn test_x86_insn_eq() {
        fn t_eq(a: &cs_x86, b: &cs_x86) {
            assert_eq!(X86InsnDetail(a), X86InsnDetail(b))
        }
        fn t_ne(a: &cs_x86, b: &cs_x86) {
            assert_ne!(X86InsnDetail(a), X86InsnDetail(b))
        }

        let a1 = cs_x86 {
            prefix: [0, 0, 0, 0],
            opcode: [0, 0, 0, 0],
            rex: 0,
            addr_size: 0,
            modrm: 0,
            sib: 0,
            disp: 0,
            sib_index: x86_reg::X86_REG_INVALID,
            sib_scale: 0,
            sib_base: x86_reg::X86_REG_INVALID,
            sse_cc: x86_sse_cc::X86_SSE_CC_INVALID,
            avx_cc: x86_avx_cc::X86_AVX_CC_INVALID,
            avx_sae: false,
            avx_rm: x86_avx_rm::X86_AVX_RM_INVALID,
            op_count: 0,
            operands: [ cs_x86_op {
                type_: x86_op_type::X86_OP_INVALID,
                __bindgen_anon_1: cs_x86_op__bindgen_ty_1 { reg: x86_reg::X86_REG_INVALID },
                size: 0,
                avx_bcast: x86_avx_bcast::X86_AVX_BCAST_INVALID,
                avx_zero_opmask: false,

            }
            ; 8]

        };
        let mut a2 = a1.clone();
        a2.operands[1].type_ = x86_op_type::X86_OP_REG;
        let a1_clone = cs_x86 {
            ..a1
        };
        let a3 = cs_x86 {
            rex: 1,
            ..a1
        };
        let op_count_differ = cs_x86 {
            op_count: 1,
            ..a1
        };
        let mut op1_differ = op_count_differ.clone();
        op1_differ.operands[0].avx_bcast = x86_avx_bcast::X86_AVX_BCAST_2;

        t_eq(&a1, &a1);
        t_eq(&a1, &a2);
        t_eq(&a1, &a1_clone);
        t_ne(&a1, &a3);
        t_ne(&a1, &op_count_differ);
        t_ne(&op_count_differ, &op1_differ);
    }
}
<|endoftext|>


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

extern crate protobuf;

use super::*;
use proto::oak_api::ChannelHandle;
use proto::storage_channel::{
    StorageChannelDeleteRequest, StorageChannelReadRequest, StorageChannelRequest,
    StorageChannelResponse, StorageChannelWriteRequest,
};

fn execute_operation(operation_request: &StorageChannelRequest) -> StorageChannelResponse {
    writeln!(
        logging_channel(),
        "StorageChannelRequest: {}",
        protobuf::text_format::print_to_string(operation_request)
    )
    .unwrap();

    let mut storage_write_channel = SendChannelHalf::new(ChannelHandle::STORAGE_OUT as Handle);
    operation_request
        .write_to_writer(&mut storage_write_channel)
        .unwrap();

    let mut storage_read_channel = ReceiveChannelHalf::new(ChannelHandle::STORAGE_IN as Handle);
    let mut buffer = Vec::<u8>::with_capacity(256);
    storage_read_channel.read_message(&mut buffer).unwrap();
    let response: StorageChannelResponse = protobuf::parse_from_reader(&mut &buffer[..]).unwrap();
    writeln!(
        logging_channel(),
        "StorageChannelResponse: {}",
        protobuf::text_format::print_to_string(&response)
    )
    .unwrap();

    response
}

pub fn read(storage_name: &[u8], name: &[u8]) -> Vec<u8> {
    let mut read_request = StorageChannelReadRequest::new();
    read_request.datum_name = name.to_owned();

    let mut operation_request = StorageChannelRequest::new();
    operation_request.storage_name = storage_name.to_owned();
    operation_request.set_read_request(read_request);

    let operation_response = execute_operation(&operation_request);

    operation_response
        .get_read_response()
        .get_datum_value()
        .to_vec()
}

pub fn write(storage_name: &[u8], name: &[u8], value: &[u8]) {
    let mut write_request = StorageChannelWriteRequest::new();
    write_request.datum_name = name.to_owned();
    write_request.datum_value = value.to_owned();

    let mut operation_request = StorageChannelRequest::new();
    operation_request.storage_name = storage_name.to_owned();
    operation_request.set_write_request(write_request);

    execute_operation(&operation_request);
}

pub fn delete(storage_name: &[u8], name: &[u8]) {
    let mut delete_request = StorageChannelDeleteRequest::new();
    delete_request.datum_name = name.to_owned();

    let mut operation_request = StorageChannelRequest::new();
    operation_request.storage_name = storage_name.to_owned();
    operation_request.set_delete_request(delete_request);

    execute_operation(&operation_request);
}
<commit_msg>Use log crate in storage lib<commit_after>//
// Copyright 2019 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

extern crate protobuf;

use super::*;
use proto::oak_api::ChannelHandle;
use proto::storage_channel::{
    StorageChannelDeleteRequest, StorageChannelReadRequest, StorageChannelRequest,
    StorageChannelResponse, StorageChannelWriteRequest,
};

fn execute_operation(operation_request: &StorageChannelRequest) -> StorageChannelResponse {
    info!(
        "StorageChannelRequest: {}",
        protobuf::text_format::print_to_string(operation_request)
    );

    let mut storage_write_channel = SendChannelHalf::new(ChannelHandle::STORAGE_OUT as Handle);
    operation_request
        .write_to_writer(&mut storage_write_channel)
        .unwrap();

    let mut storage_read_channel = ReceiveChannelHalf::new(ChannelHandle::STORAGE_IN as Handle);
    let mut buffer = Vec::<u8>::with_capacity(256);
    storage_read_channel.read_message(&mut buffer).unwrap();
    let response: StorageChannelResponse = protobuf::parse_from_reader(&mut &buffer[..]).unwrap();
    info!(
        "StorageChannelResponse: {}",
        protobuf::text_format::print_to_string(&response)
    );

    response
}

pub fn read(storage_name: &[u8], name: &[u8]) -> Vec<u8> {
    let mut read_request = StorageChannelReadRequest::new();
    read_request.datum_name = name.to_owned();

    let mut operation_request = StorageChannelRequest::new();
    operation_request.storage_name = storage_name.to_owned();
    operation_request.set_read_request(read_request);

    let operation_response = execute_operation(&operation_request);

    operation_response
        .get_read_response()
        .get_datum_value()
        .to_vec()
}

pub fn write(storage_name: &[u8], name: &[u8], value: &[u8]) {
    let mut write_request = StorageChannelWriteRequest::new();
    write_request.datum_name = name.to_owned();
    write_request.datum_value = value.to_owned();

    let mut operation_request = StorageChannelRequest::new();
    operation_request.storage_name = storage_name.to_owned();
    operation_request.set_write_request(write_request);

    execute_operation(&operation_request);
}

pub fn delete(storage_name: &[u8], name: &[u8]) {
    let mut delete_request = StorageChannelDeleteRequest::new();
    delete_request.datum_name = name.to_owned();

    let mut operation_request = StorageChannelRequest::new();
    operation_request.storage_name = storage_name.to_owned();
    operation_request.set_delete_request(delete_request);

    execute_operation(&operation_request);
}
<|endoftext|>


<commit_before>use graphics::{ Context, DrawState, Graphics, Viewport };
use graphics::BACK_END_MAX_VERTEX_COUNT as BUFFER_SIZE;
use { gfx, Texture };
use gfx::format::{DepthStencil, Rgba8};
use shader_version::{ OpenGL, Shaders };
use shader_version::glsl::GLSL;

const POS_COMPONENTS: usize = 2;
const UV_COMPONENTS: usize = 2;

// Boiler plate for automatic attribute construction.
// Needs to be improved on gfx-rs side.
// For some reason, using ``*_COMPONENT` triggers some macros errors.

gfx_vertex_struct!( PositionFormat {
    pos: [f32; 2] = "pos",
});

gfx_vertex_struct!( ColorFormat {
    color: [f32; 4] = "color",
});

gfx_vertex_struct!( TexCoordsFormat {
    uv: [f32; 2] = "uv",
});

gfx_pipeline!( pipe_colored {
    pos: gfx::VertexBuffer<PositionFormat> = (),
    color: gfx::Global<[f32; 4]> = "color",
    out_color: gfx::RenderTarget<gfx::format::Rgba8> = "o_Color",
});

gfx_pipeline!( pipe_textured {
    pos: gfx::VertexBuffer<PositionFormat> = (),
    uv: gfx::VertexBuffer<TexCoordsFormat> = (),
    color: gfx::Global<[f32; 4]> = "color",
    texture: gfx::TextureSampler<[f32; 4]> = "s_texture",
    out_color: gfx::RenderTarget<gfx::format::Rgba8> = "o_Color",
    blend_target: gfx::BlendTarget<gfx::format::Rgba8> =
        ("o_Color", gfx::state::MASK_ALL, gfx::preset::blend::ALPHA),
    blend_ref: gfx::BlendRef = (),
});

/// The data used for drawing 2D graphics.
pub struct Gfx2d<R: gfx::Resources> {
    buffer_pos: gfx::handle::Buffer<R, PositionFormat>,
    buffer_uv: gfx::handle::Buffer<R, TexCoordsFormat>,
    pso_colored: gfx::pso::PipelineState<R, pipe_colored::Meta>,
    pso_textured: gfx::pso::PipelineState<R, pipe_textured::Meta>,
    sampler: gfx::handle::Sampler<R>,
}

impl<R: gfx::Resources> Gfx2d<R> {
    /// Creates a new Gfx2d object.
    pub fn new<F>(opengl: OpenGL, factory: &mut F) -> Self
        where F: gfx::Factory<R>
    {
        use gfx::traits::*;
        use shaders::{ colored, textured };

        let glsl = opengl.to_glsl();

        let pso_colored = factory.create_pipeline_simple(
            Shaders::new()
                .set(GLSL::V1_20, colored::VERTEX_GLSL_120)
                .set(GLSL::V1_50, colored::VERTEX_GLSL_150_CORE)
                .get(glsl).unwrap(),
            Shaders::new()
                .set(GLSL::V1_20, colored::FRAGMENT_GLSL_120)
                .set(GLSL::V1_50, colored::FRAGMENT_GLSL_150_CORE)
                .get(glsl).unwrap(),
            gfx::state::CullFace::Nothing,
            pipe_colored::new()
        ).unwrap();

        let pso_textured = factory.create_pipeline_simple(
            Shaders::new()
                .set(GLSL::V1_20, textured::VERTEX_GLSL_120)
                .set(GLSL::V1_50, textured::VERTEX_GLSL_150_CORE)
                .get(glsl).unwrap(),
            Shaders::new()
                .set(GLSL::V1_20, textured::FRAGMENT_GLSL_120)
                .set(GLSL::V1_50, textured::FRAGMENT_GLSL_150_CORE)
                .get(glsl).unwrap(),
            gfx::state::CullFace::Nothing,
            pipe_textured::new()
        ).unwrap();

        let buffer_pos = factory.create_buffer_dynamic(
            POS_COMPONENTS * BUFFER_SIZE,
            gfx::BufferRole::Vertex
        );
        let buffer_uv = factory.create_buffer_dynamic(
            UV_COMPONENTS * BUFFER_SIZE,
            gfx::BufferRole::Vertex
        );

        let sampler_info = gfx::tex::SamplerInfo::new(
            gfx::tex::FilterMethod::Bilinear,
            gfx::tex::WrapMode::Clamp
        );
        let sampler = factory.create_sampler(sampler_info);

        Gfx2d {
            buffer_pos: buffer_pos,
            buffer_uv: buffer_uv,
            pso_colored: pso_colored,
            pso_textured: pso_textured,
            sampler: sampler
        }
    }

    /// Renders graphics to a Gfx renderer.
    pub fn draw<C, F>(
        &mut self,
        encoder: &mut gfx::Encoder<R, C>,
        output_color: &gfx::handle::RenderTargetView<R, Rgba8>,
        output_stencil: &gfx::handle::DepthStencilView<R, DepthStencil>,
        viewport: Viewport,
        f: F
    )
        where C: gfx::CommandBuffer<R>,
              F: FnOnce(Context, &mut GfxGraphics<R, C>)
    {
        let ref mut g = GfxGraphics::new(
            encoder,
            output_color,
            output_stencil,
            self
        );
        let c = Context::new_viewport(viewport);
        f(c, g);
    }
}

/// Used for rendering 2D graphics.
pub struct GfxGraphics<'a, R, C>
    where R: gfx::Resources + 'a,
          C: gfx::CommandBuffer<R> + 'a,
          R::Buffer: 'a,
          R::Shader: 'a,
          R::Program: 'a,
          R::Texture: 'a,
          R::Sampler: 'a
{
    encoder: &'a mut gfx::Encoder<R, C>,
    output_color: &'a gfx::handle::RenderTargetView<R, Rgba8>,
    output_stencil: &'a gfx::handle::DepthStencilView<R, DepthStencil>,
    g2d: &'a mut Gfx2d<R>,
}

impl<'a, R, C> GfxGraphics<'a, R, C>
    where R: gfx::Resources,
          C: gfx::CommandBuffer<R>,
{
    /// Creates a new object for rendering 2D graphics.
    pub fn new(encoder: &'a mut gfx::Encoder<R, C>,
               output_color: &'a gfx::handle::RenderTargetView<R, Rgba8>,
               output_stencil: &'a gfx::handle::DepthStencilView<R, DepthStencil>,
               g2d: &'a mut Gfx2d<R>) -> Self {
        GfxGraphics {
            encoder: encoder,
            output_color: output_color,
            output_stencil: output_stencil,
            g2d: g2d,
        }
    }

    /// Returns true if texture has alpha channel.
    pub fn has_texture_alpha(&self, texture: &Texture<R>) -> bool {
        use gfx::format::SurfaceType::*;

        match texture.surface.get_info().format {
            R4_G4_B4_A4
            | R5_G5_B5_A1
            | R8_G8_B8_A8
            | R10_G10_B10_A2
            | R16_G16_B16_A16
            | R32_G32_B32_A32 => true,
            R3_G3_B2
            | R4_G4
            | R5_G6_B5
            | R8 | R8_G8 | R8_G8_B8
            | R11_G11_B10
            | R16 | R16_G16 | R16_G16_B16
            | R32 | R32_G32 | R32_G32_B32
            | D16 | D24 | D24_S8 | D32 => false,
        }
    }
}

impl<'a, R, C> Graphics for GfxGraphics<'a, R, C>
    where R: gfx::Resources,
          C: gfx::CommandBuffer<R>,
          R::Buffer: 'a,
          R::Shader: 'a,
          R::Program: 'a,
          R::Texture: 'a,
          R::Sampler: 'a
{
    type Texture = Texture<R>;

    fn clear_color(&mut self, color: [f32; 4]) {
        let &mut GfxGraphics {
            ref mut encoder,
            output_color,
            ..
        } = self;
        encoder.clear(output_color, color);
    }

    fn clear_stencil(&mut self, value: u8) {
        let &mut GfxGraphics {
            ref mut encoder,
            output_stencil,
            ..
        } = self;
        encoder.clear_stencil(output_stencil, value);
    }

    fn tri_list<F>(
        &mut self,
        draw_state: &DrawState,
        color: &[f32; 4],
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32]))
    {
        let &mut GfxGraphics {
            ref mut encoder,
            output_color,
            g2d: &mut Gfx2d {
                ref mut buffer_pos,
                ref mut pso_colored,
                ..
            },
            ..
        } = self;

        // TODO: Update draw state.

        f(&mut |vertices: &[f32]| {
            use std::mem::transmute;

            unsafe {
                encoder.update_buffer(&buffer_pos, transmute(vertices), 0)
                    .unwrap();
            }

            let data = pipe_colored::Data {
                pos: buffer_pos.clone(),
                color: *color,
                out_color: output_color.clone(),
            };

            let n = vertices.len() / POS_COMPONENTS;
            let slice = gfx::Slice {
                    instances: None,
                    start: 0,
                    end: n as u32,
                    kind: gfx::SliceKind::Vertex
            };
            encoder.draw(&slice, pso_colored, &data);
        })
    }

    fn tri_list_uv<F>(
        &mut self,
        draw_state: &DrawState,
        color: &[f32; 4],
        texture: &<Self as Graphics>::Texture,
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32], &[f32]))
    {
        let &mut GfxGraphics {
            ref mut encoder,
            output_color,
            g2d: &mut Gfx2d {
                ref mut buffer_pos,
                ref mut buffer_uv,
                ref mut pso_textured,
                ref sampler,
                ..
            },
            ..
        } = self;

        // TODO: Update draw state.

        f(&mut |vertices: &[f32], texture_coords: &[f32]| {
            use std::mem::transmute;

            assert_eq!(
                vertices.len() * UV_COMPONENTS,
                texture_coords.len() * POS_COMPONENTS
            );
            unsafe {
                encoder.update_buffer(&buffer_pos, transmute(vertices), 0)
                    .unwrap();
                encoder.update_buffer(&buffer_uv, transmute(texture_coords), 0)
                    .unwrap();
            }

            let data = pipe_textured::Data {
                pos: buffer_pos.clone(),
                uv: buffer_uv.clone(),
                color: *color,
                texture: (texture.view.clone(), sampler.clone()),
                out_color: output_color.clone(),
                blend_target: output_color.clone(),
                blend_ref: [1.0; 4],
            };

            let n = vertices.len() / POS_COMPONENTS;
            let slice = gfx::Slice {
                    instances: None,
                    start: 0,
                    end: n as u32,
                    kind: gfx::SliceKind::Vertex
            };
            encoder.draw(&slice, pso_textured, &data);
        })
    }
}
<commit_msg>Fixed alpha blending<commit_after>use graphics::{ Context, DrawState, Graphics, Viewport };
use graphics::BACK_END_MAX_VERTEX_COUNT as BUFFER_SIZE;
use { gfx, Texture };
use gfx::format::{DepthStencil, Rgba8};
use shader_version::{ OpenGL, Shaders };
use shader_version::glsl::GLSL;

const POS_COMPONENTS: usize = 2;
const UV_COMPONENTS: usize = 2;

// Boiler plate for automatic attribute construction.
// Needs to be improved on gfx-rs side.
// For some reason, using ``*_COMPONENT` triggers some macros errors.

gfx_vertex_struct!( PositionFormat {
    pos: [f32; 2] = "pos",
});

gfx_vertex_struct!( ColorFormat {
    color: [f32; 4] = "color",
});

gfx_vertex_struct!( TexCoordsFormat {
    uv: [f32; 2] = "uv",
});

gfx_pipeline!( pipe_colored {
    pos: gfx::VertexBuffer<PositionFormat> = (),
    color: gfx::Global<[f32; 4]> = "color",
    blend_target: gfx::BlendTarget<gfx::format::Rgba8> =
        ("o_Color", gfx::state::MASK_ALL, gfx::preset::blend::ALPHA),
});

gfx_pipeline!( pipe_textured {
    pos: gfx::VertexBuffer<PositionFormat> = (),
    uv: gfx::VertexBuffer<TexCoordsFormat> = (),
    color: gfx::Global<[f32; 4]> = "color",
    texture: gfx::TextureSampler<[f32; 4]> = "s_texture",
    blend_target: gfx::BlendTarget<gfx::format::Rgba8> =
        ("o_Color", gfx::state::MASK_ALL, gfx::preset::blend::ALPHA),
    blend_ref: gfx::BlendRef = (),
});

/// The data used for drawing 2D graphics.
pub struct Gfx2d<R: gfx::Resources> {
    buffer_pos: gfx::handle::Buffer<R, PositionFormat>,
    buffer_uv: gfx::handle::Buffer<R, TexCoordsFormat>,
    pso_colored: gfx::pso::PipelineState<R, pipe_colored::Meta>,
    pso_textured: gfx::pso::PipelineState<R, pipe_textured::Meta>,
    sampler: gfx::handle::Sampler<R>,
}

impl<R: gfx::Resources> Gfx2d<R> {
    /// Creates a new Gfx2d object.
    pub fn new<F>(opengl: OpenGL, factory: &mut F) -> Self
        where F: gfx::Factory<R>
    {
        use gfx::traits::*;
        use shaders::{ colored, textured };

        let glsl = opengl.to_glsl();

        let pso_colored = factory.create_pipeline_simple(
            Shaders::new()
                .set(GLSL::V1_20, colored::VERTEX_GLSL_120)
                .set(GLSL::V1_50, colored::VERTEX_GLSL_150_CORE)
                .get(glsl).unwrap(),
            Shaders::new()
                .set(GLSL::V1_20, colored::FRAGMENT_GLSL_120)
                .set(GLSL::V1_50, colored::FRAGMENT_GLSL_150_CORE)
                .get(glsl).unwrap(),
            gfx::state::CullFace::Nothing,
            pipe_colored::new()
        ).unwrap();

        let pso_textured = factory.create_pipeline_simple(
            Shaders::new()
                .set(GLSL::V1_20, textured::VERTEX_GLSL_120)
                .set(GLSL::V1_50, textured::VERTEX_GLSL_150_CORE)
                .get(glsl).unwrap(),
            Shaders::new()
                .set(GLSL::V1_20, textured::FRAGMENT_GLSL_120)
                .set(GLSL::V1_50, textured::FRAGMENT_GLSL_150_CORE)
                .get(glsl).unwrap(),
            gfx::state::CullFace::Nothing,
            pipe_textured::new()
        ).unwrap();

        let buffer_pos = factory.create_buffer_dynamic(
            POS_COMPONENTS * BUFFER_SIZE,
            gfx::BufferRole::Vertex
        );
        let buffer_uv = factory.create_buffer_dynamic(
            UV_COMPONENTS * BUFFER_SIZE,
            gfx::BufferRole::Vertex
        );

        let sampler_info = gfx::tex::SamplerInfo::new(
            gfx::tex::FilterMethod::Bilinear,
            gfx::tex::WrapMode::Clamp
        );
        let sampler = factory.create_sampler(sampler_info);

        Gfx2d {
            buffer_pos: buffer_pos,
            buffer_uv: buffer_uv,
            pso_colored: pso_colored,
            pso_textured: pso_textured,
            sampler: sampler
        }
    }

    /// Renders graphics to a Gfx renderer.
    pub fn draw<C, F>(
        &mut self,
        encoder: &mut gfx::Encoder<R, C>,
        output_color: &gfx::handle::RenderTargetView<R, Rgba8>,
        output_stencil: &gfx::handle::DepthStencilView<R, DepthStencil>,
        viewport: Viewport,
        f: F
    )
        where C: gfx::CommandBuffer<R>,
              F: FnOnce(Context, &mut GfxGraphics<R, C>)
    {
        let ref mut g = GfxGraphics::new(
            encoder,
            output_color,
            output_stencil,
            self
        );
        let c = Context::new_viewport(viewport);
        f(c, g);
    }
}

/// Used for rendering 2D graphics.
pub struct GfxGraphics<'a, R, C>
    where R: gfx::Resources + 'a,
          C: gfx::CommandBuffer<R> + 'a,
          R::Buffer: 'a,
          R::Shader: 'a,
          R::Program: 'a,
          R::Texture: 'a,
          R::Sampler: 'a
{
    encoder: &'a mut gfx::Encoder<R, C>,
    output_color: &'a gfx::handle::RenderTargetView<R, Rgba8>,
    output_stencil: &'a gfx::handle::DepthStencilView<R, DepthStencil>,
    g2d: &'a mut Gfx2d<R>,
}

impl<'a, R, C> GfxGraphics<'a, R, C>
    where R: gfx::Resources,
          C: gfx::CommandBuffer<R>,
{
    /// Creates a new object for rendering 2D graphics.
    pub fn new(encoder: &'a mut gfx::Encoder<R, C>,
               output_color: &'a gfx::handle::RenderTargetView<R, Rgba8>,
               output_stencil: &'a gfx::handle::DepthStencilView<R, DepthStencil>,
               g2d: &'a mut Gfx2d<R>) -> Self {
        GfxGraphics {
            encoder: encoder,
            output_color: output_color,
            output_stencil: output_stencil,
            g2d: g2d,
        }
    }

    /// Returns true if texture has alpha channel.
    pub fn has_texture_alpha(&self, texture: &Texture<R>) -> bool {
        use gfx::format::SurfaceType::*;

        match texture.surface.get_info().format {
            R4_G4_B4_A4
            | R5_G5_B5_A1
            | R8_G8_B8_A8
            | R10_G10_B10_A2
            | R16_G16_B16_A16
            | R32_G32_B32_A32 => true,
            R3_G3_B2
            | R4_G4
            | R5_G6_B5
            | R8 | R8_G8 | R8_G8_B8
            | R11_G11_B10
            | R16 | R16_G16 | R16_G16_B16
            | R32 | R32_G32 | R32_G32_B32
            | D16 | D24 | D24_S8 | D32 => false,
        }
    }
}

impl<'a, R, C> Graphics for GfxGraphics<'a, R, C>
    where R: gfx::Resources,
          C: gfx::CommandBuffer<R>,
          R::Buffer: 'a,
          R::Shader: 'a,
          R::Program: 'a,
          R::Texture: 'a,
          R::Sampler: 'a
{
    type Texture = Texture<R>;

    fn clear_color(&mut self, color: [f32; 4]) {
        let &mut GfxGraphics {
            ref mut encoder,
            output_color,
            ..
        } = self;
        encoder.clear(output_color, color);
    }

    fn clear_stencil(&mut self, value: u8) {
        let &mut GfxGraphics {
            ref mut encoder,
            output_stencil,
            ..
        } = self;
        encoder.clear_stencil(output_stencil, value);
    }

    fn tri_list<F>(
        &mut self,
        draw_state: &DrawState,
        color: &[f32; 4],
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32]))
    {
        let &mut GfxGraphics {
            ref mut encoder,
            output_color,
            g2d: &mut Gfx2d {
                ref mut buffer_pos,
                ref mut pso_colored,
                ..
            },
            ..
        } = self;

        // TODO: Update draw state.

        f(&mut |vertices: &[f32]| {
            use std::mem::transmute;

            unsafe {
                encoder.update_buffer(&buffer_pos, transmute(vertices), 0)
                    .unwrap();
            }

            let data = pipe_colored::Data {
                pos: buffer_pos.clone(),
                color: *color,
                blend_target: output_color.clone(),
            };

            let n = vertices.len() / POS_COMPONENTS;
            let slice = gfx::Slice {
                    instances: None,
                    start: 0,
                    end: n as u32,
                    kind: gfx::SliceKind::Vertex
            };
            encoder.draw(&slice, pso_colored, &data);
        })
    }

    fn tri_list_uv<F>(
        &mut self,
        draw_state: &DrawState,
        color: &[f32; 4],
        texture: &<Self as Graphics>::Texture,
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32], &[f32]))
    {
        let &mut GfxGraphics {
            ref mut encoder,
            output_color,
            g2d: &mut Gfx2d {
                ref mut buffer_pos,
                ref mut buffer_uv,
                ref mut pso_textured,
                ref sampler,
                ..
            },
            ..
        } = self;

        // TODO: Update draw state.

        f(&mut |vertices: &[f32], texture_coords: &[f32]| {
            use std::mem::transmute;

            assert_eq!(
                vertices.len() * UV_COMPONENTS,
                texture_coords.len() * POS_COMPONENTS
            );
            unsafe {
                encoder.update_buffer(&buffer_pos, transmute(vertices), 0)
                    .unwrap();
                encoder.update_buffer(&buffer_uv, transmute(texture_coords), 0)
                    .unwrap();
            }

            let data = pipe_textured::Data {
                pos: buffer_pos.clone(),
                uv: buffer_uv.clone(),
                color: *color,
                texture: (texture.view.clone(), sampler.clone()),
                blend_target: output_color.clone(),
                blend_ref: [1.0; 4],
            };

            let n = vertices.len() / POS_COMPONENTS;
            let slice = gfx::Slice {
                    instances: None,
                    start: 0,
                    end: n as u32,
                    kind: gfx::SliceKind::Vertex
            };
            encoder.draw(&slice, pso_textured, &data);
        })
    }
}
<|endoftext|>


<commit_before>
use input;

/// Describes a behavior.
///
/// This is used for more complex event logic.
/// Can also be used for game AI.
#[deriving(Clone, PartialEq)]
pub enum Behavior<A> {
    /// A button was pressed.
    Pressed(input::Button),
    /// A button was released.
    Released(input::Button),
    /// A high level description of an action.
    Action(A),
    /// Converts `Success` into `Failure` and vice versa.
    Fail(Box<Behavior<A>>),
    /// Ignores failures and returns `Success`.
    AlwaysSucceed(Box<Behavior<A>>),
    /// Runs behaviors one by one until a behavior succeeds.
    ///
    /// If a behavior fails it will try the next one.
    /// Fails if the last behavior fails.
    /// Can be thought of as a short-circuited logical OR gate.
    Select(Vec<Behavior<A>>),
    /// Waits an amount of time before continuing.
    ///
    /// f64: Time in seconds
    Wait(f64),
    /// Wait forever.
    WaitForever,
    /// `If(condition, success, failure)`
    If(Box<Behavior<A>>, Box<Behavior<A>>, Box<Behavior<A>>),
    /// Runs behaviors one by one until all succeeded.
    ///
    /// The sequence fails if a behavior fails.
    /// The sequence succeeds if all the behavior succeeds.
    /// Can be thought of as a short-circuited logical AND gate.
    Sequence(Vec<Behavior<A>>),
    /// Loops while conditional behavior is running.
    ///
    /// Succeeds if the conditional behavior succeeds.
    /// Fails if the conditional behavior fails,
    /// or if any behavior in the loop body fails.
    While(Box<Behavior<A>>, Vec<Behavior<A>>),
    /// Runs all behaviors in parallel.
    ///
    /// Succeeds if all behavior succeeds.
    /// Fails is any behavior fails.
    WhenAll(Vec<Behavior<A>>),
}
<commit_msg>Fixed comment<commit_after>
use input;

/// Describes a behavior.
///
/// This is used for more complex event logic.
/// Can also be used for game AI.
#[deriving(Clone, PartialEq)]
pub enum Behavior<A> {
    /// A button was pressed.
    Pressed(input::Button),
    /// A button was released.
    Released(input::Button),
    /// A high level description of an action.
    Action(A),
    /// Converts `Success` into `Failure` and vice versa.
    Fail(Box<Behavior<A>>),
    /// Ignores failures and returns `Success`.
    AlwaysSucceed(Box<Behavior<A>>),
    /// Runs behaviors one by one until a behavior succeeds.
    ///
    /// If a behavior fails it will try the next one.
    /// Fails if the last behavior fails.
    /// Can be thought of as a short-circuited logical OR gate.
    Select(Vec<Behavior<A>>),
    /// Waits an amount of time before continuing.
    ///
    /// f64: Time in seconds
    Wait(f64),
    /// Wait forever.
    WaitForever,
    /// `If(condition, success, failure)`
    If(Box<Behavior<A>>, Box<Behavior<A>>, Box<Behavior<A>>),
    /// Runs behaviors one by one until all succeeded.
    ///
    /// The sequence fails if a behavior fails.
    /// The sequence succeeds if all the behavior succeeds.
    /// Can be thought of as a short-circuited logical AND gate.
    Sequence(Vec<Behavior<A>>),
    /// Loops while conditional behavior is running.
    ///
    /// Succeeds if the conditional behavior succeeds.
    /// Fails if the conditional behavior fails,
    /// or if any behavior in the loop body fails.
    While(Box<Behavior<A>>, Vec<Behavior<A>>),
    /// Runs all behaviors in parallel until all succeeded.
    ///
    /// Succeeds if all behavior succeeds.
    /// Fails is any behavior fails.
    WhenAll(Vec<Behavior<A>>),
}
<|endoftext|>


<commit_before>use std::fmt;

use num::bigint;

pub const DEFAULT_INDENT_WIDTH: usize = 2;
pub const DEFAULT_MAX_TERMS_PER_LINE: usize = 4;

#[derive(Debug, PartialEq)]
pub enum BertTerm {
    Nil,
    Int(i32),
    BigInt(bigint::BigInt),
    Float(f64),
    Atom(String),
    Tuple(Vec<BertTerm>),
    List(Vec<BertTerm>),
    Map(Vec<BertTerm>, Vec<BertTerm>),
    String(Vec<u8>),
    Binary(Vec<u8>)
}

impl BertTerm {
    fn is_basic(&self) -> bool {
        match *self {
            BertTerm::Int(_)
            | BertTerm::BigInt(_)
            | BertTerm::Float(_)
            | BertTerm::Atom(_)
            | BertTerm::String(_)
            | BertTerm::Binary(_)
            | BertTerm::Nil => true,
            BertTerm::List(_)
            | BertTerm::Tuple(_)
            | BertTerm::Map(_, _) => false
        }
    }
}

impl fmt::Display for BertTerm {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let pp = PrettyPrinter::new(self,
                                    DEFAULT_INDENT_WIDTH,
                                    DEFAULT_MAX_TERMS_PER_LINE);
        write!(f, "{}", pp)
    }
}

pub struct PrettyPrinter<'a> {
    term: &'a BertTerm,
    indent_width: usize,
    max_terms_per_line: usize
}

impl <'a> fmt::Display for PrettyPrinter<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.write_term(self.term, f, 0)
    }
}

impl <'a> PrettyPrinter<'a> {
    /// Creates a pretty printer for `term` where sub-terms
    /// are indented with a width of `indent_width` and a
    /// maximum of `max_terms_per_line` basic terms (i.e.,
    /// integers, floats, strings) can be printed per line.
    pub fn new(term: &'a BertTerm,
               indent_width: usize,
               max_terms_per_line: usize) -> Self {
        PrettyPrinter { term, indent_width, max_terms_per_line }
    }

    fn write_term(&self, term: &BertTerm, f: &mut fmt::Formatter, indent: usize) -> fmt::Result {
        match *term {
            BertTerm::Nil => write!(f, "[]"),
            BertTerm::Int(n) => write!(f, "{}", n),
            BertTerm::BigInt(ref n) => write!(f, "{}", n),
            BertTerm::Float(x) => write!(f, "{}", x),
            BertTerm::Atom(ref s) => write!(f, "{}", s),
            BertTerm::String(ref bytes) => self.write_string(bytes, f, "\"", "\""),
            BertTerm::Binary(ref bytes) => self.write_string(bytes, f, "<<\"", "\">>"),
            BertTerm::List(ref terms) => self.write_collection(terms, f, indent, '[', ']'),
            BertTerm::Tuple(ref terms) => self.write_collection(terms, f, indent, '{', '}'),
            BertTerm::Map(ref keys, ref vals) => self.write_map(keys, vals, f, indent)
        }
    }

    fn write_string(&self,
                    bytes: &[u8],
                    f: &mut fmt::Formatter,
                    open: &str,
                    close: &str) -> fmt::Result {
        write!(f, "{}", open)?;
        for &b in bytes {
            if is_printable(b) {
                write!(f, "{}", b as char)?;
            } else {
                write!(f, "\\x{:02x}", b)?;
            }
        }
        write!(f, "{}", close)
    }

    fn write_collection(&self,
                        terms: &[BertTerm],
                        f: &mut fmt::Formatter,
                        indent: usize,
                        open: char,
                        close: char) -> fmt::Result {
        let multi_line = !self.is_small_collection(terms);
        write!(f, "{}", open)?;

        let mut first = true;
        for t in terms {
            if !first { write!(f, ", ")?; }
            if multi_line {
                write!(f, "\n")?;
                self.indent(f, indent + 1)?;
            }
            self.write_term(t, f, indent + 1)?;
            first = false;
        }

        if multi_line {
            write!(f, "\n")?;
            self.indent(f, indent)?;
        }

        write!(f, "{}", close)
    }

    fn write_map(&self,
                 keys: &[BertTerm],
                 vals: &[BertTerm],
                 f: &mut fmt::Formatter,
                 indent: usize) -> fmt::Result {
        let mult_line =
            !self.is_small_collection(keys) || !self.is_small_collection(vals);
        write!(f, "#{{")?;

        for i in 0 .. keys.len() {
            if i > 0 { write!(f, ", ")?; }
            if mult_line {
                write!(f, "\n")?;
                self.indent(f, indent + 1)?;
            }
            self.write_term(&keys[i], f, indent + 1)?;
            write!(f, " => ")?;
            self.write_term(&vals[i], f, indent + 1)?;
        }

        if mult_line {
            write!(f, "\n")?;
            self.indent(f, indent)?;
        }
        write!(f, "}}")
    }

    fn indent(&self, f: &mut fmt::Formatter, depth: usize) -> fmt::Result {
        for _ in 0 .. depth * self.indent_width {
            write!(f, " ")?;
        }
        Ok(())
    }

    fn is_small_collection(&self, terms: &[BertTerm]) -> bool {
        terms.len() <= self.max_terms_per_line &&
            terms.iter().all(BertTerm::is_basic)
    }
}

fn is_printable(b: u8) -> bool {
    b >= 0x20 && b <= 0x7e
}
<commit_msg>Apply a few micro-optimizations to pretty printing<commit_after>use std::fmt::{self, Write};

use num::bigint;

pub const DEFAULT_INDENT_WIDTH: usize = 2;
pub const DEFAULT_MAX_TERMS_PER_LINE: usize = 4;

#[derive(Debug, PartialEq)]
pub enum BertTerm {
    Nil,
    Int(i32),
    BigInt(bigint::BigInt),
    Float(f64),
    Atom(String),
    Tuple(Vec<BertTerm>),
    List(Vec<BertTerm>),
    Map(Vec<BertTerm>, Vec<BertTerm>),
    String(Vec<u8>),
    Binary(Vec<u8>)
}

impl BertTerm {
    fn is_basic(&self) -> bool {
        match *self {
            BertTerm::Int(_)
            | BertTerm::BigInt(_)
            | BertTerm::Float(_)
            | BertTerm::Atom(_)
            | BertTerm::String(_)
            | BertTerm::Binary(_)
            | BertTerm::Nil => true,
            BertTerm::List(_)
            | BertTerm::Tuple(_)
            | BertTerm::Map(_, _) => false
        }
    }
}

impl fmt::Display for BertTerm {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let pp = PrettyPrinter::new(self,
                                    DEFAULT_INDENT_WIDTH,
                                    DEFAULT_MAX_TERMS_PER_LINE);
        write!(f, "{}", pp)
    }
}

pub struct PrettyPrinter<'a> {
    term: &'a BertTerm,
    indent_width: usize,
    max_terms_per_line: usize
}

impl <'a> fmt::Display for PrettyPrinter<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.write_term(self.term, f, 0)
    }
}

impl <'a> PrettyPrinter<'a> {
    /// Creates a pretty printer for `term` where sub-terms
    /// are indented with a width of `indent_width` and a
    /// maximum of `max_terms_per_line` basic terms (i.e.,
    /// integers, floats, strings) can be printed per line.
    pub fn new(term: &'a BertTerm,
               indent_width: usize,
               max_terms_per_line: usize) -> Self {
        PrettyPrinter { term, indent_width, max_terms_per_line }
    }

    fn write_term(&self, term: &BertTerm, f: &mut fmt::Formatter, depth: usize) -> fmt::Result {
        match *term {
            BertTerm::Nil => f.write_str("[]"),
            BertTerm::Int(n) => write!(f, "{}", n),
            BertTerm::BigInt(ref n) => write!(f, "{}", n),
            BertTerm::Float(x) => write!(f, "{}", x),
            BertTerm::Atom(ref s) => f.write_str(s),
            BertTerm::String(ref bytes) => self.write_string(bytes, f, "\"", "\""),
            BertTerm::Binary(ref bytes) => self.write_string(bytes, f, "<<\"", "\">>"),
            BertTerm::List(ref terms) => self.write_collection(terms, f, depth, '[', ']'),
            BertTerm::Tuple(ref terms) => self.write_collection(terms, f, depth, '{', '}'),
            BertTerm::Map(ref keys, ref vals) => self.write_map(keys, vals, f, depth)
        }
    }

    fn write_string(&self,
                    bytes: &[u8],
                    f: &mut fmt::Formatter,
                    open: &str,
                    close: &str) -> fmt::Result {
        f.write_str(open)?;
        for &b in bytes {
            if is_printable(b) {
                f.write_char(b as char)?;
            } else {
                write!(f, "\\x{:02x}", b)?;
            }
        }
        f.write_str(close)
    }

    fn write_collection(&self,
                        terms: &[BertTerm],
                        f: &mut fmt::Formatter,
                        depth: usize,
                        open: char,
                        close: char) -> fmt::Result {
        let multi_line = !self.is_small_collection(terms);

        // Every element will have the same indentation,
        // so pre-compute it once.
        let prefix =
            if multi_line {
                self.indentation(depth+1)
            } else {
                String::new()
            };

        f.write_char(open)?;
        let mut comma = "";
        for t in terms {
            f.write_str(comma)?;
            f.write_str(&prefix)?;
            self.write_term(t, f, depth + 1)?;
            comma = ", ";
        }

        if multi_line {
            f.write_str(&self.indentation(depth))?;
        }

        f.write_char(close)
    }

    fn write_map(&self,
                 keys: &[BertTerm],
                 vals: &[BertTerm],
                 f: &mut fmt::Formatter,
                 depth: usize) -> fmt::Result {
        let multi_line =
            !self.is_small_collection(keys) || !self.is_small_collection(vals);
        let prefix =
            if multi_line {
                self.indentation(depth+1)
            } else {
                String::new()
            };

        f.write_str("#{")?;
        let mut comma = "";
        for i in 0 .. keys.len() {
            f.write_str(comma)?;
            f.write_str(&prefix)?;
            self.write_term(&keys[i], f, depth + 1)?;
            f.write_str(" => ")?;
            self.write_term(&vals[i], f, depth + 1)?;
            comma = ", ";
        }

        if multi_line {
            f.write_str(&self.indentation(depth))?;
        }
        f.write_str("}")
    }

    fn is_small_collection(&self, terms: &[BertTerm]) -> bool {
        terms.len() <= self.max_terms_per_line &&
            terms.iter().all(BertTerm::is_basic)
    }

    fn indentation(&self, depth: usize) -> String {
        ::std::iter::once('\n')
            .chain((0 .. depth * self.indent_width).map(|_| ' '))
            .collect()
    }
}

fn is_printable(b: u8) -> bool {
    b >= 0x20 && b <= 0x7e
}
<|endoftext|>


<commit_before>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate common;

use common::Solver;

// x by y => C = (1 + 2 + .. + x) * (1 + 2 + .. + y) recutangulars
//             = (x (1 + x) / 2) * (y (1 + y)) / 2
//             = xy (1 + x)(1 + y) / 4
fn count_rect((x, y): (uint, uint)) -> uint {
    x * y * (1 + x) * (1 + y) / 4
}

fn distance(a: uint, target: uint) -> uint {
    if a > target { a - target } else { target - a }
}

pub fn check_distance(min_dist: &mut uint, min_pos: &mut (uint, uint), pos: (uint, uint), target: uint) {
    let dist = distance(count_rect(pos), target);
    if dist < *min_dist {
        *min_dist = dist;
        *min_pos  = pos;
    }
}

pub fn solve() -> String {
    let target = 2000000;

    let mut x = 1;
    let mut y = 1;

    while count_rect((x, y)) < target { x += 1; y += 1; }
    assert!(count_rect((x, y)) >= target);

    let mut nearest = (x, y);
    let mut dist = distance(count_rect(nearest), target);
    while x >= 1 {
        while count_rect((x, y)) < target { y += 1; }
        assert!(count_rect((x, y)) >= target);
        check_distance(&mut dist, &mut nearest, (x, y), target);
        check_distance(&mut dist, &mut nearest, (x, y - 1), target);
        x -= 1;
    }

    let (x, y) = nearest;
    (x * y).to_string()
}

fn main() { Solver::new("2772", solve).run(); }
<commit_msg>remove extra `pub`<commit_after>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate common;

use common::Solver;

// x by y => C = (1 + 2 + .. + x) * (1 + 2 + .. + y) recutangulars
//             = (x (1 + x) / 2) * (y (1 + y)) / 2
//             = xy (1 + x)(1 + y) / 4
fn count_rect((x, y): (uint, uint)) -> uint {
    x * y * (1 + x) * (1 + y) / 4
}

fn distance(a: uint, target: uint) -> uint {
    if a > target { a - target } else { target - a }
}

fn check_distance(min_dist: &mut uint, min_pos: &mut (uint, uint), pos: (uint, uint), target: uint) {
    let dist = distance(count_rect(pos), target);
    if dist < *min_dist {
        *min_dist = dist;
        *min_pos  = pos;
    }
}

fn solve() -> String {
    let target = 2000000;

    let mut x = 1;
    let mut y = 1;

    while count_rect((x, y)) < target { x += 1; y += 1; }
    assert!(count_rect((x, y)) >= target);

    let mut nearest = (x, y);
    let mut dist = distance(count_rect(nearest), target);
    while x >= 1 {
        while count_rect((x, y)) < target { y += 1; }
        assert!(count_rect((x, y)) >= target);
        check_distance(&mut dist, &mut nearest, (x, y), target);
        check_distance(&mut dist, &mut nearest, (x, y - 1), target);
        x -= 1;
    }

    let (x, y) = nearest;
    (x * y).to_string()
}

fn main() { Solver::new("2772", solve).run(); }
<|endoftext|>


<commit_before>fn main() {
    manage_docs();
}

#[cfg(any(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs"))]
fn manage_docs() {
    extern crate lgpl_docs;
    const PATH: &'static str = "src";
    const IGNORES: &'static [&'static str] = &["event.rs", "lib.rs", "prelude.rs", "rt.rs"];
    lgpl_docs::purge(PATH, IGNORES);
    if cfg!(feature = "embed-lgpl-docs") {
        lgpl_docs::embed(lgpl_docs::Library::Gdk, PATH, IGNORES);
    }
}

#[cfg(not(any(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs")))]
fn manage_docs() {}
<commit_msg>Don't include LGPL docs in the docs if both embed-lgpl-docs and purge-lgpl-docs features are selected<commit_after>fn main() {
    manage_docs();
}

#[cfg(all(
    any(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs"),
    not(all(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs"))
))]
fn manage_docs() {
    extern crate lgpl_docs;
    const PATH: &'static str = "src";
    const IGNORES: &'static [&'static str] = &["event.rs", "lib.rs", "prelude.rs", "rt.rs"];
    lgpl_docs::purge(PATH, IGNORES);
    if cfg!(feature = "embed-lgpl-docs") {
        lgpl_docs::embed(lgpl_docs::Library::Gdk, PATH, IGNORES);
    }
}

#[cfg(any(
    all(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs"),
    not(any(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs"))
))]
fn manage_docs() {}
<|endoftext|>


<commit_before>extern crate autocfg;

use std::env;

fn main() {
    let ac = autocfg::new();
    if ac.probe_type("i128") {
        println!("cargo:rustc-cfg=has_i128");
    } else if env::var_os("CARGO_FEATURE_I128").is_some() {
        panic!("i128 support was not detected!");
    }

    autocfg::rerun_path("build.rs");
}
<commit_msg>Trust the "i128" feature<commit_after>extern crate autocfg;

use std::env;

fn main() {
    // If the "i128" feature is explicity requested, don't bother probing for it.
    // It will still cause a build error if that was set improperly.
    if env::var_os("CARGO_FEATURE_I128").is_some() || autocfg::new().probe_type("i128") {
        autocfg::emit("has_i128");
    }

    autocfg::rerun_path("build.rs");
}
<|endoftext|>


<commit_before>extern crate skeptic;

fn main() {
    skeptic::generate_doc_tests(&["README.md"]);
}
<commit_msg>Implemented test automation<commit_after>extern crate skeptic;

use std::fs;

fn main() {
    let paths = fs::read_dir("./pages/").unwrap();

    for path in paths {
        let p = path.unwrap().path();
        let s = p.to_str().unwrap();
        if s.contains(".md") {
                skeptic::generate_doc_tests(&[s])
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::path::Path;
use std::process::Command;

trait CheckedCommand {
    fn check(&mut self);
}

impl CheckedCommand for Command {
    fn check(&mut self) {
        if !self.status().unwrap().success() {
            panic!("command {:?} failed", self)
        }
    }
}

fn main() {
    // Unless otherwise specified, do not re-run this script
    println!("cargo:rerun-if-changed=build.rs");

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir);

    let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src_path = Path::new(&src_dir);

    let schema_path = out_path.join("graphql-schema.json");

    eprintln!("ENV: {:?}", env::vars().collect::<Vec<_>>());

    if env::var_os("CARGO_FEATURE_GRAPHQL_SCHEMA").is_some() {
        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "-vv",
                "--path",
                src_dir.as_ref(),
                "--bin",
                "turingarena-graphql-schema",
                "--root",
                out_path.to_str().unwrap(),
                "--force",
                "--debug",
                "--offline",
                "--no-default-features",
                "--features",
                "contest",
            ])
            .env_clear()
            .envs(
                std::env::vars_os()
                    .filter(|(k, _)| !k.to_string_lossy().starts_with("CARGO_FEATURE_")),
            )
            .env(
                "CARGO_TARGET_DIR",
                out_path.join("graphql-schema-target").to_str().unwrap(),
            )
            .check();

        let schema_file = File::create(&schema_path).unwrap();

        Command::new(out_path.join("bin").join("turingarena-graphql-schema"))
            .stdout(schema_file)
            .check();
    }

    if env::var_os("CARGO_FEATURE_CLI_ADMIN").is_some() {
        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "-vv",
                "graphql_client_cli",
                "--root",
                out_path.to_str().unwrap(),
                "--force",
                // FIXME: should be offline
                // "--offline",
            ])
            .env(
                "CARGO_TARGET_DIR",
                out_path.join("graphql-client-cli-target").to_str().unwrap(),
            )
            .check();

        Command::new(out_path.join("bin").join("graphql-client"))
            .args(&[
                "generate",
                "--output-directory",
                out_path.to_str().unwrap(),
                "--schema-path",
                schema_path.to_str().unwrap(),
                src_path
                    .join("src")
                    .join("contest")
                    .join("operations.graphql")
                    .to_str()
                    .unwrap(),
            ])
            .check();
    }

    if env::var_os("CARGO_FEATURE_WEB").is_some() {
        {
            let mut options = fs_extra::dir::CopyOptions::new();
            options.overwrite = true;
            fs_extra::dir::copy(src_path.join("web"), out_path, &options).unwrap();
        }

        let out_web_path = out_path.join("web");

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["ci", "--ignore-scripts"])
            .check();

        std::fs::create_dir_all(&out_web_path.join("__generated__")).unwrap();

        std::fs::copy(
            &schema_path,
            &out_web_path
                .join("__generated__")
                .join("graphql-schema.json"),
        )
        .unwrap();

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["run", "prepare"])
            .check();

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["run", "build"])
            .check();
    }
}
<commit_msg>Rerun `build.rs` when `operations.graphql` changes<commit_after>use std::env;
use std::fs::File;
use std::path::Path;
use std::process::Command;

trait CheckedCommand {
    fn check(&mut self);
}

impl CheckedCommand for Command {
    fn check(&mut self) {
        if !self.status().unwrap().success() {
            panic!("command {:?} failed", self)
        }
    }
}

fn main() {
    // Unless otherwise specified, do not re-run this script
    println!("cargo:rerun-if-changed=build.rs");

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir);

    let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src_path = Path::new(&src_dir);

    let schema_path = out_path.join("graphql-schema.json");

    eprintln!("ENV: {:?}", env::vars().collect::<Vec<_>>());

    if env::var_os("CARGO_FEATURE_GRAPHQL_SCHEMA").is_some() {
        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "-vv",
                "--path",
                src_dir.as_ref(),
                "--bin",
                "turingarena-graphql-schema",
                "--root",
                out_path.to_str().unwrap(),
                "--force",
                "--debug",
                "--offline",
                "--no-default-features",
                "--features",
                "contest",
            ])
            .env_clear()
            .envs(
                std::env::vars_os()
                    .filter(|(k, _)| !k.to_string_lossy().starts_with("CARGO_FEATURE_")),
            )
            .env(
                "CARGO_TARGET_DIR",
                out_path.join("graphql-schema-target").to_str().unwrap(),
            )
            .check();

        let schema_file = File::create(&schema_path).unwrap();

        Command::new(out_path.join("bin").join("turingarena-graphql-schema"))
            .stdout(schema_file)
            .check();
    }

    if env::var_os("CARGO_FEATURE_CLI_ADMIN").is_some() {
        let operations_path = src_path
            .join("src")
            .join("contest")
            .join("operations.graphql");
        println!("cargo:rerun-if-changed={}", operations_path.to_str().unwrap());

        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "-vv",
                "graphql_client_cli",
                "--root",
                out_path.to_str().unwrap(),
                "--force",
                // FIXME: should be offline
                // "--offline",
            ])
            .env(
                "CARGO_TARGET_DIR",
                out_path.join("graphql-client-cli-target").to_str().unwrap(),
            )
            .check();

        Command::new(out_path.join("bin").join("graphql-client"))
            .args(&[
                "generate",
                "--output-directory",
                out_path.to_str().unwrap(),
                "--schema-path",
                schema_path.to_str().unwrap(),
                operations_path.to_str().unwrap(),
            ])
            .check();
    }

    if env::var_os("CARGO_FEATURE_WEB").is_some() {
        {
            let mut options = fs_extra::dir::CopyOptions::new();
            options.overwrite = true;
            fs_extra::dir::copy(src_path.join("web"), out_path, &options).unwrap();
        }

        let out_web_path = out_path.join("web");

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["ci", "--ignore-scripts"])
            .check();

        std::fs::create_dir_all(&out_web_path.join("__generated__")).unwrap();

        std::fs::copy(
            &schema_path,
            &out_web_path
                .join("__generated__")
                .join("graphql-schema.json"),
        )
        .unwrap();

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["run", "prepare"])
            .check();

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["run", "build"])
            .check();
    }
}
<|endoftext|>


<commit_before>extern crate ansi_term;
extern crate version_check;

use ansi_term::Color::{Blue, Red, White};
use version_check::is_nightly;

// Specifies the minimum version needed to compile Ion.
// NOTE: 1.19 is required due to the usage of `break` with values for
// `loop` (RFC 1624, rust-lang/rust GitHub issue #37339).
// const MIN_VERSION: &'static str = "1.19.0";

use std::env;
use std::fs::File;
use std::io::{self, Read, Write};
use std::path::Path;
use std::process::Command;

fn main() {
    match is_nightly() {
        Some(true) => (), // Success!
        Some(false) => {
            eprintln!(
                "{} {}",
                Red.bold().paint("Error:"),
                White.paint("Ion requires nighlty to build.")
            );
            // print_version_err(&*version_string);
            eprintln!(
                "{}{}{}",
                Blue.paint("Use `"),
                White.paint("rustup update"),
                Blue.paint("` to update to the latest stable compiler.")
            );
            panic!("Aborting compilation due to incompatible compiler.")
        }
        _ => {
            eprintln!("cargo:warning={}", "Ion was unable to check rustc compatibility.");
            eprintln!("cargo:warning={}", "Build may fail due to incompatible rustc version.");
        }
    }
    match write_version_file() {
        Ok(_) => {}
        Err(e) => panic!("Failed to create a version file: {:?}", e),
    }
}

fn write_version_file() -> io::Result<()> {
    let version = env::var("CARGO_PKG_VERSION").unwrap();
    let target = env::var("TARGET").unwrap();
    let version_fname = Path::new(&env::var("OUT_DIR").unwrap()).join("version_string");
    let mut version_file = File::create(&version_fname)?;
    write!(
        &mut version_file,
        "r#\"ion {} ({})\nrev {}\"#",
        version,
        target,
        get_git_rev()?.trim()
    )?;
    Ok(())
}

fn get_git_rev() -> io::Result<String> {
    let rev = match Command::new("git").arg("rev-parse").arg("master").output() {
        Ok(out) => match String::from_utf8(out.stdout) {
            Ok(s) => s,
            Err(_) => git_rev_from_file()?,
        },
        Err(_) => git_rev_from_file()?,
    };
    Ok(rev)
}

fn git_rev_from_file() -> io::Result<String> {
    let git_file = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
        .join(".git")
        .join("refs")
        .join("heads")
        .join("master");
    let mut file = File::open(git_file)?;
    let mut rev = String::new();
    file.read_to_string(&mut rev)?;
    Ok(rev)
}
<commit_msg>Fixes "nighlty" typo.<commit_after>extern crate ansi_term;
extern crate version_check;

use ansi_term::Color::{Blue, Red, White};
use version_check::is_nightly;

// Specifies the minimum version needed to compile Ion.
// NOTE: 1.19 is required due to the usage of `break` with values for
// `loop` (RFC 1624, rust-lang/rust GitHub issue #37339).
// const MIN_VERSION: &'static str = "1.19.0";

use std::env;
use std::fs::File;
use std::io::{self, Read, Write};
use std::path::Path;
use std::process::Command;

fn main() {
    match is_nightly() {
        Some(true) => (), // Success!
        Some(false) => {
            eprintln!(
                "{} {}",
                Red.bold().paint("Error:"),
                White.paint("Ion requires nightly to build.")
            );
            // print_version_err(&*version_string);
            eprintln!(
                "{}{}{}",
                Blue.paint("Use `"),
                White.paint("rustup update"),
                Blue.paint("` to update to the latest stable compiler.")
            );
            panic!("Aborting compilation due to incompatible compiler.")
        }
        _ => {
            eprintln!("cargo:warning={}", "Ion was unable to check rustc compatibility.");
            eprintln!("cargo:warning={}", "Build may fail due to incompatible rustc version.");
        }
    }
    match write_version_file() {
        Ok(_) => {}
        Err(e) => panic!("Failed to create a version file: {:?}", e),
    }
}

fn write_version_file() -> io::Result<()> {
    let version = env::var("CARGO_PKG_VERSION").unwrap();
    let target = env::var("TARGET").unwrap();
    let version_fname = Path::new(&env::var("OUT_DIR").unwrap()).join("version_string");
    let mut version_file = File::create(&version_fname)?;
    write!(
        &mut version_file,
        "r#\"ion {} ({})\nrev {}\"#",
        version,
        target,
        get_git_rev()?.trim()
    )?;
    Ok(())
}

fn get_git_rev() -> io::Result<String> {
    let rev = match Command::new("git").arg("rev-parse").arg("master").output() {
        Ok(out) => match String::from_utf8(out.stdout) {
            Ok(s) => s,
            Err(_) => git_rev_from_file()?,
        },
        Err(_) => git_rev_from_file()?,
    };
    Ok(rev)
}

fn git_rev_from_file() -> io::Result<String> {
    let git_file = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
        .join(".git")
        .join("refs")
        .join("heads")
        .join("master");
    let mut file = File::open(git_file)?;
    let mut rev = String::new();
    file.read_to_string(&mut rev)?;
    Ok(rev)
}
<|endoftext|>