<commit_before>use jeebie::core::cpu::CPU;
use jeebie::memory::MMU;
use jeebie::core::registers::*;
use jeebie::core::registers::Register8::*;

#[test]
fn compute_add_8_bit() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);
    // simple add, 2 + 2
    cpu.set8(A, 2u8);
    cpu.compute_add(A, A);
    assert_eq!(cpu.get8(A), 4u8);
    // no flags
    assert!(!cpu.reg.is_set(Flags::Zero));
    assert!(!cpu.reg.is_set(Flags::Carry));
    assert!(!cpu.reg.is_set(Flags::HalfCarry));
    assert!(!cpu.reg.is_set(Flags::Sub));

    // overflow, 255 + 1
    cpu.set8(A, 255u8);
    cpu.set8(B, 1u8);
    cpu.compute_add(A, B);
    assert_eq!(cpu.get8(A), 0u8);
    // all except sub
    assert!(cpu.reg.is_set(Flags::Zero));
    assert!(cpu.reg.is_set(Flags::Carry));
    assert!(cpu.reg.is_set(Flags::HalfCarry));
    assert!(!cpu.reg.is_set(Flags::Sub));

    // halfcarry
    cpu.set8(A, 127u8);
    cpu.set8(B, 1u8);
    cpu.compute_add(A, B);
    assert_eq!(cpu.get8(A), 128u8);
    // HC only
    assert!(!cpu.reg.is_set(Flags::Zero));
    assert!(!cpu.reg.is_set(Flags::Carry));
    assert!(cpu.reg.is_set(Flags::HalfCarry));
    assert!(!cpu.reg.is_set(Flags::Sub));
}

#[test]
fn compute_sub_8_bit() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);
    // simple sub
    cpu.set8(A, 8u8);
    cpu.set8(B, 2u8);
    cpu.compute_sub(B);
    assert_eq!(cpu.get8(A), 6u8);
    // sub only
    assert!(!cpu.reg.is_set(Flags::Zero));
    assert!(!cpu.reg.is_set(Flags::Carry));
    assert!(!cpu.reg.is_set(Flags::HalfCarry));
    assert!(cpu.reg.is_set(Flags::Sub));

    // underflow
    cpu.set8(A, 0u8);
    cpu.set8(B, 1u8);
    cpu.compute_sub(B);
    assert_eq!(cpu.get8(A), 255u8);
    // all flags except zero
    assert!(!cpu.reg.is_set(Flags::Zero));
    assert!(cpu.reg.is_set(Flags::Carry));
    assert!(cpu.reg.is_set(Flags::HalfCarry));
    assert!(cpu.reg.is_set(Flags::Sub));

    // halfcarry
    cpu.set8(A, 128u8);
    cpu.set8(B, 2u8);
    cpu.compute_sub(B);
    assert_eq!(cpu.get8(A), 126u8);
    // HC and sub
    assert!(!cpu.reg.is_set(Flags::Zero));
    assert!(!cpu.reg.is_set(Flags::Carry));
    assert!(cpu.reg.is_set(Flags::HalfCarry));
    assert!(cpu.reg.is_set(Flags::Sub));
}

#[test]
fn compute_cp_test() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);

    // simple sub
    cpu.set8(A, 10);
    cpu.set8(B, 2);
    cpu.compute_cp(B);

    assert!(cpu.reg.is_set(Flags::Sub));
    assert!(!cpu.reg.is_set(Flags::Zero));
    assert!(!cpu.reg.is_set(Flags::Carry));
    assert!(!cpu.reg.is_set(Flags::HalfCarry));

    // underflow
    cpu.set8(A, 100);
    cpu.set8(B, 100);
    cpu.compute_cp(B);

    assert!(cpu.reg.is_set(Flags::Zero));
    assert!(!cpu.reg.is_set(Flags::Carry));
    assert!(!cpu.reg.is_set(Flags::HalfCarry));
    assert!(cpu.reg.is_set(Flags::Sub));
}
<commit_msg>Added new tests for cpu<commit_after>use jeebie::core::cpu::CPU;
use jeebie::memory::MMU;
use jeebie::core::registers::Register8::*;
use jeebie::core::registers::Register16::*;
use jeebie::core::registers::Flags::*;

#[test]
fn add_8_bit() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);
    // simple add, 2 + 2
    cpu.set8(A, 2u8);
    cpu.compute_add(A, A);
    assert_eq!(cpu.get8(A), 4u8);
    // no flags
    assert!(!cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(Carry));
    assert!(!cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Sub));

    // overflow, 255 + 1
    cpu.set8(A, 255u8);
    cpu.set8(B, 1u8);
    cpu.compute_add(A, B);
    assert_eq!(cpu.get8(A), 0u8);
    // all except sub
    assert!(cpu.reg.is_set(Zero));
    assert!(cpu.reg.is_set(Carry));
    assert!(cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Sub));

    // halfcarry
    cpu.set8(A, 127u8);
    cpu.set8(B, 1u8);
    cpu.compute_add(A, B);
    assert_eq!(cpu.get8(A), 128u8);
    // HC only
    assert!(!cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(Carry));
    assert!(cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Sub));
}

#[test]
fn sub_8_bit() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);
    // simple sub
    cpu.set8(A, 8u8);
    cpu.set8(B, 2u8);
    cpu.compute_sub(B);
    assert_eq!(cpu.get8(A), 6u8);
    // sub only
    assert!(!cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(Carry));
    assert!(!cpu.reg.is_set(HalfCarry));
    assert!(cpu.reg.is_set(Sub));

    // underflow
    cpu.set8(A, 0u8);
    cpu.set8(B, 1u8);
    cpu.compute_sub(B);
    assert_eq!(cpu.get8(A), 255u8);
    // all flags except zero
    assert!(!cpu.reg.is_set(Zero));
    assert!(cpu.reg.is_set(Carry));
    assert!(cpu.reg.is_set(HalfCarry));
    assert!(cpu.reg.is_set(Sub));

    // halfcarry
    cpu.set8(A, 128u8);
    cpu.set8(B, 2u8);
    cpu.compute_sub(B);
    assert_eq!(cpu.get8(A), 126u8);
    // HC and sub
    assert!(!cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(Carry));
    assert!(cpu.reg.is_set(HalfCarry));
    assert!(cpu.reg.is_set(Sub));
}

#[test]
fn cp_test() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);

    // simple sub
    cpu.set8(A, 10);
    cpu.set8(B, 2);
    cpu.compute_cp(B);

    assert!(cpu.reg.is_set(Sub));
    assert!(!cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(Carry));
    assert!(!cpu.reg.is_set(HalfCarry));

    // underflow
    cpu.set8(A, 100);
    cpu.set8(B, 100);
    cpu.compute_cp(B);

    assert!(cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(Carry));
    assert!(!cpu.reg.is_set(HalfCarry));
    assert!(cpu.reg.is_set(Sub));
}

#[test]
fn inc_test() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);

    // NOTE: Carry flag is unmodified
    // simple inc
    cpu.set8(A, 0x9);
    cpu.compute_inc(A);

    assert_eq!(0xA, cpu.get8(A));
    assert!(!cpu.reg.is_set(Sub));
    assert!(!cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(HalfCarry));

    // zero
    cpu.set8(A, 0xFF);
    cpu.compute_inc(A);

    assert_eq!(0, cpu.get8(A));
    assert!(cpu.reg.is_set(Zero));
    assert!(cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Sub));

    // halfcarry
    cpu.set8(A, 0x0F);
    cpu.compute_inc(A);

    assert_eq!(0x10, cpu.get8(A));
    assert!(!cpu.reg.is_set(Zero));
    assert!(cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Sub));
}

#[test]
fn bit_check_test() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);

    cpu.set8(B, 0b1000_0001u8);
    cpu.bit_check(0, B);
    // Sub is always 0, HC always 1
    assert!(!cpu.reg.is_set(Zero));
    assert!(cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Sub));

    cpu.bit_check(1, B);
    // Sub is always 0, HC always 1
    assert!(cpu.reg.is_set(Zero));
    assert!(cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Sub));
}

#[test]
fn swap_test() {
    let mut mmu = MMU::new();
    let mut cpu = CPU::new(&mut mmu);

    cpu.set8(B, 0xAB);
    cpu.compute_swap(B);

    assert_eq!(0xBA, cpu.get8(B));
    // all reset except zero
    assert!(!cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(Sub));
    assert!(!cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Carry));

    // internal RAM, will be initialized to 0
    cpu.set16(HL, 0xC000);
    cpu.compute_swap(RegisterAddress(HL));

    assert_eq!(0, cpu.get8(RegisterAddress(HL)));
    // Zero should be set
    assert!(cpu.reg.is_set(Zero));
    assert!(!cpu.reg.is_set(Sub));
    assert!(!cpu.reg.is_set(HalfCarry));
    assert!(!cpu.reg.is_set(Carry));
}<|endoftext|>


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

use crate::deserialize::Deserialize;
use crate::exceptions::{ExceptionInfo, ResultInfo, ResultType};
use crate::protocol::{Field, ProtocolReader, ProtocolWriter};
use crate::serialize::Serialize;
use crate::thrift_protocol::ProtocolID;
use crate::ttype::TType;
use crate::Result;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(i32)]
pub enum ApplicationExceptionErrorCode {
    Unknown = 0,
    UnknownMethod = 1,
    InvalidMessageType = 2,
    WrongMethodName = 3,
    BadSequenceID = 4,
    MissingResult = 5,
    InternalError = 6,
    ProtocolError = 7,
    InvalidTransform = 8,
    InvalidProtocol = 9,
    UnsupportedClientType = 10,
    Loadshedding = 11,
    Timeout = 12,
    InjectedFailure = 13,
}

impl Default for ApplicationExceptionErrorCode {
    fn default() -> Self {
        ApplicationExceptionErrorCode::Unknown
    }
}

const TAPPLICATION_EXCEPTION_ERROR_CODE: &str = "ApplicationExceptionErrorCode";

/// ApplicationException is *not* actually an error type in the Rust sense, but
/// a Thrift-specific serializable
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
pub struct ApplicationException {
    pub message: String,
    pub type_: ApplicationExceptionErrorCode,
}

impl ApplicationException {
    #[cold]
    pub fn new(type_: ApplicationExceptionErrorCode, message: String) -> Self {
        ApplicationException { message, type_ }
    }

    // Used for methods which should exist but don't
    #[cold]
    pub fn unimplemented_method(handler: &str, method: &str) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::UnknownMethod,
            message: format!("Method {} not implemented for {}", method, handler),
        }
    }

    /// Indicator that this service doesn't have the method, but another might
    #[inline]
    pub fn unknown_method() -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::UnknownMethod,
            message: String::new(), // no allocation
        }
    }

    #[cold]
    pub fn missing_arg(method: &str, arg: &str) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::ProtocolError,
            message: format!("{} missing arg {}", method, arg),
        }
    }

    #[cold]
    pub fn missing_field(method: &str, field: &str) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::ProtocolError,
            message: format!("Struct {} missing field {}", method, field),
        }
    }

    #[cold]
    pub fn invalid_protocol(badproto: ProtocolID) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::InvalidProtocol,
            message: format!("Invalid protocol {:?}", badproto),
        }
    }
}

impl ExceptionInfo for ApplicationException {
    #[rustfmt::skip]
    fn exn_name(&self) -> &'static str {
        match self.type_ {
            ApplicationExceptionErrorCode::Unknown => "ApplicationExceptionErrorCode::Unknown",
            ApplicationExceptionErrorCode::UnknownMethod => "ApplicationExceptionErrorCode::UnknownMethod",
            ApplicationExceptionErrorCode::InvalidMessageType => "ApplicationExceptionErrorCode::InvalidMessageType",
            ApplicationExceptionErrorCode::WrongMethodName => "ApplicationExceptionErrorCode::WrongMethodName",
            ApplicationExceptionErrorCode::BadSequenceID => "ApplicationExceptionErrorCode::BadSequenceID",
            ApplicationExceptionErrorCode::MissingResult => "ApplicationExceptionErrorCode::MissingResult",
            ApplicationExceptionErrorCode::InternalError => "ApplicationExceptionErrorCode::InternalError",
            ApplicationExceptionErrorCode::ProtocolError => "ApplicationExceptionErrorCode::ProtocolError",
            ApplicationExceptionErrorCode::InvalidTransform => "ApplicationExceptionErrorCode::InvalidTransform",
            ApplicationExceptionErrorCode::InvalidProtocol => "ApplicationExceptionErrorCode::InvalidProtocol",
            ApplicationExceptionErrorCode::UnsupportedClientType => "ApplicationExceptionErrorCode::UnsupportedClientType",
            ApplicationExceptionErrorCode::Loadshedding => "ApplicationExceptionErrorCode::Loadshedding",
            ApplicationExceptionErrorCode::Timeout => "ApplicationExceptionErrorCode::Timeout",
            ApplicationExceptionErrorCode::InjectedFailure => "ApplicationExceptionErrorCode::InjectedFailure",
        }
    }

    fn exn_value(&self) -> String {
        self.message.clone()
    }

    #[inline]
    fn exn_is_declared(&self) -> bool {
        false
    }
}

impl ResultInfo for ApplicationException {
    fn result_type(&self) -> ResultType {
        ResultType::Exception
    }
}

impl<P> Deserialize<P> for ApplicationException
where
    P: ProtocolReader,
{
    /// Decodes a ApplicationException message from a Protocol stream
    fn read(iprot: &mut P) -> Result<Self> {
        iprot.read_struct_begin(|_| ())?;

        let mut message = String::from("");
        let mut type_ = ApplicationExceptionErrorCode::Unknown;

        loop {
            // Start reading the next field
            static FIELDS: &[Field] = &[
                Field::new("message", TType::String, 1),
                Field::new("type", TType::I32, 2),
            ];
            let (_, ttype, id) = iprot.read_field_begin(|_| (), FIELDS)?;

            match (ttype, id) {
                (TType::Stop, _) => break,
                (TType::String, 1) => message = iprot.read_string()?,
                (TType::I32, 2) => {
                    type_ = match iprot.read_i32()? {
                        1 => ApplicationExceptionErrorCode::UnknownMethod,
                        2 => ApplicationExceptionErrorCode::InvalidMessageType,
                        3 => ApplicationExceptionErrorCode::WrongMethodName,
                        4 => ApplicationExceptionErrorCode::BadSequenceID,
                        5 => ApplicationExceptionErrorCode::MissingResult,
                        6 => ApplicationExceptionErrorCode::InternalError,
                        7 => ApplicationExceptionErrorCode::ProtocolError,
                        8 => ApplicationExceptionErrorCode::InvalidTransform,
                        9 => ApplicationExceptionErrorCode::InvalidProtocol,
                        10 => ApplicationExceptionErrorCode::UnsupportedClientType,
                        11 => ApplicationExceptionErrorCode::Loadshedding,
                        12 => ApplicationExceptionErrorCode::Timeout,
                        13 => ApplicationExceptionErrorCode::InjectedFailure,

                        _ => ApplicationExceptionErrorCode::Unknown,
                    }
                }
                (ttype, _) => iprot.skip(ttype)?,
            };

            // Finished reading the end of the field
            iprot.read_field_end()?;
        }
        iprot.read_struct_end()?;
        Ok(ApplicationException::new(type_, message))
    }
}

impl<P> Serialize<P> for ApplicationException
where
    P: ProtocolWriter,
{
    /// Writes an application exception to the Protocol stream
    fn write(&self, oprot: &mut P) {
        oprot.write_struct_begin(TAPPLICATION_EXCEPTION_ERROR_CODE);

        if !self.message.is_empty() {
            oprot.write_field_begin("message", TType::String, 1);
            oprot.write_string(&self.message);
            oprot.write_field_end();
        }
        oprot.write_field_begin("type", TType::I32, 2);
        oprot.write_i32(self.type_ as i32);
        oprot.write_field_end();
        oprot.write_field_stop();
        oprot.write_struct_end();
    }
}
<commit_msg>thrift/rust: add `handler_panic` constructor<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use crate::deserialize::Deserialize;
use crate::exceptions::{ExceptionInfo, ResultInfo, ResultType};
use crate::protocol::{Field, ProtocolReader, ProtocolWriter};
use crate::serialize::Serialize;
use crate::thrift_protocol::ProtocolID;
use crate::ttype::TType;
use crate::Result;
use std::any::Any;

// Reference is thrift/lib/cpp/TApplicationException.h
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(i32)]
pub enum ApplicationExceptionErrorCode {
    Unknown = 0,
    UnknownMethod = 1,
    InvalidMessageType = 2,
    WrongMethodName = 3,
    BadSequenceID = 4,
    MissingResult = 5,
    InternalError = 6,
    ProtocolError = 7,
    InvalidTransform = 8,
    InvalidProtocol = 9,
    UnsupportedClientType = 10,
    Loadshedding = 11,
    Timeout = 12,
    InjectedFailure = 13,
    ChecksumMismatch = 14,
    Interruption = 15,
}

impl Default for ApplicationExceptionErrorCode {
    fn default() -> Self {
        ApplicationExceptionErrorCode::Unknown
    }
}

const TAPPLICATION_EXCEPTION_ERROR_CODE: &str = "ApplicationExceptionErrorCode";

/// ApplicationException is *not* actually an error type in the Rust sense, but
/// a Thrift-specific serializable
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
pub struct ApplicationException {
    pub message: String,
    pub type_: ApplicationExceptionErrorCode,
}

impl ApplicationException {
    #[cold]
    pub fn new(type_: ApplicationExceptionErrorCode, message: String) -> Self {
        ApplicationException { message, type_ }
    }

    // Used for methods which should exist but don't
    #[cold]
    pub fn unimplemented_method(handler: &str, method: &str) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::UnknownMethod,
            message: format!("Method {} not implemented for {}", method, handler),
        }
    }

    /// Indicator that this service doesn't have the method, but another might
    #[inline]
    pub fn unknown_method() -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::UnknownMethod,
            message: String::new(), // no allocation
        }
    }

    #[cold]
    pub fn missing_arg(method: &str, arg: &str) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::ProtocolError,
            message: format!("{} missing arg {}", method, arg),
        }
    }

    #[cold]
    pub fn missing_field(method: &str, field: &str) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::ProtocolError,
            message: format!("Struct {} missing field {}", method, field),
        }
    }

    #[cold]
    pub fn invalid_protocol(badproto: ProtocolID) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::InvalidProtocol,
            message: format!("Invalid protocol {:?}", badproto),
        }
    }

    /// An undeclared "exception"/panic etc
    #[cold]
    pub fn handler_panic(method: &str, exn: Box<dyn Any + Send + 'static>) -> Self {
        ApplicationException {
            type_: ApplicationExceptionErrorCode::Unknown,
            message: format!(
                "Handler for `{}` panicked with: {}",
                method,
                panic_message::get_panic_message(&exn).unwrap_or("<panic>")
            ),
        }
    }
}

impl ExceptionInfo for ApplicationException {
    #[rustfmt::skip]
    fn exn_name(&self) -> &'static str {
        match self.type_ {
            ApplicationExceptionErrorCode::Unknown => "ApplicationExceptionErrorCode::Unknown",
            ApplicationExceptionErrorCode::UnknownMethod => "ApplicationExceptionErrorCode::UnknownMethod",
            ApplicationExceptionErrorCode::InvalidMessageType => "ApplicationExceptionErrorCode::InvalidMessageType",
            ApplicationExceptionErrorCode::WrongMethodName => "ApplicationExceptionErrorCode::WrongMethodName",
            ApplicationExceptionErrorCode::BadSequenceID => "ApplicationExceptionErrorCode::BadSequenceID",
            ApplicationExceptionErrorCode::MissingResult => "ApplicationExceptionErrorCode::MissingResult",
            ApplicationExceptionErrorCode::InternalError => "ApplicationExceptionErrorCode::InternalError",
            ApplicationExceptionErrorCode::ProtocolError => "ApplicationExceptionErrorCode::ProtocolError",
            ApplicationExceptionErrorCode::InvalidTransform => "ApplicationExceptionErrorCode::InvalidTransform",
            ApplicationExceptionErrorCode::InvalidProtocol => "ApplicationExceptionErrorCode::InvalidProtocol",
            ApplicationExceptionErrorCode::UnsupportedClientType => "ApplicationExceptionErrorCode::UnsupportedClientType",
            ApplicationExceptionErrorCode::Loadshedding => "ApplicationExceptionErrorCode::Loadshedding",
            ApplicationExceptionErrorCode::Timeout => "ApplicationExceptionErrorCode::Timeout",
            ApplicationExceptionErrorCode::InjectedFailure => "ApplicationExceptionErrorCode::InjectedFailure",
            ApplicationExceptionErrorCode::ChecksumMismatch => "ApplicationExceptionErrorCode::ChecksumMismatch",
            ApplicationExceptionErrorCode::Interruption => "ApplicationExceptionErrorCode::Interruption",
        }
    }

    fn exn_value(&self) -> String {
        self.message.clone()
    }

    #[inline]
    fn exn_is_declared(&self) -> bool {
        false
    }
}

impl ResultInfo for ApplicationException {
    fn result_type(&self) -> ResultType {
        ResultType::Exception
    }
}

impl<P> Deserialize<P> for ApplicationException
where
    P: ProtocolReader,
{
    /// Decodes a ApplicationException message from a Protocol stream
    fn read(iprot: &mut P) -> Result<Self> {
        iprot.read_struct_begin(|_| ())?;

        let mut message = String::from("");
        let mut type_ = ApplicationExceptionErrorCode::Unknown;

        loop {
            // Start reading the next field
            static FIELDS: &[Field] = &[
                Field::new("message", TType::String, 1),
                Field::new("type", TType::I32, 2),
            ];
            let (_, ttype, id) = iprot.read_field_begin(|_| (), FIELDS)?;

            match (ttype, id) {
                (TType::Stop, _) => break,
                (TType::String, 1) => message = iprot.read_string()?,
                (TType::I32, 2) => {
                    type_ = match iprot.read_i32()? {
                        1 => ApplicationExceptionErrorCode::UnknownMethod,
                        2 => ApplicationExceptionErrorCode::InvalidMessageType,
                        3 => ApplicationExceptionErrorCode::WrongMethodName,
                        4 => ApplicationExceptionErrorCode::BadSequenceID,
                        5 => ApplicationExceptionErrorCode::MissingResult,
                        6 => ApplicationExceptionErrorCode::InternalError,
                        7 => ApplicationExceptionErrorCode::ProtocolError,
                        8 => ApplicationExceptionErrorCode::InvalidTransform,
                        9 => ApplicationExceptionErrorCode::InvalidProtocol,
                        10 => ApplicationExceptionErrorCode::UnsupportedClientType,
                        11 => ApplicationExceptionErrorCode::Loadshedding,
                        12 => ApplicationExceptionErrorCode::Timeout,
                        13 => ApplicationExceptionErrorCode::InjectedFailure,
                        14 => ApplicationExceptionErrorCode::ChecksumMismatch,
                        15 => ApplicationExceptionErrorCode::Interruption,

                        _ => ApplicationExceptionErrorCode::Unknown,
                    }
                }
                (ttype, _) => iprot.skip(ttype)?,
            };

            // Finished reading the end of the field
            iprot.read_field_end()?;
        }
        iprot.read_struct_end()?;
        Ok(ApplicationException::new(type_, message))
    }
}

impl<P> Serialize<P> for ApplicationException
where
    P: ProtocolWriter,
{
    /// Writes an application exception to the Protocol stream
    fn write(&self, oprot: &mut P) {
        oprot.write_struct_begin(TAPPLICATION_EXCEPTION_ERROR_CODE);

        if !self.message.is_empty() {
            oprot.write_field_begin("message", TType::String, 1);
            oprot.write_string(&self.message);
            oprot.write_field_end();
        }
        oprot.write_field_begin("type", TType::I32, 2);
        oprot.write_i32(self.type_ as i32);
        oprot.write_field_end();
        oprot.write_field_stop();
        oprot.write_struct_end();
    }
}
<|endoftext|>


<commit_before>//! Available RPC methods types and ids.

use crate::types::EnrBitfield;
use serde::Serialize;
use ssz_derive::{Decode, Encode};
use ssz_types::{
    typenum::{U1024, U256},
    VariableList,
};
use std::ops::Deref;
use types::{Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot};

/// Maximum number of blocks in a single request.
pub type MaxRequestBlocks = U1024;
pub const MAX_REQUEST_BLOCKS: u64 = 1024;

/// Maximum length of error message.
type MaxErrorLen = U256;

/// Wrapper over SSZ List to represent error message in rpc responses.
#[derive(Debug, Clone)]
pub struct ErrorType(VariableList<u8, MaxErrorLen>);

impl From<String> for ErrorType {
    fn from(s: String) -> Self {
        Self(VariableList::from(s.as_bytes().to_vec()))
    }
}

impl From<&str> for ErrorType {
    fn from(s: &str) -> Self {
        Self(VariableList::from(s.as_bytes().to_vec()))
    }
}

impl Deref for ErrorType {
    type Target = VariableList<u8, MaxErrorLen>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl ToString for ErrorType {
    fn to_string(&self) -> String {
        match std::str::from_utf8(self.0.deref()) {
            Ok(s) => s.to_string(),
            Err(_) => format!("{:?}", self.0.deref()), // Display raw bytes if not a UTF-8 string
        }
    }
}

/* Request/Response data structures for RPC methods */

/* Requests */

/// Identifier of a request.
///
// NOTE: The handler stores the `RequestId` to inform back of responses and errors, but it's execution
// is independent of the contents on this type.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RequestId {
    Router,
    Sync(usize),
    Behaviour,
}

/// The STATUS request/response handshake message.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct StatusMessage {
    /// The fork version of the chain we are broadcasting.
    pub fork_digest: [u8; 4],

    /// Latest finalized root.
    pub finalized_root: Hash256,

    /// Latest finalized epoch.
    pub finalized_epoch: Epoch,

    /// The latest block root.
    pub head_root: Hash256,

    /// The slot associated with the latest block root.
    pub head_slot: Slot,
}

/// The PING request/response message.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct Ping {
    /// The metadata sequence number.
    pub data: u64,
}

/// The METADATA response structure.
#[derive(Encode, Decode, Clone, Debug, PartialEq, Serialize)]
#[serde(bound = "T: EthSpec")]
pub struct MetaData<T: EthSpec> {
    /// A sequential counter indicating when data gets modified.
    pub seq_number: u64,
    /// The persistent subnet bitfield.
    pub attnets: EnrBitfield<T>,
}

/// The reason given for a `Goodbye` message.
///
/// Note: any unknown `u64::into(n)` will resolve to `Goodbye::Unknown` for any unknown `n`,
/// however `GoodbyeReason::Unknown.into()` will go into `0_u64`. Therefore de-serializing then
/// re-serializing may not return the same bytes.
#[derive(Debug, Clone, PartialEq)]
pub enum GoodbyeReason {
    /// This node has shutdown.
    ClientShutdown = 1,

    /// Incompatible networks.
    IrrelevantNetwork = 2,

    /// Error/fault in the RPC.
    Fault = 3,

    /// Teku uses this code for not being able to verify a network.
    UnableToVerifyNetwork = 128,

    /// The node has too many connected peers.
    TooManyPeers = 129,

    /// Scored poorly.
    BadScore = 250,

    /// The peer is banned
    Banned = 251,

    /// Unknown reason.
    Unknown = 0,
}

impl From<u64> for GoodbyeReason {
    fn from(id: u64) -> GoodbyeReason {
        match id {
            1 => GoodbyeReason::ClientShutdown,
            2 => GoodbyeReason::IrrelevantNetwork,
            3 => GoodbyeReason::Fault,
            128 => GoodbyeReason::UnableToVerifyNetwork,
            129 => GoodbyeReason::TooManyPeers,
            250 => GoodbyeReason::BadScore,
            251 => GoodbyeReason::Banned,
            _ => GoodbyeReason::Unknown,
        }
    }
}

impl Into<u64> for GoodbyeReason {
    fn into(self) -> u64 {
        self as u64
    }
}

impl ssz::Encode for GoodbyeReason {
    fn is_ssz_fixed_len() -> bool {
        <u64 as ssz::Encode>::is_ssz_fixed_len()
    }

    fn ssz_fixed_len() -> usize {
        <u64 as ssz::Encode>::ssz_fixed_len()
    }

    fn ssz_bytes_len(&self) -> usize {
        0_u64.ssz_bytes_len()
    }

    fn ssz_append(&self, buf: &mut Vec<u8>) {
        let conv: u64 = self.clone().into();
        conv.ssz_append(buf)
    }
}

impl ssz::Decode for GoodbyeReason {
    fn is_ssz_fixed_len() -> bool {
        <u64 as ssz::Decode>::is_ssz_fixed_len()
    }

    fn ssz_fixed_len() -> usize {
        <u64 as ssz::Decode>::ssz_fixed_len()
    }

    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
        u64::from_ssz_bytes(bytes).map(|n| n.into())
    }
}

/// Request a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BlocksByRangeRequest {
    /// The starting slot to request blocks.
    pub start_slot: u64,

    /// The number of blocks from the start slot.
    pub count: u64,

    /// The step increment to receive blocks.
    ///
    /// A value of 1 returns every block.
    /// A value of 2 returns every second block.
    /// A value of 3 returns every third block and so on.
    pub step: u64,
}

/// Request a number of beacon block bodies from a peer.
#[derive(Clone, Debug, PartialEq)]
pub struct BlocksByRootRequest {
    /// The list of beacon block bodies being requested.
    pub block_roots: VariableList<Hash256, MaxRequestBlocks>,
}

/* RPC Handling and Grouping */
// Collection of enums and structs used by the Codecs to encode/decode RPC messages

#[derive(Debug, Clone, PartialEq)]
pub enum RPCResponse<T: EthSpec> {
    /// A HELLO message.
    Status(StatusMessage),

    /// A response to a get BLOCKS_BY_RANGE request. A None response signifies the end of the
    /// batch.
    BlocksByRange(Box<SignedBeaconBlock<T>>),

    /// A response to a get BLOCKS_BY_ROOT request.
    BlocksByRoot(Box<SignedBeaconBlock<T>>),

    /// A PONG response to a PING request.
    Pong(Ping),

    /// A response to a META_DATA request.
    MetaData(MetaData<T>),
}

/// Indicates which response is being terminated by a stream termination response.
#[derive(Debug, Clone)]
pub enum ResponseTermination {
    /// Blocks by range stream termination.
    BlocksByRange,

    /// Blocks by root stream termination.
    BlocksByRoot,
}

/// The structured response containing a result/code indicating success or failure
/// and the contents of the response
#[derive(Debug, Clone)]
pub enum RPCCodedResponse<T: EthSpec> {
    /// The response is a successful.
    Success(RPCResponse<T>),

    Error(RPCResponseErrorCode, ErrorType),

    /// Received a stream termination indicating which response is being terminated.
    StreamTermination(ResponseTermination),
}

/// The code assigned to an erroneous `RPCResponse`.
#[derive(Debug, Clone, Copy)]
pub enum RPCResponseErrorCode {
    RateLimited,
    InvalidRequest,
    ServerError,
    Unknown,
}

impl<T: EthSpec> RPCCodedResponse<T> {
    /// Used to encode the response in the codec.
    pub fn as_u8(&self) -> Option<u8> {
        match self {
            RPCCodedResponse::Success(_) => Some(0),
            RPCCodedResponse::Error(code, _) => Some(code.as_u8()),
            RPCCodedResponse::StreamTermination(_) => None,
        }
    }

    /// Tells the codec whether to decode as an RPCResponse or an error.
    pub fn is_response(response_code: u8) -> bool {
        match response_code {
            0 => true,
            _ => false,
        }
    }

    /// Builds an RPCCodedResponse from a response code and an ErrorMessage
    pub fn from_error(response_code: u8, err: String) -> Self {
        let code = match response_code {
            1 => RPCResponseErrorCode::InvalidRequest,
            2 => RPCResponseErrorCode::ServerError,
            _ => RPCResponseErrorCode::Unknown,
        };
        RPCCodedResponse::Error(code, err.into())
    }

    /// Specifies which response allows for multiple chunks for the stream handler.
    pub fn multiple_responses(&self) -> bool {
        match self {
            RPCCodedResponse::Success(resp) => match resp {
                RPCResponse::Status(_) => false,
                RPCResponse::BlocksByRange(_) => true,
                RPCResponse::BlocksByRoot(_) => true,
                RPCResponse::Pong(_) => false,
                RPCResponse::MetaData(_) => false,
            },
            RPCCodedResponse::Error(_, _) => true,
            // Stream terminations are part of responses that have chunks
            RPCCodedResponse::StreamTermination(_) => true,
        }
    }

    /// Returns true if this response always terminates the stream.
    pub fn close_after(&self) -> bool {
        match self {
            RPCCodedResponse::Success(_) => false,
            _ => true,
        }
    }
}

impl RPCResponseErrorCode {
    fn as_u8(&self) -> u8 {
        match self {
            RPCResponseErrorCode::InvalidRequest => 1,
            RPCResponseErrorCode::ServerError => 2,
            RPCResponseErrorCode::Unknown => 255,
            RPCResponseErrorCode::RateLimited => 128,
        }
    }
}

impl std::fmt::Display for RPCResponseErrorCode {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let repr = match self {
            RPCResponseErrorCode::InvalidRequest => "The request was invalid",
            RPCResponseErrorCode::ServerError => "Server error occurred",
            RPCResponseErrorCode::Unknown => "Unknown error occurred",
            RPCResponseErrorCode::RateLimited => "Rate limited",
        };
        f.write_str(repr)
    }
}

impl std::fmt::Display for StatusMessage {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Status Message: Fork Digest: {:?}, Finalized Root: {}, Finalized Epoch: {}, Head Root: {}, Head Slot: {}", self.fork_digest, self.finalized_root, self.finalized_epoch, self.head_root, self.head_slot)
    }
}

impl<T: EthSpec> std::fmt::Display for RPCResponse<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            RPCResponse::Status(status) => write!(f, "{}", status),
            RPCResponse::BlocksByRange(block) => {
                write!(f, "BlocksByRange: Block slot: {}", block.message.slot)
            }
            RPCResponse::BlocksByRoot(block) => {
                write!(f, "BlocksByRoot: BLock slot: {}", block.message.slot)
            }
            RPCResponse::Pong(ping) => write!(f, "Pong: {}", ping.data),
            RPCResponse::MetaData(metadata) => write!(f, "Metadata: {}", metadata.seq_number),
        }
    }
}

impl<T: EthSpec> std::fmt::Display for RPCCodedResponse<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            RPCCodedResponse::Success(res) => write!(f, "{}", res),
            RPCCodedResponse::Error(code, err) => write!(f, "{}: {:?}", code, err),
            RPCCodedResponse::StreamTermination(_) => write!(f, "Stream Termination"),
        }
    }
}

impl std::fmt::Display for GoodbyeReason {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            GoodbyeReason::ClientShutdown => write!(f, "Client Shutdown"),
            GoodbyeReason::IrrelevantNetwork => write!(f, "Irrelevant Network"),
            GoodbyeReason::Fault => write!(f, "Fault"),
            GoodbyeReason::UnableToVerifyNetwork => write!(f, "Unable to verify network"),
            GoodbyeReason::TooManyPeers => write!(f, "Too many peers"),
            GoodbyeReason::BadScore => write!(f, "Bad Score"),
            GoodbyeReason::Banned => write!(f, "Banned"),
            GoodbyeReason::Unknown => write!(f, "Unknown Reason"),
        }
    }
}

impl std::fmt::Display for BlocksByRangeRequest {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Start Slot: {}, Count: {}, Step: {}",
            self.start_slot, self.count, self.step
        )
    }
}

impl slog::Value for RequestId {
    fn serialize(
        &self,
        record: &slog::Record,
        key: slog::Key,
        serializer: &mut dyn slog::Serializer,
    ) -> slog::Result {
        match self {
            RequestId::Behaviour => slog::Value::serialize("Behaviour", record, key, serializer),
            RequestId::Router => slog::Value::serialize("Router", record, key, serializer),
            RequestId::Sync(ref id) => slog::Value::serialize(id, record, key, serializer),
        }
    }
}
<commit_msg>Fix rpc coded response display (#1470)<commit_after>//! Available RPC methods types and ids.

use crate::types::EnrBitfield;
use serde::Serialize;
use ssz_derive::{Decode, Encode};
use ssz_types::{
    typenum::{U1024, U256},
    VariableList,
};
use std::ops::Deref;
use types::{Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot};

/// Maximum number of blocks in a single request.
pub type MaxRequestBlocks = U1024;
pub const MAX_REQUEST_BLOCKS: u64 = 1024;

/// Maximum length of error message.
type MaxErrorLen = U256;

/// Wrapper over SSZ List to represent error message in rpc responses.
#[derive(Debug, Clone)]
pub struct ErrorType(VariableList<u8, MaxErrorLen>);

impl From<String> for ErrorType {
    fn from(s: String) -> Self {
        Self(VariableList::from(s.as_bytes().to_vec()))
    }
}

impl From<&str> for ErrorType {
    fn from(s: &str) -> Self {
        Self(VariableList::from(s.as_bytes().to_vec()))
    }
}

impl Deref for ErrorType {
    type Target = VariableList<u8, MaxErrorLen>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl ToString for ErrorType {
    fn to_string(&self) -> String {
        match std::str::from_utf8(self.0.deref()) {
            Ok(s) => s.to_string(),
            Err(_) => format!("{:?}", self.0.deref()), // Display raw bytes if not a UTF-8 string
        }
    }
}

/* Request/Response data structures for RPC methods */

/* Requests */

/// Identifier of a request.
///
// NOTE: The handler stores the `RequestId` to inform back of responses and errors, but it's execution
// is independent of the contents on this type.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RequestId {
    Router,
    Sync(usize),
    Behaviour,
}

/// The STATUS request/response handshake message.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct StatusMessage {
    /// The fork version of the chain we are broadcasting.
    pub fork_digest: [u8; 4],

    /// Latest finalized root.
    pub finalized_root: Hash256,

    /// Latest finalized epoch.
    pub finalized_epoch: Epoch,

    /// The latest block root.
    pub head_root: Hash256,

    /// The slot associated with the latest block root.
    pub head_slot: Slot,
}

/// The PING request/response message.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct Ping {
    /// The metadata sequence number.
    pub data: u64,
}

/// The METADATA response structure.
#[derive(Encode, Decode, Clone, Debug, PartialEq, Serialize)]
#[serde(bound = "T: EthSpec")]
pub struct MetaData<T: EthSpec> {
    /// A sequential counter indicating when data gets modified.
    pub seq_number: u64,
    /// The persistent subnet bitfield.
    pub attnets: EnrBitfield<T>,
}

/// The reason given for a `Goodbye` message.
///
/// Note: any unknown `u64::into(n)` will resolve to `Goodbye::Unknown` for any unknown `n`,
/// however `GoodbyeReason::Unknown.into()` will go into `0_u64`. Therefore de-serializing then
/// re-serializing may not return the same bytes.
#[derive(Debug, Clone, PartialEq)]
pub enum GoodbyeReason {
    /// This node has shutdown.
    ClientShutdown = 1,

    /// Incompatible networks.
    IrrelevantNetwork = 2,

    /// Error/fault in the RPC.
    Fault = 3,

    /// Teku uses this code for not being able to verify a network.
    UnableToVerifyNetwork = 128,

    /// The node has too many connected peers.
    TooManyPeers = 129,

    /// Scored poorly.
    BadScore = 250,

    /// The peer is banned
    Banned = 251,

    /// Unknown reason.
    Unknown = 0,
}

impl From<u64> for GoodbyeReason {
    fn from(id: u64) -> GoodbyeReason {
        match id {
            1 => GoodbyeReason::ClientShutdown,
            2 => GoodbyeReason::IrrelevantNetwork,
            3 => GoodbyeReason::Fault,
            128 => GoodbyeReason::UnableToVerifyNetwork,
            129 => GoodbyeReason::TooManyPeers,
            250 => GoodbyeReason::BadScore,
            251 => GoodbyeReason::Banned,
            _ => GoodbyeReason::Unknown,
        }
    }
}

impl Into<u64> for GoodbyeReason {
    fn into(self) -> u64 {
        self as u64
    }
}

impl ssz::Encode for GoodbyeReason {
    fn is_ssz_fixed_len() -> bool {
        <u64 as ssz::Encode>::is_ssz_fixed_len()
    }

    fn ssz_fixed_len() -> usize {
        <u64 as ssz::Encode>::ssz_fixed_len()
    }

    fn ssz_bytes_len(&self) -> usize {
        0_u64.ssz_bytes_len()
    }

    fn ssz_append(&self, buf: &mut Vec<u8>) {
        let conv: u64 = self.clone().into();
        conv.ssz_append(buf)
    }
}

impl ssz::Decode for GoodbyeReason {
    fn is_ssz_fixed_len() -> bool {
        <u64 as ssz::Decode>::is_ssz_fixed_len()
    }

    fn ssz_fixed_len() -> usize {
        <u64 as ssz::Decode>::ssz_fixed_len()
    }

    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
        u64::from_ssz_bytes(bytes).map(|n| n.into())
    }
}

/// Request a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BlocksByRangeRequest {
    /// The starting slot to request blocks.
    pub start_slot: u64,

    /// The number of blocks from the start slot.
    pub count: u64,

    /// The step increment to receive blocks.
    ///
    /// A value of 1 returns every block.
    /// A value of 2 returns every second block.
    /// A value of 3 returns every third block and so on.
    pub step: u64,
}

/// Request a number of beacon block bodies from a peer.
#[derive(Clone, Debug, PartialEq)]
pub struct BlocksByRootRequest {
    /// The list of beacon block bodies being requested.
    pub block_roots: VariableList<Hash256, MaxRequestBlocks>,
}

/* RPC Handling and Grouping */
// Collection of enums and structs used by the Codecs to encode/decode RPC messages

#[derive(Debug, Clone, PartialEq)]
pub enum RPCResponse<T: EthSpec> {
    /// A HELLO message.
    Status(StatusMessage),

    /// A response to a get BLOCKS_BY_RANGE request. A None response signifies the end of the
    /// batch.
    BlocksByRange(Box<SignedBeaconBlock<T>>),

    /// A response to a get BLOCKS_BY_ROOT request.
    BlocksByRoot(Box<SignedBeaconBlock<T>>),

    /// A PONG response to a PING request.
    Pong(Ping),

    /// A response to a META_DATA request.
    MetaData(MetaData<T>),
}

/// Indicates which response is being terminated by a stream termination response.
#[derive(Debug, Clone)]
pub enum ResponseTermination {
    /// Blocks by range stream termination.
    BlocksByRange,

    /// Blocks by root stream termination.
    BlocksByRoot,
}

/// The structured response containing a result/code indicating success or failure
/// and the contents of the response
#[derive(Debug, Clone)]
pub enum RPCCodedResponse<T: EthSpec> {
    /// The response is a successful.
    Success(RPCResponse<T>),

    Error(RPCResponseErrorCode, ErrorType),

    /// Received a stream termination indicating which response is being terminated.
    StreamTermination(ResponseTermination),
}

/// The code assigned to an erroneous `RPCResponse`.
#[derive(Debug, Clone, Copy)]
pub enum RPCResponseErrorCode {
    RateLimited,
    InvalidRequest,
    ServerError,
    Unknown,
}

impl<T: EthSpec> RPCCodedResponse<T> {
    /// Used to encode the response in the codec.
    pub fn as_u8(&self) -> Option<u8> {
        match self {
            RPCCodedResponse::Success(_) => Some(0),
            RPCCodedResponse::Error(code, _) => Some(code.as_u8()),
            RPCCodedResponse::StreamTermination(_) => None,
        }
    }

    /// Tells the codec whether to decode as an RPCResponse or an error.
    pub fn is_response(response_code: u8) -> bool {
        match response_code {
            0 => true,
            _ => false,
        }
    }

    /// Builds an RPCCodedResponse from a response code and an ErrorMessage
    pub fn from_error(response_code: u8, err: String) -> Self {
        let code = match response_code {
            1 => RPCResponseErrorCode::InvalidRequest,
            2 => RPCResponseErrorCode::ServerError,
            _ => RPCResponseErrorCode::Unknown,
        };
        RPCCodedResponse::Error(code, err.into())
    }

    /// Specifies which response allows for multiple chunks for the stream handler.
    pub fn multiple_responses(&self) -> bool {
        match self {
            RPCCodedResponse::Success(resp) => match resp {
                RPCResponse::Status(_) => false,
                RPCResponse::BlocksByRange(_) => true,
                RPCResponse::BlocksByRoot(_) => true,
                RPCResponse::Pong(_) => false,
                RPCResponse::MetaData(_) => false,
            },
            RPCCodedResponse::Error(_, _) => true,
            // Stream terminations are part of responses that have chunks
            RPCCodedResponse::StreamTermination(_) => true,
        }
    }

    /// Returns true if this response always terminates the stream.
    pub fn close_after(&self) -> bool {
        match self {
            RPCCodedResponse::Success(_) => false,
            _ => true,
        }
    }
}

impl RPCResponseErrorCode {
    fn as_u8(&self) -> u8 {
        match self {
            RPCResponseErrorCode::InvalidRequest => 1,
            RPCResponseErrorCode::ServerError => 2,
            RPCResponseErrorCode::Unknown => 255,
            RPCResponseErrorCode::RateLimited => 128,
        }
    }
}

impl std::fmt::Display for RPCResponseErrorCode {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let repr = match self {
            RPCResponseErrorCode::InvalidRequest => "The request was invalid",
            RPCResponseErrorCode::ServerError => "Server error occurred",
            RPCResponseErrorCode::Unknown => "Unknown error occurred",
            RPCResponseErrorCode::RateLimited => "Rate limited",
        };
        f.write_str(repr)
    }
}

impl std::fmt::Display for StatusMessage {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Status Message: Fork Digest: {:?}, Finalized Root: {}, Finalized Epoch: {}, Head Root: {}, Head Slot: {}", self.fork_digest, self.finalized_root, self.finalized_epoch, self.head_root, self.head_slot)
    }
}

impl<T: EthSpec> std::fmt::Display for RPCResponse<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            RPCResponse::Status(status) => write!(f, "{}", status),
            RPCResponse::BlocksByRange(block) => {
                write!(f, "BlocksByRange: Block slot: {}", block.message.slot)
            }
            RPCResponse::BlocksByRoot(block) => {
                write!(f, "BlocksByRoot: BLock slot: {}", block.message.slot)
            }
            RPCResponse::Pong(ping) => write!(f, "Pong: {}", ping.data),
            RPCResponse::MetaData(metadata) => write!(f, "Metadata: {}", metadata.seq_number),
        }
    }
}

impl<T: EthSpec> std::fmt::Display for RPCCodedResponse<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            RPCCodedResponse::Success(res) => write!(f, "{}", res),
            RPCCodedResponse::Error(code, err) => write!(f, "{}: {}", code, err.to_string()),
            RPCCodedResponse::StreamTermination(_) => write!(f, "Stream Termination"),
        }
    }
}

impl std::fmt::Display for GoodbyeReason {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            GoodbyeReason::ClientShutdown => write!(f, "Client Shutdown"),
            GoodbyeReason::IrrelevantNetwork => write!(f, "Irrelevant Network"),
            GoodbyeReason::Fault => write!(f, "Fault"),
            GoodbyeReason::UnableToVerifyNetwork => write!(f, "Unable to verify network"),
            GoodbyeReason::TooManyPeers => write!(f, "Too many peers"),
            GoodbyeReason::BadScore => write!(f, "Bad Score"),
            GoodbyeReason::Banned => write!(f, "Banned"),
            GoodbyeReason::Unknown => write!(f, "Unknown Reason"),
        }
    }
}

impl std::fmt::Display for BlocksByRangeRequest {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Start Slot: {}, Count: {}, Step: {}",
            self.start_slot, self.count, self.step
        )
    }
}

impl slog::Value for RequestId {
    fn serialize(
        &self,
        record: &slog::Record,
        key: slog::Key,
        serializer: &mut dyn slog::Serializer,
    ) -> slog::Result {
        match self {
            RequestId::Behaviour => slog::Value::serialize("Behaviour", record, key, serializer),
            RequestId::Router => slog::Value::serialize("Router", record, key, serializer),
            RequestId::Sync(ref id) => slog::Value::serialize(id, record, key, serializer),
        }
    }
}
<|endoftext|>


<commit_before>
pub struct ProcessResults<'a, I, E: 'a> {
    error: &'a mut Result<(), E>,
    iter: I,
}

impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E>
    where I: Iterator<Item = Result<T, E>>
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self.iter.next() {
            Some(Ok(x)) => Some(x),
            Some(Err(e)) => {
                *self.error = Err(e);
                None
            }
            None => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, hi) = self.iter.size_hint();
        (0, hi)
    }
}

/// “Lift” a function of the values of an iterator so that it can process
/// an iterator of `Result` values instead.
///
/// `iterable` is an iterator or iterable with `Result<T, E>` elements, where
/// `T` is the value type and `E` the error type.
///
/// `processor` is a closure that receives an adapted version of the iterable
/// as the only argument — the adapted iterator produces elements of type `T`,
/// as long as the original iterator produces `Ok` values.
///
/// If the original iterable produces an error at any point, the adapted
/// iterator ends and the `process_results` function will return the
/// error iself.
///
/// Otherwise, the return value from the closure is returned wrapped
/// inside `Ok`.
///
/// # Example
///
/// ```
/// use itertools::process_results;
///
/// type R = Result<i32, &'static str>;
///
/// let first_values: Vec<R> = vec![Ok(1), Ok(0), Ok(3)];
/// let second_values: Vec<R> = vec![Ok(2), Ok(1), Err("overflow")];
///
/// // “Lift” the iterator .max() method to work on the values in Results using process_results
///
/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0));
/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0));
///
/// assert_eq!(first_max, Ok(3));
/// assert!(second_max.is_err());
/// ```
pub fn process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E>
    where I: IntoIterator<Item = Result<T, E>>,
          F: FnOnce(ProcessResults<I::IntoIter, E>) -> R
{
    let iter = iterable.into_iter();
    let mut error = Ok(());

    let result = processor(ProcessResults { error: &mut error, iter: iter });

    error.map(|_| result)
}
<commit_msg>DOC: For ProcessResults struct<commit_after>
/// An iterator that produces only the `T` values as long as the
/// inner iterator produces `Ok(T)`.
///
/// Used by [`process_results`](../fn.process_results.html), see its docs
/// for more information.
pub struct ProcessResults<'a, I, E: 'a> {
    error: &'a mut Result<(), E>,
    iter: I,
}

impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E>
    where I: Iterator<Item = Result<T, E>>
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self.iter.next() {
            Some(Ok(x)) => Some(x),
            Some(Err(e)) => {
                *self.error = Err(e);
                None
            }
            None => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, hi) = self.iter.size_hint();
        (0, hi)
    }
}

/// “Lift” a function of the values of an iterator so that it can process
/// an iterator of `Result` values instead.
///
/// `iterable` is an iterator or iterable with `Result<T, E>` elements, where
/// `T` is the value type and `E` the error type.
///
/// `processor` is a closure that receives an adapted version of the iterable
/// as the only argument — the adapted iterator produces elements of type `T`,
/// as long as the original iterator produces `Ok` values.
///
/// If the original iterable produces an error at any point, the adapted
/// iterator ends and the `process_results` function will return the
/// error iself.
///
/// Otherwise, the return value from the closure is returned wrapped
/// inside `Ok`.
///
/// # Example
///
/// ```
/// use itertools::process_results;
///
/// type R = Result<i32, &'static str>;
///
/// let first_values: Vec<R> = vec![Ok(1), Ok(0), Ok(3)];
/// let second_values: Vec<R> = vec![Ok(2), Ok(1), Err("overflow")];
///
/// // “Lift” the iterator .max() method to work on the values in Results using process_results
///
/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0));
/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0));
///
/// assert_eq!(first_max, Ok(3));
/// assert!(second_max.is_err());
/// ```
pub fn process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E>
    where I: IntoIterator<Item = Result<T, E>>,
          F: FnOnce(ProcessResults<I::IntoIter, E>) -> R
{
    let iter = iterable.into_iter();
    let mut error = Ok(());

    let result = processor(ProcessResults { error: &mut error, iter: iter });

    error.map(|_| result)
}
<|endoftext|>


<commit_before>//! Functionality for declaring Objective-C classes.

use std::ffi::CString;
use std::mem;
use libc::size_t;

use {encode, Encode, EncodePtr, Message};
use runtime::{Class, Imp, Sel, self};

/// A type for declaring a new method.
pub struct MethodDecl {
    sel: Sel,
    imp: Imp,
    types: String,
}

impl MethodDecl {
    /// Constructs a `MethodDecl` with the given selector and function.
    ///
    /// Returns an error if the selector and the function take different
    /// numbers of arguments.
    pub fn new<F>(sel: Sel, func: F) -> Result<MethodDecl, ()>
            where F: IntoMethodDecl {
        func.into_method_decl(sel)
    }
}

/// Types that can be used as the implementation of an Objective-C method to
/// construct a `MethodDecl`.
pub trait IntoMethodDecl {
    /// Consumes self to declare a method for the given selector with self as
    /// the implementation.
    ///
    /// Returns an error if self and the selector do not accept the same number
    /// of arguments.
    fn into_method_decl(self, sel: Sel) -> Result<MethodDecl, ()>;
}

macro_rules! count_idents {
    () => (0);
    ($a:ident) => (1);
    ($a:ident, $($b:ident),+) => (1 + count_idents!($($b),*));
}

macro_rules! method_decl_impl {
    (-$s:ident, $sp:ty, $($t:ident),*) => (
        impl<$s, R $(, $t)*> IntoMethodDecl for extern fn($sp, Sel $(, $t)*) -> R
                where $s: Message + EncodePtr, R: Encode $(, $t: Encode)* {
            fn into_method_decl(self, sel: Sel) -> Result<MethodDecl, ()> {
                let num_args = count_idents!($($t),*);
                if sel.name().chars().filter(|&c| c == ':').count() == num_args {
                    let imp: Imp = unsafe { mem::transmute(self) };

                    let mut types = encode::<R>().to_string();
                    types.push_str(encode::<$sp>());
                    types.push_str(encode::<Sel>());
                    $(types.push_str(encode::<$t>());)*

                    Ok(MethodDecl { sel: sel, imp: imp, types: types })
                } else {
                    Err(())
                }
            }
        }
    );
    ($($t:ident),*) => (
        method_decl_impl!(-T, &T, $($t),*);
        method_decl_impl!(-T, &mut T, $($t),*);
    );
}

method_decl_impl!();
method_decl_impl!(A);
method_decl_impl!(A, B);
method_decl_impl!(A, B, C);
method_decl_impl!(A, B, C, D);
method_decl_impl!(A, B, C, D, E);
method_decl_impl!(A, B, C, D, E, F);
method_decl_impl!(A, B, C, D, E, F, G);
method_decl_impl!(A, B, C, D, E, F, G, H);
method_decl_impl!(A, B, C, D, E, F, G, H, I);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// A type for declaring a new class and adding new methods and ivars to it
/// before registering it.
pub struct ClassDecl {
    cls: *mut Class,
}

impl ClassDecl {
    /// Constructs a `ClassDecl` with the given superclass and name.
    /// Returns `None` if the class couldn't be allocated.
    pub fn new(superclass: &Class, name: &str) -> Option<ClassDecl> {
        let name = CString::new(name).unwrap();
        let cls = unsafe {
            runtime::objc_allocateClassPair(superclass, name.as_ptr(), 0)
        };
        if cls.is_null() {
            None
        } else {
            Some(ClassDecl { cls: cls })
        }
    }

    /// Adds a method declared with the given `MethodDecl` to self.
    /// Returns true if the method was sucessfully added.
    pub fn add_method(&mut self, method: MethodDecl) -> bool {
        let MethodDecl { sel, imp, types } = method;
        let types = CString::new(types).unwrap();
        unsafe {
            runtime::class_addMethod(self.cls, sel, imp, types.as_ptr())
        }
    }

    /// Adds an ivar with type `T` and the provided name to self.
    /// Returns true if the ivar was sucessfully added.
    pub fn add_ivar<T>(&mut self, name: &str) -> bool where T: Encode {
        let name = CString::new(name).unwrap();
        let types = CString::new(encode::<T>()).unwrap();
        let size = mem::size_of::<T>() as size_t;
        let align = mem::align_of::<T>() as u8;
        unsafe {
            runtime::class_addIvar(self.cls, name.as_ptr(), size, align,
                types.as_ptr())
        }
    }

    /// Registers self, consuming it and returning a reference to the
    /// newly registered `Class`.
    pub fn register(self) -> &'static Class {
        unsafe {
            let cls = self.cls;
            runtime::objc_registerClassPair(cls);
            // Forget self otherwise the class will be disposed in drop
            mem::forget(self);
            &*cls
        }
    }
}

impl Drop for ClassDecl {
    fn drop(&mut self) {
        unsafe {
            runtime::objc_disposeClassPair(self.cls);
        }
    }
}

#[cfg(test)]
mod tests {
    use runtime::{Object, Sel};
    use test_utils;
    use super::MethodDecl;

    #[test]
    fn test_custom_class() {
        // Registering the custom class is in test_utils
        let obj = test_utils::custom_object();
        unsafe {
            let _: () = msg_send![obj, setFoo:13u32];
            let result: u32 = msg_send![obj, foo];
            assert!(result == 13);
        }
    }

    #[test]
    fn test_mismatched_args() {
        extern fn wrong_num_args_method(_obj: &Object, _cmd: Sel, _a: i32) { }

        let sel = sel!(doSomethingWithFoo:bar:);
        let f: extern fn(&Object, Sel, i32) = wrong_num_args_method;
        let decl = MethodDecl::new(sel, f);
        assert!(decl.is_err());
    }
}
<commit_msg>Added an example for declare.<commit_after>/*!
Functionality for declaring Objective-C classes.

Classes can be declared using the `ClassDecl` struct. Instance variables and
methods can then be added before the class is ultimately registered.

# Example

The following example demonstrates declaring a class named `MyNumber` that has
one ivar, a `u32` named `_number` and a `number` method that returns it:

```
# #[macro_use] extern crate objc;
# use objc::declare::{ClassDecl, MethodDecl};
# use objc::runtime::{Class, Object, Sel};
# fn main() {
let superclass = Class::get("NSObject").unwrap();
let mut decl = ClassDecl::new(superclass, "MyNumber").unwrap();

// Add an instance variable
assert!(decl.add_ivar::<u32>("_number"));

// Add an ObjC method for getting the number
extern fn my_number_get(this: &Object, _cmd: Sel) -> u32 {
    unsafe { *this.get_ivar("_number") }
}
let method = MethodDecl::new(sel!(number),
    my_number_get as extern fn(&Object, Sel) -> u32);
assert!(decl.add_method(method.unwrap()));

decl.register();
# }
```
*/

use std::ffi::CString;
use std::mem;
use libc::size_t;

use {encode, Encode, EncodePtr, Message};
use runtime::{Class, Imp, Sel, self};

/// A type for declaring a new method.
pub struct MethodDecl {
    sel: Sel,
    imp: Imp,
    types: String,
}

impl MethodDecl {
    /// Constructs a `MethodDecl` with the given selector and function.
    ///
    /// Returns an error if the selector and the function take different
    /// numbers of arguments.
    pub fn new<F>(sel: Sel, func: F) -> Result<MethodDecl, ()>
            where F: IntoMethodDecl {
        func.into_method_decl(sel)
    }
}

/// Types that can be used as the implementation of an Objective-C method to
/// construct a `MethodDecl`.
pub trait IntoMethodDecl {
    /// Consumes self to declare a method for the given selector with self as
    /// the implementation.
    ///
    /// Returns an error if self and the selector do not accept the same number
    /// of arguments.
    fn into_method_decl(self, sel: Sel) -> Result<MethodDecl, ()>;
}

macro_rules! count_idents {
    () => (0);
    ($a:ident) => (1);
    ($a:ident, $($b:ident),+) => (1 + count_idents!($($b),*));
}

macro_rules! method_decl_impl {
    (-$s:ident, $sp:ty, $($t:ident),*) => (
        impl<$s, R $(, $t)*> IntoMethodDecl for extern fn($sp, Sel $(, $t)*) -> R
                where $s: Message + EncodePtr, R: Encode $(, $t: Encode)* {
            fn into_method_decl(self, sel: Sel) -> Result<MethodDecl, ()> {
                let num_args = count_idents!($($t),*);
                if sel.name().chars().filter(|&c| c == ':').count() == num_args {
                    let imp: Imp = unsafe { mem::transmute(self) };

                    let mut types = encode::<R>().to_string();
                    types.push_str(encode::<$sp>());
                    types.push_str(encode::<Sel>());
                    $(types.push_str(encode::<$t>());)*

                    Ok(MethodDecl { sel: sel, imp: imp, types: types })
                } else {
                    Err(())
                }
            }
        }
    );
    ($($t:ident),*) => (
        method_decl_impl!(-T, &T, $($t),*);
        method_decl_impl!(-T, &mut T, $($t),*);
    );
}

method_decl_impl!();
method_decl_impl!(A);
method_decl_impl!(A, B);
method_decl_impl!(A, B, C);
method_decl_impl!(A, B, C, D);
method_decl_impl!(A, B, C, D, E);
method_decl_impl!(A, B, C, D, E, F);
method_decl_impl!(A, B, C, D, E, F, G);
method_decl_impl!(A, B, C, D, E, F, G, H);
method_decl_impl!(A, B, C, D, E, F, G, H, I);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K);
method_decl_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// A type for declaring a new class and adding new methods and ivars to it
/// before registering it.
pub struct ClassDecl {
    cls: *mut Class,
}

impl ClassDecl {
    /// Constructs a `ClassDecl` with the given superclass and name.
    /// Returns `None` if the class couldn't be allocated.
    pub fn new(superclass: &Class, name: &str) -> Option<ClassDecl> {
        let name = CString::new(name).unwrap();
        let cls = unsafe {
            runtime::objc_allocateClassPair(superclass, name.as_ptr(), 0)
        };
        if cls.is_null() {
            None
        } else {
            Some(ClassDecl { cls: cls })
        }
    }

    /// Adds a method declared with the given `MethodDecl` to self.
    /// Returns true if the method was sucessfully added.
    pub fn add_method(&mut self, method: MethodDecl) -> bool {
        let MethodDecl { sel, imp, types } = method;
        let types = CString::new(types).unwrap();
        unsafe {
            runtime::class_addMethod(self.cls, sel, imp, types.as_ptr())
        }
    }

    /// Adds an ivar with type `T` and the provided name to self.
    /// Returns true if the ivar was sucessfully added.
    pub fn add_ivar<T>(&mut self, name: &str) -> bool where T: Encode {
        let name = CString::new(name).unwrap();
        let types = CString::new(encode::<T>()).unwrap();
        let size = mem::size_of::<T>() as size_t;
        let align = mem::align_of::<T>() as u8;
        unsafe {
            runtime::class_addIvar(self.cls, name.as_ptr(), size, align,
                types.as_ptr())
        }
    }

    /// Registers self, consuming it and returning a reference to the
    /// newly registered `Class`.
    pub fn register(self) -> &'static Class {
        unsafe {
            let cls = self.cls;
            runtime::objc_registerClassPair(cls);
            // Forget self otherwise the class will be disposed in drop
            mem::forget(self);
            &*cls
        }
    }
}

impl Drop for ClassDecl {
    fn drop(&mut self) {
        unsafe {
            runtime::objc_disposeClassPair(self.cls);
        }
    }
}

#[cfg(test)]
mod tests {
    use runtime::{Object, Sel};
    use test_utils;
    use super::MethodDecl;

    #[test]
    fn test_custom_class() {
        // Registering the custom class is in test_utils
        let obj = test_utils::custom_object();
        unsafe {
            let _: () = msg_send![obj, setFoo:13u32];
            let result: u32 = msg_send![obj, foo];
            assert!(result == 13);
        }
    }

    #[test]
    fn test_mismatched_args() {
        extern fn wrong_num_args_method(_obj: &Object, _cmd: Sel, _a: i32) { }

        let sel = sel!(doSomethingWithFoo:bar:);
        let f: extern fn(&Object, Sel, i32) = wrong_num_args_method;
        let decl = MethodDecl::new(sel, f);
        assert!(decl.is_err());
    }
}
<|endoftext|>


<commit_before>use core::iter::*;
use test::{Bencher, black_box};

#[bench]
fn bench_rposition(b: &mut Bencher) {
    let it: Vec<usize> = (0..300).collect();
    b.iter(|| {
        it.iter().rposition(|&x| x <= 150);
    });
}

#[bench]
fn bench_skip_while(b: &mut Bencher) {
    b.iter(|| {
        let it = 0..100;
        let mut sum = 0;
        it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true);
    });
}

#[bench]
fn bench_multiple_take(b: &mut Bencher) {
    let mut it = (0..42).cycle();
    b.iter(|| {
        let n = it.next().unwrap();
        for _ in 0..n {
            it.clone().take(it.next().unwrap()).all(|_| true);
        }
    });
}

fn scatter(x: i32) -> i32 { (x * 31) % 127 }

#[bench]
fn bench_max_by_key(b: &mut Bencher) {
    b.iter(|| {
        let it = 0..100;
        it.max_by_key(|&x| scatter(x))
    })
}

// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/
#[bench]
fn bench_max_by_key2(b: &mut Bencher) {
    fn max_index_iter(array: &[i32]) -> usize {
        array.iter().enumerate().max_by_key(|&(_, item)| item).unwrap().0
    }

    let mut data = vec![0; 1638];
    data[514] = 9999;

    b.iter(|| max_index_iter(&data));
}

#[bench]
fn bench_max(b: &mut Bencher) {
    b.iter(|| {
        let it = 0..100;
        it.map(scatter).max()
    })
}

pub fn copy_zip(xs: &[u8], ys: &mut [u8]) {
    for (a, b) in ys.iter_mut().zip(xs) {
        *a = *b;
    }
}

pub fn add_zip(xs: &[f32], ys: &mut [f32]) {
    for (a, b) in ys.iter_mut().zip(xs) {
        *a += *b;
    }
}

#[bench]
fn bench_zip_copy(b: &mut Bencher) {
    let source = vec![0u8; 16 * 1024];
    let mut dst = black_box(vec![0u8; 16 * 1024]);
    b.iter(|| {
        copy_zip(&source, &mut dst)
    })
}

#[bench]
fn bench_zip_add(b: &mut Bencher) {
    let source = vec![1.; 16 * 1024];
    let mut dst = vec![0.; 16 * 1024];
    b.iter(|| {
        add_zip(&source, &mut dst)
    });
}

/// `Iterator::for_each` implemented as a plain loop.
fn for_each_loop<I, F>(iter: I, mut f: F) where
    I: Iterator, F: FnMut(I::Item)
{
    for item in iter {
        f(item);
    }
}

/// `Iterator::for_each` implemented with `fold` for internal iteration.
/// (except when `by_ref()` effectively disables that optimization.)
fn for_each_fold<I, F>(iter: I, mut f: F) where
    I: Iterator, F: FnMut(I::Item)
{
    iter.fold((), move |(), item| f(item));
}

#[bench]
fn bench_for_each_chain_loop(b: &mut Bencher) {
    b.iter(|| {
        let mut acc = 0;
        let iter = (0i64..1000000).chain(0..1000000).map(black_box);
        for_each_loop(iter, |x| acc += x);
        acc
    });
}

#[bench]
fn bench_for_each_chain_fold(b: &mut Bencher) {
    b.iter(|| {
        let mut acc = 0;
        let iter = (0i64..1000000).chain(0..1000000).map(black_box);
        for_each_fold(iter, |x| acc += x);
        acc
    });
}

#[bench]
fn bench_for_each_chain_ref_fold(b: &mut Bencher) {
    b.iter(|| {
        let mut acc = 0;
        let mut iter = (0i64..1000000).chain(0..1000000).map(black_box);
        for_each_fold(iter.by_ref(), |x| acc += x);
        acc
    });
}

/// Helper to benchmark `sum` for iterators taken by value which
/// can optimize `fold`, and by reference which cannot.
macro_rules! bench_sums {
    ($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => {
        #[bench]
        fn $bench_sum(b: &mut Bencher) {
            b.iter(|| -> i64 {
                $iter.map(black_box).sum()
            });
        }

        #[bench]
        fn $bench_ref_sum(b: &mut Bencher) {
            b.iter(|| -> i64 {
                $iter.map(black_box).by_ref().sum()
            });
        }
    }
}

bench_sums! {
    bench_flat_map_sum,
    bench_flat_map_ref_sum,
    (0i64..1000).flat_map(|x| x..x+1000)
}

bench_sums! {
    bench_flat_map_chain_sum,
    bench_flat_map_chain_ref_sum,
    (0i64..1000000).flat_map(|x| once(x).chain(once(x)))
}

bench_sums! {
    bench_enumerate_sum,
    bench_enumerate_ref_sum,
    (0i64..1000000).enumerate().map(|(i, x)| x * i as i64)
}

bench_sums! {
    bench_enumerate_chain_sum,
    bench_enumerate_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).enumerate().map(|(i, x)| x * i as i64)
}

bench_sums! {
    bench_filter_sum,
    bench_filter_ref_sum,
    (0i64..1000000).filter(|x| x % 3 == 0)
}

bench_sums! {
    bench_filter_chain_sum,
    bench_filter_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
}

bench_sums! {
    bench_filter_map_sum,
    bench_filter_map_ref_sum,
    (0i64..1000000).filter_map(|x| x.checked_mul(x))
}

bench_sums! {
    bench_filter_map_chain_sum,
    bench_filter_map_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).filter_map(|x| x.checked_mul(x))
}

bench_sums! {
    bench_fuse_sum,
    bench_fuse_ref_sum,
    (0i64..1000000).fuse()
}

bench_sums! {
    bench_fuse_chain_sum,
    bench_fuse_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).fuse()
}

bench_sums! {
    bench_inspect_sum,
    bench_inspect_ref_sum,
    (0i64..1000000).inspect(|_| {})
}

bench_sums! {
    bench_inspect_chain_sum,
    bench_inspect_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).inspect(|_| {})
}

bench_sums! {
    bench_peekable_sum,
    bench_peekable_ref_sum,
    (0i64..1000000).peekable()
}

bench_sums! {
    bench_peekable_chain_sum,
    bench_peekable_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).peekable()
}

bench_sums! {
    bench_skip_sum,
    bench_skip_ref_sum,
    (0i64..1000000).skip(1000)
}

bench_sums! {
    bench_skip_chain_sum,
    bench_skip_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).skip(1000)
}

bench_sums! {
    bench_skip_while_sum,
    bench_skip_while_ref_sum,
    (0i64..1000000).skip_while(|&x| x < 1000)
}

bench_sums! {
    bench_skip_while_chain_sum,
    bench_skip_while_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).skip_while(|&x| x < 1000)
}

bench_sums! {
    bench_take_while_chain_sum,
    bench_take_while_chain_ref_sum,
    (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111)
}

bench_sums! {
    bench_cycle_take_sum,
    bench_cycle_take_ref_sum,
    (0i64..10000).cycle().take(1000000)
}

// Checks whether Skip<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, from
// https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743
#[bench]
fn bench_zip_then_skip(b: &mut Bencher) {
    let v: Vec<_> = (0..100_000).collect();
    let t: Vec<_> = (0..100_000).collect();

    b.iter(|| {
        let s = v.iter().zip(t.iter()).skip(10000)
            .take_while(|t| *t.0 < 10100)
            .map(|(a, b)| *a + *b)
            .sum::<u64>();
        assert_eq!(s, 2009900);
    });
}
#[bench]
fn bench_skip_then_zip(b: &mut Bencher) {
    let v: Vec<_> = (0..100_000).collect();
    let t: Vec<_> = (0..100_000).collect();

    b.iter(|| {
        let s = v.iter().skip(10000).zip(t.iter().skip(10000))
            .take_while(|t| *t.0 < 10100)
            .map(|(a, b)| *a + *b)
            .sum::<u64>();
        assert_eq!(s, 2009900);
    });
}

#[bench]
fn bench_filter_count(b: &mut Bencher) {
    b.iter(|| {
        (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
    })
}

#[bench]
fn bench_filter_ref_count(b: &mut Bencher) {
    b.iter(|| {
        (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
    })
}

#[bench]
fn bench_filter_chain_count(b: &mut Bencher) {
    b.iter(|| {
        (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
    })
}

#[bench]
fn bench_filter_chain_ref_count(b: &mut Bencher) {
    b.iter(|| {
        (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
    })
}
<commit_msg>Fix the bench_max and bench_max_by_key benchmarks<commit_after>use core::iter::*;
use test::{Bencher, black_box};

#[bench]
fn bench_rposition(b: &mut Bencher) {
    let it: Vec<usize> = (0..300).collect();
    b.iter(|| {
        it.iter().rposition(|&x| x <= 150);
    });
}

#[bench]
fn bench_skip_while(b: &mut Bencher) {
    b.iter(|| {
        let it = 0..100;
        let mut sum = 0;
        it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true);
    });
}

#[bench]
fn bench_multiple_take(b: &mut Bencher) {
    let mut it = (0..42).cycle();
    b.iter(|| {
        let n = it.next().unwrap();
        for _ in 0..n {
            it.clone().take(it.next().unwrap()).all(|_| true);
        }
    });
}

fn scatter(x: i32) -> i32 { (x * 31) % 127 }

#[bench]
fn bench_max_by_key(b: &mut Bencher) {
    b.iter(|| {
        let it = 0..100;
        it.map(black_box).max_by_key(|&x| scatter(x))
    })
}

// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/
#[bench]
fn bench_max_by_key2(b: &mut Bencher) {
    fn max_index_iter(array: &[i32]) -> usize {
        array.iter().enumerate().max_by_key(|&(_, item)| item).unwrap().0
    }

    let mut data = vec![0; 1638];
    data[514] = 9999;

    b.iter(|| max_index_iter(&data));
}

#[bench]
fn bench_max(b: &mut Bencher) {
    b.iter(|| {
        let it = 0..100;
        it.map(black_box).map(scatter).max()
    })
}

pub fn copy_zip(xs: &[u8], ys: &mut [u8]) {
    for (a, b) in ys.iter_mut().zip(xs) {
        *a = *b;
    }
}

pub fn add_zip(xs: &[f32], ys: &mut [f32]) {
    for (a, b) in ys.iter_mut().zip(xs) {
        *a += *b;
    }
}

#[bench]
fn bench_zip_copy(b: &mut Bencher) {
    let source = vec![0u8; 16 * 1024];
    let mut dst = black_box(vec![0u8; 16 * 1024]);
    b.iter(|| {
        copy_zip(&source, &mut dst)
    })
}

#[bench]
fn bench_zip_add(b: &mut Bencher) {
    let source = vec![1.; 16 * 1024];
    let mut dst = vec![0.; 16 * 1024];
    b.iter(|| {
        add_zip(&source, &mut dst)
    });
}

/// `Iterator::for_each` implemented as a plain loop.
fn for_each_loop<I, F>(iter: I, mut f: F) where
    I: Iterator, F: FnMut(I::Item)
{
    for item in iter {
        f(item);
    }
}

/// `Iterator::for_each` implemented with `fold` for internal iteration.
/// (except when `by_ref()` effectively disables that optimization.)
fn for_each_fold<I, F>(iter: I, mut f: F) where
    I: Iterator, F: FnMut(I::Item)
{
    iter.fold((), move |(), item| f(item));
}

#[bench]
fn bench_for_each_chain_loop(b: &mut Bencher) {
    b.iter(|| {
        let mut acc = 0;
        let iter = (0i64..1000000).chain(0..1000000).map(black_box);
        for_each_loop(iter, |x| acc += x);
        acc
    });
}

#[bench]
fn bench_for_each_chain_fold(b: &mut Bencher) {
    b.iter(|| {
        let mut acc = 0;
        let iter = (0i64..1000000).chain(0..1000000).map(black_box);
        for_each_fold(iter, |x| acc += x);
        acc
    });
}

#[bench]
fn bench_for_each_chain_ref_fold(b: &mut Bencher) {
    b.iter(|| {
        let mut acc = 0;
        let mut iter = (0i64..1000000).chain(0..1000000).map(black_box);
        for_each_fold(iter.by_ref(), |x| acc += x);
        acc
    });
}

/// Helper to benchmark `sum` for iterators taken by value which
/// can optimize `fold`, and by reference which cannot.
macro_rules! bench_sums {
    ($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => {
        #[bench]
        fn $bench_sum(b: &mut Bencher) {
            b.iter(|| -> i64 {
                $iter.map(black_box).sum()
            });
        }

        #[bench]
        fn $bench_ref_sum(b: &mut Bencher) {
            b.iter(|| -> i64 {
                $iter.map(black_box).by_ref().sum()
            });
        }
    }
}

bench_sums! {
    bench_flat_map_sum,
    bench_flat_map_ref_sum,
    (0i64..1000).flat_map(|x| x..x+1000)
}

bench_sums! {
    bench_flat_map_chain_sum,
    bench_flat_map_chain_ref_sum,
    (0i64..1000000).flat_map(|x| once(x).chain(once(x)))
}

bench_sums! {
    bench_enumerate_sum,
    bench_enumerate_ref_sum,
    (0i64..1000000).enumerate().map(|(i, x)| x * i as i64)
}

bench_sums! {
    bench_enumerate_chain_sum,
    bench_enumerate_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).enumerate().map(|(i, x)| x * i as i64)
}

bench_sums! {
    bench_filter_sum,
    bench_filter_ref_sum,
    (0i64..1000000).filter(|x| x % 3 == 0)
}

bench_sums! {
    bench_filter_chain_sum,
    bench_filter_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
}

bench_sums! {
    bench_filter_map_sum,
    bench_filter_map_ref_sum,
    (0i64..1000000).filter_map(|x| x.checked_mul(x))
}

bench_sums! {
    bench_filter_map_chain_sum,
    bench_filter_map_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).filter_map(|x| x.checked_mul(x))
}

bench_sums! {
    bench_fuse_sum,
    bench_fuse_ref_sum,
    (0i64..1000000).fuse()
}

bench_sums! {
    bench_fuse_chain_sum,
    bench_fuse_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).fuse()
}

bench_sums! {
    bench_inspect_sum,
    bench_inspect_ref_sum,
    (0i64..1000000).inspect(|_| {})
}

bench_sums! {
    bench_inspect_chain_sum,
    bench_inspect_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).inspect(|_| {})
}

bench_sums! {
    bench_peekable_sum,
    bench_peekable_ref_sum,
    (0i64..1000000).peekable()
}

bench_sums! {
    bench_peekable_chain_sum,
    bench_peekable_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).peekable()
}

bench_sums! {
    bench_skip_sum,
    bench_skip_ref_sum,
    (0i64..1000000).skip(1000)
}

bench_sums! {
    bench_skip_chain_sum,
    bench_skip_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).skip(1000)
}

bench_sums! {
    bench_skip_while_sum,
    bench_skip_while_ref_sum,
    (0i64..1000000).skip_while(|&x| x < 1000)
}

bench_sums! {
    bench_skip_while_chain_sum,
    bench_skip_while_chain_ref_sum,
    (0i64..1000000).chain(0..1000000).skip_while(|&x| x < 1000)
}

bench_sums! {
    bench_take_while_chain_sum,
    bench_take_while_chain_ref_sum,
    (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111)
}

bench_sums! {
    bench_cycle_take_sum,
    bench_cycle_take_ref_sum,
    (0i64..10000).cycle().take(1000000)
}

// Checks whether Skip<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, from
// https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743
#[bench]
fn bench_zip_then_skip(b: &mut Bencher) {
    let v: Vec<_> = (0..100_000).collect();
    let t: Vec<_> = (0..100_000).collect();

    b.iter(|| {
        let s = v.iter().zip(t.iter()).skip(10000)
            .take_while(|t| *t.0 < 10100)
            .map(|(a, b)| *a + *b)
            .sum::<u64>();
        assert_eq!(s, 2009900);
    });
}
#[bench]
fn bench_skip_then_zip(b: &mut Bencher) {
    let v: Vec<_> = (0..100_000).collect();
    let t: Vec<_> = (0..100_000).collect();

    b.iter(|| {
        let s = v.iter().skip(10000).zip(t.iter().skip(10000))
            .take_while(|t| *t.0 < 10100)
            .map(|(a, b)| *a + *b)
            .sum::<u64>();
        assert_eq!(s, 2009900);
    });
}

#[bench]
fn bench_filter_count(b: &mut Bencher) {
    b.iter(|| {
        (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
    })
}

#[bench]
fn bench_filter_ref_count(b: &mut Bencher) {
    b.iter(|| {
        (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
    })
}

#[bench]
fn bench_filter_chain_count(b: &mut Bencher) {
    b.iter(|| {
        (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
    })
}

#[bench]
fn bench_filter_chain_ref_count(b: &mut Bencher) {
    b.iter(|| {
        (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
    })
}
<|endoftext|>


<commit_before>use crate::io::{self, IoSlice, IoSliceMut};
use crate::sys::Void;

pub struct AnonPipe(Void);

impl AnonPipe {
    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
        match self.0 {}
    }

    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        match self.0 {}
    }

    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
        match self.0 {}
    }

    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        match self.0 {}
    }

    pub fn diverge(&self) -> ! {
        match self.0 {}
    }
}

pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
    match p1.0 {}
}
<commit_msg>fix wasm build<commit_after>use crate::io::{self, IoSlice, IoSliceMut};
use crate::sys::Void;

pub struct AnonPipe(Void);

impl AnonPipe {
    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
        match self.0 {}
    }

    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        match self.0 {}
    }

    pub fn is_read_vectored(&self) -> bool {
        match self.0 {}
    }

    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
        match self.0 {}
    }

    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        match self.0 {}
    }

    pub fn is_write_vectored(&self) -> bool {
        match self.0 {}
    }

    pub fn diverge(&self) -> ! {
        match self.0 {}
    }
}

pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
    match p1.0 {}
}
<|endoftext|>


<commit_before>pub struct Paragraph {
    parts: Vec<Text>,
}

pub enum Text {
    Plain(String),      // TODO: make these &str and figure out lifetimes
    Bold(String),
}

impl Paragraph {
    pub fn new(text: &str) -> Paragraph {
        Paragraph {
            parts: Vec::new(),
        }
    }

    pub fn to_html(&self) -> String {
        let s = String::new();

        s
    }
}

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

    #[test]
    fn test_parse() {
        let p = Paragraph::new("hello world");
    }

    #[test]
    fn test_html() {
        let p = Paragraph {
            parts: vec![Text::Plain("plaintext".to_owned()),
                        Text::Bold("bold text".to_owned())],
        };
    }
}
<commit_msg>First draft of Paragraph<commit_after>pub struct Paragraph {
    parts: Vec<Text>,
}

pub enum Text {
    Plain(String),      // TODO: make these &str and figure out lifetimes
    Bold(String),
}

impl Paragraph {
    pub fn new(text: &str) -> Paragraph {
        Paragraph {
            parts: Vec::new(),
        }
    }

    pub fn to_html(&self) -> String {
        self.parts.iter().map(|text| match text {
            &Text::Plain(ref s) => s.to_string(),
            &Text::Bold(ref s) => ["", &s[..], ""].join("").to_string(),
        }).collect::<Vec<_>>().join("")
    }
}

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

    #[test]
    fn test_parse() {
        let p = Paragraph::new("hello world");
    }

    #[test]
    fn test_html1() {
        let p = Paragraph {
            parts: vec![Text::Plain("plaintext ".to_owned()),
                        Text::Bold("bold text".to_owned())],
        };

        assert!(p.to_html() == "plaintext bold text".to_owned());
    }
}
<|endoftext|>