<commit_before>
use handshake::{Token, HandshakePattern};
use handshake::Token::*;
use crypto_stuff::{copy_memory};

fn copy_tokens(input: &[Token], out: &mut [Token]) {
    for count in 0..input.len() {out[count] = input[count];}
}

pub struct NoiseN;
pub struct NoiseK;
pub struct NoiseX;

pub struct NoiseNN;
pub struct NoiseNK;
pub struct NoiseNE;
pub struct NoiseNX;

pub struct NoiseXN;
pub struct NoiseXK;
pub struct NoiseXE;
pub struct NoiseXX;

pub struct NoiseKN;
pub struct NoiseKK;
pub struct NoiseKE;
pub struct NoiseKX;

pub struct NoiseIN;
pub struct NoiseIK;
pub struct NoiseIE;
pub struct NoiseIX;

impl HandshakePattern for NoiseN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_N".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes], &mut msg_patterns[0]);
    }
}

impl HandshakePattern for NoiseK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_K".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes, Dhss], &mut msg_patterns[0]);
    }
}

impl HandshakePattern for NoiseX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_X".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes, S, Dhss], &mut msg_patterns[0]);
    }
}

impl HandshakePattern for NoiseNN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_NN".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseNK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_NK".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseNE {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_NE".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S, E], premsg_pattern_r);

        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseNX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_NX".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, S, Dhse], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseXN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_XN".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
        copy_tokens(&[S, Dhse], &mut msg_patterns[2]);
    }
}

impl HandshakePattern for NoiseXK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_XK".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
        copy_tokens(&[S, Dhse], &mut msg_patterns[2]);
    }
}

impl HandshakePattern for NoiseXE {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_XE".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S, E], premsg_pattern_r);

        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
        copy_tokens(&[S, Dhse], &mut msg_patterns[2]);
    }
}

impl HandshakePattern for NoiseXX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_XX".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {

        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, S, Dhse], &mut msg_patterns[1]);
        copy_tokens(&[S, Dhse], &mut msg_patterns[2]);
    }
}

impl HandshakePattern for NoiseKN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_KN".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseKK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_KK".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes, Dhss], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseKE {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_KE".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[S, E], premsg_pattern_r);

        copy_tokens(&[E, Dhee, Dhes, Dhse], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseKX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_KX".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes, S, Dhse], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseIN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_IN".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[S, E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseIK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_IK".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes, S, Dhss], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseIE {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_IE".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S, E], premsg_pattern_r);

        copy_tokens(&[E, Dhee, Dhes, S, Dhse], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseIX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_IX".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[S, E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes, S, Dhse], &mut msg_patterns[1]);
    }
}
<commit_msg>s,e -> e,s<commit_after>
use handshake::{Token, HandshakePattern};
use handshake::Token::*;
use crypto_stuff::{copy_memory};

fn copy_tokens(input: &[Token], out: &mut [Token]) {
    for count in 0..input.len() {out[count] = input[count];}
}

pub struct NoiseN;
pub struct NoiseK;
pub struct NoiseX;

pub struct NoiseNN;
pub struct NoiseNK;
pub struct NoiseNE;
pub struct NoiseNX;

pub struct NoiseXN;
pub struct NoiseXK;
pub struct NoiseXE;
pub struct NoiseXX;

pub struct NoiseKN;
pub struct NoiseKK;
pub struct NoiseKE;
pub struct NoiseKX;

pub struct NoiseIN;
pub struct NoiseIK;
pub struct NoiseIE;
pub struct NoiseIX;

impl HandshakePattern for NoiseN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_N".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes], &mut msg_patterns[0]);
    }
}

impl HandshakePattern for NoiseK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_K".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes, Dhss], &mut msg_patterns[0]);
    }
}

impl HandshakePattern for NoiseX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_X".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes, S, Dhss], &mut msg_patterns[0]);
    }
}

impl HandshakePattern for NoiseNN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_NN".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseNK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_NK".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseNE {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_NE".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S, E], premsg_pattern_r);

        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseNX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_NX".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, S, Dhse], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseXN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_XN".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
        copy_tokens(&[S, Dhse], &mut msg_patterns[2]);
    }
}

impl HandshakePattern for NoiseXK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_XK".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
        copy_tokens(&[S, Dhse], &mut msg_patterns[2]);
    }
}

impl HandshakePattern for NoiseXE {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_XE".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S, E], premsg_pattern_r);

        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee], &mut msg_patterns[1]);
        copy_tokens(&[S, Dhse], &mut msg_patterns[2]);
    }
}

impl HandshakePattern for NoiseXX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_XX".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {

        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, S, Dhse], &mut msg_patterns[1]);
        copy_tokens(&[S, Dhse], &mut msg_patterns[2]);
    }
}

impl HandshakePattern for NoiseKN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_KN".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseKK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_KK".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes, Dhss], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseKE {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_KE".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[S, E], premsg_pattern_r);

        copy_tokens(&[E, Dhee, Dhes, Dhse], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseKX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_KX".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[S], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes, S, Dhse], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseIN {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_IN".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E, S], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseIK {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_IK".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S], premsg_pattern_r);

        copy_tokens(&[E, Dhes, S, Dhss], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseIE {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_IE".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[S, E], premsg_pattern_r);

        copy_tokens(&[E, Dhee, Dhes, S, Dhse], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes], &mut msg_patterns[1]);
    }
}

impl HandshakePattern for NoiseIX {
    fn name(out : &mut [u8]) -> usize {
        copy_memory("Noise_IX".as_bytes(), out)
    }

    fn get(premsg_pattern_i: &mut [Token],
           premsg_pattern_r: &mut [Token],
           msg_patterns: &mut [[Token; 8]; 5]) {
        copy_tokens(&[], premsg_pattern_i);
        copy_tokens(&[], premsg_pattern_r);

        copy_tokens(&[E, S], &mut msg_patterns[0]);
        copy_tokens(&[E, Dhee, Dhes, S, Dhse], &mut msg_patterns[1]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#![cfg_attr(not(feature = "v1_12"), allow(unused_imports))]

use libc::{c_double, c_int, c_uint};
use std::mem::transmute;
use ffi::enums::{
    Extend,
    Filter,
    Status,
    PatternType
};
use ffi;
use ffi::{
    cairo_pattern_t
};
use ::{
    Path,
    Matrix,
    MatrixTrait,
};

//Quite some changes from the C api but all suggested by the cairo devs.
//See http://cairographics.org/manual/bindings-patterns.html for more info

//TODO Does anyone know a way to do this without dynamic dispatch -- @mthq
pub fn wrap_pattern<'a>(ptr: *mut cairo_pattern_t) -> Box<Pattern + 'a> {
    let pattern_type = unsafe{ ffi::cairo_pattern_get_type(ptr) };

    match pattern_type {
        PatternType::Solid            => Box::new(SolidPattern::wrap(ptr))   as Box<Pattern>,
        PatternType::Surface          => Box::new(SurfacePattern::wrap(ptr)) as Box<Pattern>,
        PatternType::LinearGradient   => Box::new(LinearGradient::wrap(ptr)) as Box<Pattern>,
        PatternType::RadialGradient   => Box::new(RadialGradient::wrap(ptr)) as Box<Pattern>,
        #[cfg(feature = "v1_12")]
        PatternType::Mesh             => Box::new(Mesh::wrap(ptr))           as Box<Pattern>,
        #[cfg(feature = "v1_12")]
        PatternType::RasterSource     => panic!("Not implemented")
    }
}

pub trait Pattern {
    #[doc(hidden)]
    fn get_ptr(&self) -> *mut cairo_pattern_t;

    fn ensure_status(&self) {
        self.status().ensure_valid();
    }

    fn status(&self) -> Status {
        unsafe {
            ffi::cairo_pattern_status(self.get_ptr())
        }
    }

    fn get_reference_count(&self) -> isize {
        unsafe {
            ffi::cairo_pattern_get_reference_count(self.get_ptr()) as isize
        }
    }

    fn set_extend(&self, extend: Extend) {
        unsafe {
            ffi::cairo_pattern_set_extend(self.get_ptr(), extend)
        }
    }

    fn get_extend(&self) -> Extend {
        unsafe {
            ffi::cairo_pattern_get_extend(self.get_ptr())
        }
    }

    fn set_filter(&self, filter: Filter) {
        unsafe {
            ffi::cairo_pattern_set_filter(self.get_ptr(), filter)
        }
    }

    fn get_filter(&self) -> Filter {
        unsafe {
            ffi::cairo_pattern_get_filter(self.get_ptr())
        }
    }

    fn set_matrix(&self, matrix: Matrix) {
        unsafe {
            ffi::cairo_pattern_set_matrix (self.get_ptr(), &matrix)
        }
    }

    fn get_matrix(&self) -> Matrix {
        let mut matrix = <Matrix as MatrixTrait>::null();
        unsafe {
            ffi::cairo_pattern_get_matrix(self.get_ptr(), &mut matrix);
        }
        matrix
    }
}

macro_rules! pattern_type(
    //Signals without arguments
    ($pattern_type:ident) => (

        pub struct $pattern_type {
            pointer: *mut cairo_pattern_t
        }

        impl $pattern_type {
            pub fn wrap(pointer: *mut cairo_pattern_t) -> $pattern_type {
                $pattern_type{
                    pointer: pointer
                }
            }

            pub fn reference(&self) -> $pattern_type {
                $pattern_type{
                    pointer: unsafe {
                        ffi::cairo_pattern_reference(self.pointer)
                    }
                }
            }
        }

        impl Pattern for $pattern_type {
            fn get_ptr(&self) -> *mut cairo_pattern_t{
                self.pointer
            }
        }

        impl Drop for $pattern_type {
            fn drop(&mut self){
                unsafe {
                    ffi::cairo_pattern_destroy(self.pointer)
                }
            }
        }
    );
);

pattern_type!(SolidPattern);

impl SolidPattern {
    pub fn from_rgb(red: f64, green: f64, blue: f64) -> SolidPattern {
        SolidPattern::wrap(unsafe {
            ffi::cairo_pattern_create_rgb(red, green, blue)
        })
    }

    pub fn from_rgba(red: f64, green: f64, blue: f64, alpha: f64) -> SolidPattern {
        SolidPattern::wrap(unsafe {
            ffi::cairo_pattern_create_rgba(red, green, blue, alpha)
        })
    }

    pub fn get_rgba(&self) -> (f64, f64, f64, f64) {
        unsafe {
            let red  : *mut c_double = transmute(Box::new(0.0f64));
            let green: *mut c_double = transmute(Box::new(0.0f64));
            let blue : *mut c_double = transmute(Box::new(0.0f64));
            let alpha: *mut c_double = transmute(Box::new(0.0f64));

            ffi::cairo_pattern_get_rgba(self.pointer, red, green, blue, alpha).ensure_valid();

            (*red, *green, *blue, *alpha)
        }
    }
}

pub trait Gradient : Pattern {
    fn add_color_stop_rgb(&self, offset: f64, red: f64, green: f64, blue: f64) {
        unsafe {
            ffi::cairo_pattern_add_color_stop_rgb(self.get_ptr(), offset, red, green, blue)
        }
    }

    fn add_color_stop_rgba(&self, offset: f64, red: f64, green: f64, blue: f64, alpha: f64) {
        unsafe {
            ffi::cairo_pattern_add_color_stop_rgba(self.get_ptr(), offset, red, green, blue, alpha)
        }
    }

    fn get_color_stop_count(&self) -> isize {
        unsafe {
            let count : *mut c_int = transmute(Box::new(0i32));
            let result = ffi::cairo_pattern_get_color_stop_count(self.get_ptr(), count);

            result.ensure_valid(); // Not sure if these are needed
            count as isize
        }
    }

    fn get_color_stop_rgba(&self, index: isize) -> (f64, f64, f64, f64, f64) {
        unsafe {
            let offset: *mut c_double = transmute(Box::new(0.0f64));
            let red   : *mut c_double = transmute(Box::new(0.0f64));
            let green : *mut c_double = transmute(Box::new(0.0f64));
            let blue  : *mut c_double = transmute(Box::new(0.0f64));
            let alpha : *mut c_double = transmute(Box::new(0.0f64));

            ffi::cairo_pattern_get_color_stop_rgba(self.get_ptr(), index as c_int, offset, red, green, blue, alpha).ensure_valid();
            (*offset, *red, *green, *blue, *alpha)
        }
    }
}

pattern_type!(LinearGradient);

impl LinearGradient {
    pub fn new(x0: f64, y0: f64, x1: f64, y1: f64) -> LinearGradient {
        LinearGradient::wrap(unsafe {
            ffi::cairo_pattern_create_linear(x0, y0, x1, y1)
        })
    }

    pub fn get_linear_points(&self) -> (f64, f64, f64, f64) {
        unsafe {
            let x0 : *mut c_double = transmute(Box::new(0.0f64));
            let y0 : *mut c_double = transmute(Box::new(0.0f64));
            let x1 : *mut c_double = transmute(Box::new(0.0f64));
            let y1 : *mut c_double = transmute(Box::new(0.0f64));

            ffi::cairo_pattern_get_linear_points(self.pointer, x0, y0, x1, y1).ensure_valid();
            (*x0, *y0, *x1, *y1)
        }
    }
}

impl Gradient for LinearGradient{}

pattern_type!(RadialGradient);

impl RadialGradient {
    pub fn new(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64) -> RadialGradient {
        RadialGradient::wrap(unsafe{
            ffi::cairo_pattern_create_radial(x0, y0, r0, x1, y1, r1)
        })
    }

    pub fn get_radial_circles(&self) -> (f64,f64,f64,f64) {
        unsafe{
            let x0 : *mut c_double = transmute(Box::new(0.0f64));
            let y0 : *mut c_double = transmute(Box::new(0.0f64));
            let r0 : *mut c_double = transmute(Box::new(0.0f64));
            let x1 : *mut c_double = transmute(Box::new(0.0f64));
            let y1 : *mut c_double = transmute(Box::new(0.0f64));
            let r1 : *mut c_double = transmute(Box::new(0.0f64));

            ffi::cairo_pattern_get_radial_circles(self.pointer, x0, y0, r0, x1, y1, r1).ensure_valid();
            (*x0, *y0, *x1, *y1)
        }
    }
}

impl Gradient for RadialGradient{}

pattern_type!(SurfacePattern);

impl SurfacePattern {
    //pub fn cairo_pattern_create_for_surface(surface: *mut cairo_surface_t) -> *mut cairo_pattern_t;

    //pub fn cairo_pattern_get_surface(pattern: *mut cairo_pattern_t, surface: **mut cairo_surface_t) -> Status;
}

#[cfg(feature = "v1_12")]
#[derive(Clone, PartialEq, PartialOrd, Copy)]
pub enum MeshCorner {
    MeshCorner0,
    MeshCorner1,
    MeshCorner2,
    MeshCorner3
}

#[cfg(feature = "v1_12")]
pattern_type!(Mesh);

#[cfg(feature = "v1_12")]
impl Mesh {
    pub fn new() -> Mesh {
        Mesh::wrap(unsafe {
            ffi::cairo_pattern_create_mesh()
        })
    }

    pub fn begin_patch(&self) {
        unsafe {
            ffi::cairo_mesh_pattern_begin_patch(self.pointer)
        }
        self.ensure_status();
    }

    pub fn end_patch(&self) {
        unsafe {
            ffi::cairo_mesh_pattern_end_patch(self.pointer)
        }
        self.ensure_status();
    }

    pub fn move_to(&self, x: f64, y: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_move_to(self.pointer, x, y)
        }
        self.ensure_status();
    }

    pub fn line_to(&self, x: f64, y: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_line_to(self.pointer, x, y)
        }
        self.ensure_status();
    }

    pub fn curve_to(&self, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_curve_to(self.pointer, x1, y1, x2, y2, x3, y3)
        }
        self.ensure_status();
    }

    pub fn set_control_point(&self, corner: MeshCorner, x: f64, y: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_set_control_point(self.pointer, corner as c_uint, x, y)
        }
        self.ensure_status();
    }

    pub fn get_control_point(&self, patch_num: usize, corner: MeshCorner) -> (f64, f64) {
        let mut x: c_double = 0.0;
        let mut y: c_double = 0.0;

        let status = unsafe {
            ffi::cairo_mesh_pattern_get_control_point(self.pointer, patch_num as c_uint, corner as c_uint, &mut x, &mut y)
        };
        status.ensure_valid();
        (x, y)
    }

    pub fn set_corner_color_rgb(&self, corner: MeshCorner, red: f64, green: f64, blue: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_set_corner_color_rgb(self.pointer, corner as c_uint, red, green, blue)
        }
        self.ensure_status();
    }

    pub fn set_corner_color_rgba(&self, corner: MeshCorner, red: f64, green: f64, blue: f64, alpha: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_set_corner_color_rgba(self.pointer, corner as c_uint, red, green, blue, alpha)
        }
        self.ensure_status();
    }

    pub fn get_corner_color_rgba(&self, patch_num: usize, corner: MeshCorner) -> (f64, f64, f64, f64) {
        let mut red: c_double = 0.0;
        let mut green: c_double = 0.0;
        let mut blue: c_double = 0.0;
        let mut alpha: c_double = 0.0;

        let status = unsafe {
            ffi::cairo_mesh_pattern_get_corner_color_rgba(self.pointer, patch_num as c_uint, corner as c_uint, &mut red, &mut green, &mut blue, &mut alpha)
        };
        status.ensure_valid();
        (red, green, blue, alpha)
    }

    pub fn get_patch_count(&self) -> usize {
        let mut count: c_uint = 0;
        unsafe {
            ffi::cairo_mesh_pattern_get_patch_count(self.pointer, &mut count).ensure_valid();
        }
        count as usize
    }

    pub fn get_path(&self, patch_num: usize) -> Path {
        let path: Path = Path::wrap(unsafe {
            ffi::cairo_mesh_pattern_get_path(self.pointer, patch_num as c_uint)
        });
        path.ensure_status();
        path
    }
}
<commit_msg>SurfacePattern: implement create() and get_surface()<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#![cfg_attr(not(feature = "v1_12"), allow(unused_imports))]

use libc::{c_double, c_int, c_uint};
use std::ptr;
use std::mem::transmute;
use glib::translate::*;
use ffi::enums::{
    Extend,
    Filter,
    Status,
    PatternType
};
use ffi;
use ffi::{
    cairo_pattern_t,
    cairo_surface_t,
};
use ::{
    Path,
    Matrix,
    MatrixTrait,
    Surface,
};

//Quite some changes from the C api but all suggested by the cairo devs.
//See http://cairographics.org/manual/bindings-patterns.html for more info

//TODO Does anyone know a way to do this without dynamic dispatch -- @mthq
pub fn wrap_pattern<'a>(ptr: *mut cairo_pattern_t) -> Box<Pattern + 'a> {
    let pattern_type = unsafe{ ffi::cairo_pattern_get_type(ptr) };

    match pattern_type {
        PatternType::Solid            => Box::new(SolidPattern::wrap(ptr))   as Box<Pattern>,
        PatternType::Surface          => Box::new(SurfacePattern::wrap(ptr)) as Box<Pattern>,
        PatternType::LinearGradient   => Box::new(LinearGradient::wrap(ptr)) as Box<Pattern>,
        PatternType::RadialGradient   => Box::new(RadialGradient::wrap(ptr)) as Box<Pattern>,
        #[cfg(feature = "v1_12")]
        PatternType::Mesh             => Box::new(Mesh::wrap(ptr))           as Box<Pattern>,
        #[cfg(feature = "v1_12")]
        PatternType::RasterSource     => panic!("Not implemented")
    }
}

pub trait Pattern {
    #[doc(hidden)]
    fn get_ptr(&self) -> *mut cairo_pattern_t;

    fn ensure_status(&self) {
        self.status().ensure_valid();
    }

    fn status(&self) -> Status {
        unsafe {
            ffi::cairo_pattern_status(self.get_ptr())
        }
    }

    fn get_reference_count(&self) -> isize {
        unsafe {
            ffi::cairo_pattern_get_reference_count(self.get_ptr()) as isize
        }
    }

    fn set_extend(&self, extend: Extend) {
        unsafe {
            ffi::cairo_pattern_set_extend(self.get_ptr(), extend)
        }
    }

    fn get_extend(&self) -> Extend {
        unsafe {
            ffi::cairo_pattern_get_extend(self.get_ptr())
        }
    }

    fn set_filter(&self, filter: Filter) {
        unsafe {
            ffi::cairo_pattern_set_filter(self.get_ptr(), filter)
        }
    }

    fn get_filter(&self) -> Filter {
        unsafe {
            ffi::cairo_pattern_get_filter(self.get_ptr())
        }
    }

    fn set_matrix(&self, matrix: Matrix) {
        unsafe {
            ffi::cairo_pattern_set_matrix (self.get_ptr(), &matrix)
        }
    }

    fn get_matrix(&self) -> Matrix {
        let mut matrix = <Matrix as MatrixTrait>::null();
        unsafe {
            ffi::cairo_pattern_get_matrix(self.get_ptr(), &mut matrix);
        }
        matrix
    }
}

macro_rules! pattern_type(
    //Signals without arguments
    ($pattern_type:ident) => (

        pub struct $pattern_type {
            pointer: *mut cairo_pattern_t
        }

        impl $pattern_type {
            pub fn wrap(pointer: *mut cairo_pattern_t) -> $pattern_type {
                $pattern_type{
                    pointer: pointer
                }
            }

            pub fn reference(&self) -> $pattern_type {
                $pattern_type{
                    pointer: unsafe {
                        ffi::cairo_pattern_reference(self.pointer)
                    }
                }
            }
        }

        impl Pattern for $pattern_type {
            fn get_ptr(&self) -> *mut cairo_pattern_t{
                self.pointer
            }
        }

        impl Drop for $pattern_type {
            fn drop(&mut self){
                unsafe {
                    ffi::cairo_pattern_destroy(self.pointer)
                }
            }
        }
    );
);

pattern_type!(SolidPattern);

impl SolidPattern {
    pub fn from_rgb(red: f64, green: f64, blue: f64) -> SolidPattern {
        SolidPattern::wrap(unsafe {
            ffi::cairo_pattern_create_rgb(red, green, blue)
        })
    }

    pub fn from_rgba(red: f64, green: f64, blue: f64, alpha: f64) -> SolidPattern {
        SolidPattern::wrap(unsafe {
            ffi::cairo_pattern_create_rgba(red, green, blue, alpha)
        })
    }

    pub fn get_rgba(&self) -> (f64, f64, f64, f64) {
        unsafe {
            let red  : *mut c_double = transmute(Box::new(0.0f64));
            let green: *mut c_double = transmute(Box::new(0.0f64));
            let blue : *mut c_double = transmute(Box::new(0.0f64));
            let alpha: *mut c_double = transmute(Box::new(0.0f64));

            ffi::cairo_pattern_get_rgba(self.pointer, red, green, blue, alpha).ensure_valid();

            (*red, *green, *blue, *alpha)
        }
    }
}

pub trait Gradient : Pattern {
    fn add_color_stop_rgb(&self, offset: f64, red: f64, green: f64, blue: f64) {
        unsafe {
            ffi::cairo_pattern_add_color_stop_rgb(self.get_ptr(), offset, red, green, blue)
        }
    }

    fn add_color_stop_rgba(&self, offset: f64, red: f64, green: f64, blue: f64, alpha: f64) {
        unsafe {
            ffi::cairo_pattern_add_color_stop_rgba(self.get_ptr(), offset, red, green, blue, alpha)
        }
    }

    fn get_color_stop_count(&self) -> isize {
        unsafe {
            let count : *mut c_int = transmute(Box::new(0i32));
            let result = ffi::cairo_pattern_get_color_stop_count(self.get_ptr(), count);

            result.ensure_valid(); // Not sure if these are needed
            count as isize
        }
    }

    fn get_color_stop_rgba(&self, index: isize) -> (f64, f64, f64, f64, f64) {
        unsafe {
            let offset: *mut c_double = transmute(Box::new(0.0f64));
            let red   : *mut c_double = transmute(Box::new(0.0f64));
            let green : *mut c_double = transmute(Box::new(0.0f64));
            let blue  : *mut c_double = transmute(Box::new(0.0f64));
            let alpha : *mut c_double = transmute(Box::new(0.0f64));

            ffi::cairo_pattern_get_color_stop_rgba(self.get_ptr(), index as c_int, offset, red, green, blue, alpha).ensure_valid();
            (*offset, *red, *green, *blue, *alpha)
        }
    }
}

pattern_type!(LinearGradient);

impl LinearGradient {
    pub fn new(x0: f64, y0: f64, x1: f64, y1: f64) -> LinearGradient {
        LinearGradient::wrap(unsafe {
            ffi::cairo_pattern_create_linear(x0, y0, x1, y1)
        })
    }

    pub fn get_linear_points(&self) -> (f64, f64, f64, f64) {
        unsafe {
            let x0 : *mut c_double = transmute(Box::new(0.0f64));
            let y0 : *mut c_double = transmute(Box::new(0.0f64));
            let x1 : *mut c_double = transmute(Box::new(0.0f64));
            let y1 : *mut c_double = transmute(Box::new(0.0f64));

            ffi::cairo_pattern_get_linear_points(self.pointer, x0, y0, x1, y1).ensure_valid();
            (*x0, *y0, *x1, *y1)
        }
    }
}

impl Gradient for LinearGradient{}

pattern_type!(RadialGradient);

impl RadialGradient {
    pub fn new(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64) -> RadialGradient {
        RadialGradient::wrap(unsafe{
            ffi::cairo_pattern_create_radial(x0, y0, r0, x1, y1, r1)
        })
    }

    pub fn get_radial_circles(&self) -> (f64,f64,f64,f64) {
        unsafe{
            let x0 : *mut c_double = transmute(Box::new(0.0f64));
            let y0 : *mut c_double = transmute(Box::new(0.0f64));
            let r0 : *mut c_double = transmute(Box::new(0.0f64));
            let x1 : *mut c_double = transmute(Box::new(0.0f64));
            let y1 : *mut c_double = transmute(Box::new(0.0f64));
            let r1 : *mut c_double = transmute(Box::new(0.0f64));

            ffi::cairo_pattern_get_radial_circles(self.pointer, x0, y0, r0, x1, y1, r1).ensure_valid();
            (*x0, *y0, *x1, *y1)
        }
    }
}

impl Gradient for RadialGradient{}

pattern_type!(SurfacePattern);

impl SurfacePattern {
    pub fn create<T: AsRef<Surface>>(surface: &T) -> SurfacePattern {
        SurfacePattern::wrap(unsafe {
            ffi::cairo_pattern_create_for_surface(surface.as_ref().to_glib_none().0)
        })
    }

    pub fn get_surface(&self) -> Surface {
        unsafe {
            let mut surface_ptr: *mut cairo_surface_t = ptr::null_mut();
            ffi::cairo_pattern_get_surface(self.pointer, &mut surface_ptr).ensure_valid();
            Surface::from_glib_none(surface_ptr)
        }
    }
}

#[cfg(feature = "v1_12")]
#[derive(Clone, PartialEq, PartialOrd, Copy)]
pub enum MeshCorner {
    MeshCorner0,
    MeshCorner1,
    MeshCorner2,
    MeshCorner3
}

#[cfg(feature = "v1_12")]
pattern_type!(Mesh);

#[cfg(feature = "v1_12")]
impl Mesh {
    pub fn new() -> Mesh {
        Mesh::wrap(unsafe {
            ffi::cairo_pattern_create_mesh()
        })
    }

    pub fn begin_patch(&self) {
        unsafe {
            ffi::cairo_mesh_pattern_begin_patch(self.pointer)
        }
        self.ensure_status();
    }

    pub fn end_patch(&self) {
        unsafe {
            ffi::cairo_mesh_pattern_end_patch(self.pointer)
        }
        self.ensure_status();
    }

    pub fn move_to(&self, x: f64, y: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_move_to(self.pointer, x, y)
        }
        self.ensure_status();
    }

    pub fn line_to(&self, x: f64, y: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_line_to(self.pointer, x, y)
        }
        self.ensure_status();
    }

    pub fn curve_to(&self, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_curve_to(self.pointer, x1, y1, x2, y2, x3, y3)
        }
        self.ensure_status();
    }

    pub fn set_control_point(&self, corner: MeshCorner, x: f64, y: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_set_control_point(self.pointer, corner as c_uint, x, y)
        }
        self.ensure_status();
    }

    pub fn get_control_point(&self, patch_num: usize, corner: MeshCorner) -> (f64, f64) {
        let mut x: c_double = 0.0;
        let mut y: c_double = 0.0;

        let status = unsafe {
            ffi::cairo_mesh_pattern_get_control_point(self.pointer, patch_num as c_uint, corner as c_uint, &mut x, &mut y)
        };
        status.ensure_valid();
        (x, y)
    }

    pub fn set_corner_color_rgb(&self, corner: MeshCorner, red: f64, green: f64, blue: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_set_corner_color_rgb(self.pointer, corner as c_uint, red, green, blue)
        }
        self.ensure_status();
    }

    pub fn set_corner_color_rgba(&self, corner: MeshCorner, red: f64, green: f64, blue: f64, alpha: f64) {
        unsafe {
            ffi::cairo_mesh_pattern_set_corner_color_rgba(self.pointer, corner as c_uint, red, green, blue, alpha)
        }
        self.ensure_status();
    }

    pub fn get_corner_color_rgba(&self, patch_num: usize, corner: MeshCorner) -> (f64, f64, f64, f64) {
        let mut red: c_double = 0.0;
        let mut green: c_double = 0.0;
        let mut blue: c_double = 0.0;
        let mut alpha: c_double = 0.0;

        let status = unsafe {
            ffi::cairo_mesh_pattern_get_corner_color_rgba(self.pointer, patch_num as c_uint, corner as c_uint, &mut red, &mut green, &mut blue, &mut alpha)
        };
        status.ensure_valid();
        (red, green, blue, alpha)
    }

    pub fn get_patch_count(&self) -> usize {
        let mut count: c_uint = 0;
        unsafe {
            ffi::cairo_mesh_pattern_get_patch_count(self.pointer, &mut count).ensure_valid();
        }
        count as usize
    }

    pub fn get_path(&self, patch_num: usize) -> Path {
        let path: Path = Path::wrap(unsafe {
            ffi::cairo_mesh_pattern_get_path(self.pointer, patch_num as c_uint)
        });
        path.ensure_status();
        path
    }
}
<|endoftext|>


<commit_before>use std::io::{BufReader, BufRead};
use std::str::FromStr;
use std::fs::File;
use std::cmp;
use tar::Archive;
use zigzag::Zigzag;
use dfa::{Dfa, DfaState};

struct Move {
    x: u32,
    y: u32,
    p: f64 // probability
}

struct Pattern {
    p: f64, // priority (probability = p / sum(p))
    moves: Vec<Move>
}

struct Patterns {
    dfa: Dfa,
    patterns: Vec<Pattern>
}

impl Patterns {
    fn read_sizes<T: BufRead>(input: &mut T, s: &mut String) -> (u32, u32, u32) {
        s.clear();
        input.read_line(s).ok();
        let mut split = s.split(' ').fuse();
        let width = u32::from_str(split.next().expect("Invalid pattern format: expected width.")).expect("Invalid pattern format: width must be u32.");
        let height = u32::from_str(split.next().expect("Invalid pattern format: expected height.")).expect("Invalid pattern format: height must be u32.");
        let moves_count = u32::from_str(split.next().expect("Invalid pattern format: expected moves count.")).expect("Invalid pattern format: moves count must be u32.");
        (width, height, moves_count)
    }

    fn read_pattern<T: BufRead>(input: &mut T, s: &mut String, width: u32, height: u32) {
        for y in 0 .. height {
            input.read_line(s).ok();
        }
    }

    fn covering_zigzag_length(side_of_square: u32) -> u32 {
        let x = side_of_square / 2;
        8 * x * x - 13 * x + 6
    }

    fn build_dfa(width: u32, height: u32, pattern: u32, s: &str) -> Dfa {
        let center_x = width / 2;
        let center_y = height / 2;
        let zigzag_length = Patterns::covering_zigzag_length(cmp::max(width, height)) as usize;
        let mut states = Vec::with_capacity(zigzag_length + 1);
        let mut i = 0;
        for (shift_x, shift_y) in Zigzag::new().into_iter().take(zigzag_length) {
            i += 1;
            let x = center_x as i32 + shift_x;
            let y = center_y as i32 + shift_y;
            let state = if x >= 0 && x < width as i32 && y >= 0 && y < height as i32 {
                let pos = y as u32 * width + x as u32;
                match s.char_at(pos as usize) {
                    '.' => DfaState::new(i, -1, -1, -1, -1),
                    '?' => DfaState::new(i, i, i, i, -1),
                    'R' => DfaState::new(-1, i, -1, -1, -1),
                    'B' => DfaState::new(-1, -1, i, -1, -1),
                    'r' => DfaState::new(i, i, -1, -1, -1),
                    'b' => DfaState::new(i, -1, i, -1, -1),
                    '*' => DfaState::new(-1, -1, -1, i, -1),
                    c   => panic!("Invalid character in pattern: {}", c)
                }

            } else {
                DfaState::new(-1, -1, -1, -1, -1)
            };
            states.push(state);
        }
        states.push(DfaState::new(-1, -1, -1, -1, pattern as i32));
        Dfa::new(states)
    }

    pub fn load(file: File) -> Patterns {
        let archive = Archive::new(file);
        let mut s = String::new();
        for file in archive.files().expect("Reading of tar archive is failed.").into_iter().map(|file| file.expect("Reading of file in tar archive is failed.")) {
            let mut input = BufReader::new(file);
            let (width, height, moves_count) = Patterns::read_sizes(&mut input, &mut s);
        }
        unimplemented!()
    }
}
<commit_msg>Small fix.<commit_after>use std::io::{BufReader, BufRead};
use std::str::FromStr;
use std::fs::File;
use std::cmp;
use tar::Archive;
use zigzag::Zigzag;
use dfa::{Dfa, DfaState};

struct Move {
    x: u32,
    y: u32,
    p: f64 // probability
}

struct Pattern {
    p: f64, // priority (probability = p / sum(p))
    moves: Vec<Move>
}

struct Patterns {
    dfa: Dfa,
    patterns: Vec<Pattern>
}

impl Patterns {
    fn read_sizes<T: BufRead>(input: &mut T, s: &mut String) -> (u32, u32, u32) {
        s.clear();
        input.read_line(s).ok();
        let mut split = s.split(' ').fuse();
        let width = u32::from_str(split.next().expect("Invalid pattern format: expected width.")).expect("Invalid pattern format: width must be u32.");
        let height = u32::from_str(split.next().expect("Invalid pattern format: expected height.")).expect("Invalid pattern format: height must be u32.");
        let moves_count = u32::from_str(split.next().expect("Invalid pattern format: expected moves count.")).expect("Invalid pattern format: moves count must be u32.");
        (width, height, moves_count)
    }

    fn read_pattern<T: BufRead>(input: &mut T, s: &mut String, width: u32, height: u32) {
        for y in 0 .. height {
            input.read_line(s).ok();
        }
    }

    fn covering_zigzag_length(side_of_square: u32) -> u32 {
        let x = side_of_square / 2;
        (8 * x - 13) * x + 6
    }

    fn build_dfa(width: u32, height: u32, pattern: u32, s: &str) -> Dfa {
        let center_x = width / 2;
        let center_y = height / 2;
        let zigzag_length = Patterns::covering_zigzag_length(cmp::max(width, height)) as usize;
        let mut states = Vec::with_capacity(zigzag_length + 1);
        let mut i = 0;
        for (shift_x, shift_y) in Zigzag::new().into_iter().take(zigzag_length) {
            i += 1;
            let x = center_x as i32 + shift_x;
            let y = center_y as i32 + shift_y;
            let state = if x >= 0 && x < width as i32 && y >= 0 && y < height as i32 {
                let pos = y as u32 * width + x as u32;
                match s.char_at(pos as usize) {
                    '.' => DfaState::new(i, -1, -1, -1, -1),
                    '?' => DfaState::new(i, i, i, i, -1),
                    'R' => DfaState::new(-1, i, -1, -1, -1),
                    'B' => DfaState::new(-1, -1, i, -1, -1),
                    'r' => DfaState::new(i, i, -1, -1, -1),
                    'b' => DfaState::new(i, -1, i, -1, -1),
                    '*' => DfaState::new(-1, -1, -1, i, -1),
                    c   => panic!("Invalid character in pattern: {}", c)
                }

            } else {
                DfaState::new(-1, -1, -1, -1, -1)
            };
            states.push(state);
        }
        states.push(DfaState::new(-1, -1, -1, -1, pattern as i32));
        Dfa::new(states)
    }

    pub fn load(file: File) -> Patterns {
        let archive = Archive::new(file);
        let mut s = String::new();
        for file in archive.files().expect("Reading of tar archive is failed.").into_iter().map(|file| file.expect("Reading of file in tar archive is failed.")) {
            let mut input = BufReader::new(file);
            let (width, height, moves_count) = Patterns::read_sizes(&mut input, &mut s);
        }
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O> IResult<I,O> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O> GetInput<&'a[I]> for IResult<&'a[I],O> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<'a,O> GetInput<()> for IResult<(),O> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,O> GetOutput<&'a[O]> for IResult<I,&'a[O]> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<'a,I> GetOutput<()> for IResult<I,()> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

<commit_msg>GetInput and GetOutput implementations for &str parsers<commit_after>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O> IResult<I,O> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O> GetInput<&'a[I]> for IResult<&'a[I],O> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O> GetInput<()> for IResult<(),O> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O> GetInput<&'a str> for IResult<&'a str,O> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O> GetOutput<&'a[O]> for IResult<I,&'a[O]> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I> GetOutput<()> for IResult<I,()> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I> GetOutput<&'a str> for IResult<I,&'a str> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::vec::Vec;
use std::boxed::Box;

#[derive(Debug)]
pub struct QuadTree<T: Debug> {
    root: Node<T>
}

#[derive(Debug)]
enum Child<T: Sized + Debug> {
    Inner(Box<Node<T>>),
    Leaf(T)
}

impl<T: Debug> Child<T> {
    fn visit(&self) {
        match self {
            &Child::Leaf(ref t) => {
                println!("{:?}", t);
            },
            &Child::Inner(ref b) => {
                b.as_ref().visit();
            },
        }
    }
}

#[derive(Debug)]
struct Node<T: Sized + Debug> {
    children: Vec<Child<T>>
}

impl<T: Debug> Node<T> {

    fn new() -> Node<T> {
        return Node {
            children: Vec::with_capacity(4)
        };
    }

    fn visit(&self) {
        for i in 0..4 {
            match self.children.get(i) {
                Some(c) => c.visit(),
                None => println!("None")
            };
        };
    }

    fn add(&mut self, t: T) {
        if self.children.len() < 4 {
            self.children.push(Child::Leaf(t));
        } else {
            match self.children.pop().unwrap() {
                Child::Leaf(old_t) => {
                    let mut new_node = Node::new();
                    new_node.add(t);
                    new_node.add(old_t);
                    self.children.push(Child::Inner(Box::new(new_node)));
                },
                Child::Inner(b) => {

                }
            }
        }
    }
}

impl<T: Debug> QuadTree<T> {
    pub fn new(span: PosSpan) -> QuadTree<T> {
        return QuadTree { root: Node::new() };
    }

    pub fn visit(&self) {
        // println!("{:?}", self.root);
        self.root.visit();
    }

    pub fn add(&mut self, t: T) {
        self.root.add(t);
    }
}

pub enum Dir { N, S, E, W, NE, NW, SE, SW }

#[derive(Debug, PartialEq, Eq)]
pub struct Position {
    pub x: i32,
    pub y: i32
}

#[derive(Debug, PartialEq, Eq)]
pub struct PosSpan {
    pub nw: Position,
    pub width: i32,
    pub height: i32
}

impl PosSpan {
// impl<Position> Span<Position> for PosSpan {
    fn dir_of(&self, t: &Position) -> Option<Dir> {
        if t.x < self.nw.x {
            if t.y < self.nw.y {
                return Some(Dir::NW);
            } else if t.y < self.nw.y + self.height {
                return Some(Dir::W);
            } else {
                return Some(Dir::SW);
            }
        } else if t.x < self.nw.x + self.width {
            if t.y < self.nw.y {
                return Some(Dir::N);
            } else if t.y < self.nw.y + self.height {
                return None;
            } else {
                return Some(Dir::S);
            }
        } else {
            if t.y < self.nw.y {
                return Some(Dir::NE);
            } else if t.y < self.nw.y + self.height {
                return Some(Dir::E);
            } else {
                return Some(Dir::SE);
            }
        }
    }

    // fn split(self) -> Vec<PosSpan> {

    // }
}

// pub trait Span<T> {
//     fn dir_of(&self, t: &T) -> Option<Dir>;
//     // fn north_span(&self) -> Span<T>;
//     // fn south_span(&self) -> Span<T>;
//     // fn east_span(&self) -> Span<T>;
//     // fn west_span(&self) -> Span<T>;
// }

<commit_msg>fixed generic span<commit_after>use std::fmt::Debug;
use std::vec::Vec;
use std::boxed::Box;

#[derive(Debug)]
pub struct QuadTree<T: Debug> {
    root: Node<T>
}

#[derive(Debug)]
enum Child<T: Sized + Debug> {
    Inner(Box<Node<T>>),
    Leaf(T)
}

impl<T: Debug> Child<T> {
    fn visit(&self) {
        match self {
            &Child::Leaf(ref t) => {
                println!("{:?}", t);
            },
            &Child::Inner(ref b) => {
                b.as_ref().visit();
            },
        }
    }
}

#[derive(Debug)]
struct Node<T: Sized + Debug> {
    children: Vec<Child<T>>
}

impl<T: Debug> Node<T> {

    fn new() -> Node<T> {
        return Node {
            children: Vec::with_capacity(4)
        };
    }

    fn visit(&self) {
        for i in 0..4 {
            match self.children.get(i) {
                Some(c) => c.visit(),
                None => println!("None")
            };
        };
    }

    fn add(&mut self, t: T) {
        if self.children.len() < 4 {
            self.children.push(Child::Leaf(t));
        } else {
            match self.children.pop().unwrap() {
                Child::Leaf(old_t) => {
                    let mut new_node = Node::new();
                    new_node.add(t);
                    new_node.add(old_t);
                    self.children.push(Child::Inner(Box::new(new_node)));
                },
                Child::Inner(b) => {

                }
            }
        }
    }
}

impl<T: Debug> QuadTree<T> {
    pub fn new(span: PosSpan) -> QuadTree<T> {
        return QuadTree { root: Node::new() };
    }

    pub fn visit(&self) {
        // println!("{:?}", self.root);
        self.root.visit();
    }

    pub fn add(&mut self, t: T) {
        self.root.add(t);
    }
}

pub enum Dir { N, S, E, W, NE, NW, SE, SW }

#[derive(Debug, PartialEq, Eq)]
pub struct Position {
    pub x: i32,
    pub y: i32
}

#[derive(Debug, PartialEq, Eq)]
pub struct PosSpan {
    pub nw: Position,
    pub width: i32,
    pub height: i32
}

impl Span<Position> for PosSpan {
    fn dir_of(&self, t: &Position) -> Option<Dir> {
        if t.x < self.nw.x {
            if t.y < self.nw.y {
                return Some(Dir::NW);
            } else if t.y < self.nw.y + self.height {
                return Some(Dir::W);
            } else {
                return Some(Dir::SW);
            }
        } else if t.x < self.nw.x + self.width {
            if t.y < self.nw.y {
                return Some(Dir::N);
            } else if t.y < self.nw.y + self.height {
                return None;
            } else {
                return Some(Dir::S);
            }
        } else {
            if t.y < self.nw.y {
                return Some(Dir::NE);
            } else if t.y < self.nw.y + self.height {
                return Some(Dir::E);
            } else {
                return Some(Dir::SE);
            }
        }
    }

    // fn split(self) -> Vec<PosSpan> {

    // }
}

pub trait Span<T> {
    fn dir_of(&self, t: &T) -> Option<Dir>;
    // fn north_span(&self) -> Span<T>;
    // fn south_span(&self) -> Span<T>;
    // fn east_span(&self) -> Span<T>;
    // fn west_span(&self) -> Span<T>;
}

<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright 2015 The etcd 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.

use raft::errors::{Result, Error};
use raft::Storage;
use protobuf::{self, RepeatedField};
use kvproto::eraftpb::{HardState, Entry, EntryType, Message, Snapshot, MessageType, ConfChange,
                       ConfChangeType, ConfState};
use raft::raft::{Config, Raft, SoftState, INVALID_ID};
use raft::Status;
use raft::read_only::ReadState;

#[derive(Debug, Default)]
pub struct Peer {
    pub id: u64,
    pub context: Option<Vec<u8>>,
}

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SnapshotStatus {
    Finish,
    Failure,
}

fn is_local_msg(t: MessageType) -> bool {
    match t {
        MessageType::MsgHup |
        MessageType::MsgBeat |
        MessageType::MsgUnreachable |
        MessageType::MsgSnapStatus |
        MessageType::MsgCheckQuorum => true,
        _ => false,
    }
}

fn is_response_msg(t: MessageType) -> bool {
    match t {
        MessageType::MsgAppendResponse |
        MessageType::MsgRequestVoteResponse |
        MessageType::MsgHeartbeatResponse |
        MessageType::MsgUnreachable |
        MessageType::MsgRequestPreVoteResponse => true,
        _ => false,
    }
}

pub fn is_empty_snap(s: &Snapshot) -> bool {
    s.get_metadata().get_index() == 0
}

// Ready encapsulates the entries and messages that are ready to read,
// be saved to stable storage, committed or sent to other peers.
// All fields in Ready are read-only.
#[derive(Default, Debug, PartialEq)]
pub struct Ready {
    // The current volatile state of a Node.
    // SoftState will be nil if there is no update.
    // It is not required to consume or store SoftState.
    pub ss: Option<SoftState>,

    // The current state of a Node to be saved to stable storage BEFORE
    // Messages are sent.
    // HardState will be equal to empty state if there is no update.
    pub hs: Option<HardState>,

    // read_states states can be used for node to serve linearizable read requests locally
    // when its applied index is greater than the index in ReadState.
    // Note that the read_state will be returned when raft receives MsgReadIndex.
    // The returned is only valid for the request that requested to read.
    pub read_states: Vec<ReadState>,

    // Entries specifies entries to be saved to stable storage BEFORE
    // Messages are sent.
    pub entries: Vec<Entry>,

    // Snapshot specifies the snapshot to be saved to stable storage.
    pub snapshot: Snapshot,

    // CommittedEntries specifies entries to be committed to a
    // store/state-machine. These have previously been committed to stable
    // store.
    pub committed_entries: Vec<Entry>,

    // Messages specifies outbound messages to be sent AFTER Entries are
    // committed to stable storage.
    // If it contains a MsgSnap message, the application MUST report back to raft
    // when the snapshot has been received or has failed by calling ReportSnapshot.
    pub messages: Vec<Message>,
}

impl Ready {
    fn new<T: Storage>(raft: &mut Raft<T>, prev_ss: &SoftState, prev_hs: &HardState) -> Ready {
        let mut rd = Ready {
            entries: raft.raft_log.unstable_entries().unwrap_or(&[]).to_vec(),
            committed_entries: raft.raft_log.next_entries().unwrap_or_else(Vec::new),
            messages: raft.msgs.drain(..).collect(),
            ..Default::default()
        };
        let ss = raft.soft_state();
        if &ss != prev_ss {
            rd.ss = Some(ss);
        }
        let hs = raft.hard_state();
        if &hs != prev_hs {
            rd.hs = Some(hs);
        }
        if raft.raft_log.get_unstable().snapshot.is_some() {
            rd.snapshot = raft.raft_log.get_unstable().snapshot.clone().unwrap();
        }
        if !raft.read_states.is_empty() {
            rd.read_states = raft.read_states.clone();
        }
        rd
    }
}

// RawNode is a thread-unsafe Node.
// The methods of this struct correspond to the methods of Node and are described
// more fully there.
pub struct RawNode<T: Storage> {
    pub raft: Raft<T>,
    prev_ss: SoftState,
    prev_hs: HardState,
}

impl<T: Storage> RawNode<T> {
    // NewRawNode returns a new RawNode given configuration and a list of raft peers.
    pub fn new(config: &Config, store: T, peers: &[Peer]) -> Result<RawNode<T>> {
        assert!(config.id != 0, "config.id must not be zero");
        let r = Raft::new(config, store);
        let mut rn = RawNode {
            raft: r,
            prev_hs: Default::default(),
            prev_ss: Default::default(),
        };
        let last_index = rn.raft.get_store().last_index().expect("");
        if last_index == 0 {
            rn.raft.become_follower(1, INVALID_ID);
            let mut ents = Vec::with_capacity(peers.len());
            for (i, peer) in peers.iter().enumerate() {
                let mut cc = ConfChange::new();
                cc.set_change_type(ConfChangeType::AddNode);
                cc.set_node_id(peer.id);
                if peer.context.is_some() {
                    cc.set_context(peer.context.as_ref().unwrap().clone());
                }
                let data = protobuf::Message::write_to_bytes(&cc)
                    .expect("unexpected marshal error");
                let mut e = Entry::new();
                e.set_entry_type(EntryType::EntryConfChange);
                e.set_term(1);
                e.set_index(i as u64 + 1);
                e.set_data(data);
                ents.push(e);
            }
            rn.raft.raft_log.append(&ents);
            rn.raft.raft_log.committed = ents.len() as u64;
            for peer in peers {
                rn.raft.add_node(peer.id);
            }
        }
        rn.prev_ss = rn.raft.soft_state();
        if last_index == 0 {
            rn.prev_hs = Default::default();
        } else {
            rn.prev_hs = rn.raft.hard_state();
        }
        Ok(rn)
    }

    fn commit_ready(&mut self, rd: Ready) {
        if rd.ss.is_some() {
            self.prev_ss = rd.ss.unwrap();
        }
        if let Some(e) = rd.hs {
            if e != HardState::new() {
                self.prev_hs = e;
            }
        }
        if self.prev_hs.get_commit() != 0 {
            // In most cases, prevHardSt and rd.HardState will be the same
            // because when there are new entries to apply we just sent a
            // HardState with an updated Commit value. However, on initial
            // startup the two are different because we don't send a HardState
            // until something changes, but we do send any un-applied but
            // committed entries (and previously-committed entries may be
            // incorporated into the snapshot, even if rd.CommittedEntries is
            // empty). Therefore we mark all committed entries as applied
            // whether they were included in rd.HardState or not.
            self.raft.raft_log.applied_to(self.prev_hs.get_commit());
        }
        if !rd.entries.is_empty() {
            let e = rd.entries.last().unwrap();
            self.raft.raft_log.stable_to(e.get_index(), e.get_term());
        }
        if rd.snapshot != Snapshot::new() {
            self.raft.raft_log.stable_snap_to(rd.snapshot.get_metadata().get_index());
        }
        if !rd.read_states.is_empty() {
            self.raft.read_states.clear();
        }
    }

    // Tick advances the internal logical clock by a single tick.
    pub fn tick(&mut self) {
        self.raft.tick();
    }

    // Campaign causes this RawNode to transition to candidate state.
    pub fn campaign(&mut self) -> Result<()> {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgHup);
        self.raft.step(m)
    }

    // Propose proposes data be appended to the raft log.
    pub fn propose(&mut self, data: Vec<u8>) -> Result<()> {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgPropose);
        m.set_from(self.raft.id);
        let mut e = Entry::new();
        e.set_data(data);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m)
    }

    // ProposeConfChange proposes a config change.
    pub fn propose_conf_change(&mut self, cc: ConfChange) -> Result<()> {
        let data = box_try!(protobuf::Message::write_to_bytes(&cc));
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgPropose);
        let mut e = Entry::new();
        e.set_entry_type(EntryType::EntryConfChange);
        e.set_data(data);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m)
    }

    pub fn apply_conf_change(&mut self, cc: ConfChange) -> ConfState {
        if cc.get_node_id() == INVALID_ID {
            self.raft.reset_pending_conf();
            let mut cs = ConfState::new();
            cs.set_nodes(self.raft.nodes());
            return cs;
        }
        let nid = cc.get_node_id();
        assert!(cc.has_change_type(), "unexpected conf type");
        match cc.get_change_type() {
            ConfChangeType::AddNode => self.raft.add_node(nid),
            ConfChangeType::RemoveNode => self.raft.remove_node(nid),
        }
        let mut cs = ConfState::new();
        cs.set_nodes(self.raft.nodes());
        cs
    }

    // Step advances the state machine using the given message.
    pub fn step(&mut self, m: Message) -> Result<()> {
        // ignore unexpected local messages receiving over network
        if is_local_msg(m.get_msg_type()) {
            return Err(Error::StepLocalMsg);
        }
        if self.raft.prs.contains_key(&m.get_from()) || !is_response_msg(m.get_msg_type()) {
            return self.raft.step(m);
        }
        Err(Error::StepPeerNotFound)
    }

    // Ready returns the current point-in-time state of this RawNode.
    pub fn ready(&mut self) -> Ready {
        Ready::new(&mut self.raft, &self.prev_ss, &self.prev_hs)
    }

    // HasReady called when RawNode user need to check if any Ready pending.
    // Checking logic in this method should be consistent with Ready.containsUpdates().
    pub fn has_ready(&self) -> bool {
        let raft = &self.raft;
        if raft.soft_state() != self.prev_ss {
            return true;
        }
        let hs = raft.hard_state();
        if hs != HardState::new() && hs != self.prev_hs {
            return true;
        }
        if self.get_snap().map_or(false, |s| !is_empty_snap(s)) {
            return true;
        }
        if !raft.msgs.is_empty() || raft.raft_log.unstable_entries().is_some() ||
           raft.raft_log.has_next_entries() {
            return true;
        }
        if !raft.read_states.is_empty() {
            return true;
        }
        false
    }

    #[inline]
    pub fn get_snap(&self) -> Option<&Snapshot> {
        self.raft.get_snap()
    }

    // Advance notifies the RawNode that the application has applied and saved progress in the
    // last Ready results.
    pub fn advance(&mut self, rd: Ready) {
        self.commit_ready(rd);
    }

    // Status returns the current status of the given group.
    pub fn status(&self) -> Status {
        Status::new(&self.raft)
    }

    // ReportUnreachable reports the given node is not reachable for the last send.
    pub fn report_unreachable(&mut self, id: u64) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgUnreachable);
        m.set_from(id);
        // we don't care if it is ok actually
        self.raft.step(m).is_ok();
    }

    // ReportSnapshot reports the status of the sent snapshot.
    pub fn report_snapshot(&mut self, id: u64, status: SnapshotStatus) {
        let rej = status == SnapshotStatus::Failure;
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgSnapStatus);
        m.set_from(id);
        m.set_reject(rej);
        // we don't care if it is ok actually
        self.raft.step(m).is_ok();
    }

    // TransferLeader tries to transfer leadership to the given transferee.
    pub fn transfer_leader(&mut self, transferee: u64) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgTransferLeader);
        m.set_from(transferee);
        self.raft.step(m).is_ok();
    }

    // ReadIndex requests a read state. The read state will be set in ready.
    // Read State has a read index. Once the application advances further than the read
    // index, any linearizable read requests issued before the read request can be
    // processed safely. The read state will have the same rctx attched.
    pub fn read_index(&mut self, rctx: Vec<u8>) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgReadIndex);
        let mut e = Entry::new();
        e.set_data(rctx);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m).is_ok();
    }

    #[inline]
    pub fn get_store(&self) -> &T {
        self.raft.get_store()
    }

    #[inline]
    pub fn mut_store(&mut self) -> &mut T {
        self.raft.mut_store()
    }
}

#[cfg(test)]
mod test {
    use kvproto::eraftpb::MessageType;
    use super::is_local_msg;

    #[test]
    fn test_is_local_msg() {
        let tests = vec![(MessageType::MsgHup, true),
                         (MessageType::MsgBeat, true),
                         (MessageType::MsgUnreachable, true),
                         (MessageType::MsgSnapStatus, true),
                         (MessageType::MsgCheckQuorum, true),
                         (MessageType::MsgPropose, false),
                         (MessageType::MsgAppend, false),
                         (MessageType::MsgAppendResponse, false),
                         (MessageType::MsgRequestVote, false),
                         (MessageType::MsgRequestVoteResponse, false),
                         (MessageType::MsgSnapshot, false),
                         (MessageType::MsgHeartbeat, false),
                         (MessageType::MsgHeartbeatResponse, false),
                         (MessageType::MsgTransferLeader, false),
                         (MessageType::MsgTimeoutNow, false),
                         (MessageType::MsgReadIndex, false),
                         (MessageType::MsgReadIndexResp, false),
                         (MessageType::MsgRequestPreVote, false),
                         (MessageType::MsgRequestPreVoteResponse, false)];
        for (msg_type, result) in tests {
            assert_eq!(is_local_msg(msg_type), result);
        }
    }
}
<commit_msg>raftstore: tiny refactor (#1533)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright 2015 The etcd 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.

use raft::errors::{Result, Error};
use raft::Storage;
use protobuf::{self, RepeatedField};
use kvproto::eraftpb::{HardState, Entry, EntryType, Message, Snapshot, MessageType, ConfChange,
                       ConfChangeType, ConfState};
use raft::raft::{Config, Raft, SoftState, INVALID_ID};
use raft::Status;
use raft::read_only::ReadState;

#[derive(Debug, Default)]
pub struct Peer {
    pub id: u64,
    pub context: Option<Vec<u8>>,
}

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SnapshotStatus {
    Finish,
    Failure,
}

fn is_local_msg(t: MessageType) -> bool {
    match t {
        MessageType::MsgHup |
        MessageType::MsgBeat |
        MessageType::MsgUnreachable |
        MessageType::MsgSnapStatus |
        MessageType::MsgCheckQuorum => true,
        _ => false,
    }
}

fn is_response_msg(t: MessageType) -> bool {
    match t {
        MessageType::MsgAppendResponse |
        MessageType::MsgRequestVoteResponse |
        MessageType::MsgHeartbeatResponse |
        MessageType::MsgUnreachable |
        MessageType::MsgRequestPreVoteResponse => true,
        _ => false,
    }
}

pub fn is_empty_snap(s: &Snapshot) -> bool {
    s.get_metadata().get_index() == 0
}

// Ready encapsulates the entries and messages that are ready to read,
// be saved to stable storage, committed or sent to other peers.
// All fields in Ready are read-only.
#[derive(Default, Debug, PartialEq)]
pub struct Ready {
    // The current volatile state of a Node.
    // SoftState will be nil if there is no update.
    // It is not required to consume or store SoftState.
    pub ss: Option<SoftState>,

    // The current state of a Node to be saved to stable storage BEFORE
    // Messages are sent.
    // HardState will be equal to empty state if there is no update.
    pub hs: Option<HardState>,

    // read_states states can be used for node to serve linearizable read requests locally
    // when its applied index is greater than the index in ReadState.
    // Note that the read_state will be returned when raft receives MsgReadIndex.
    // The returned is only valid for the request that requested to read.
    pub read_states: Vec<ReadState>,

    // Entries specifies entries to be saved to stable storage BEFORE
    // Messages are sent.
    pub entries: Vec<Entry>,

    // Snapshot specifies the snapshot to be saved to stable storage.
    pub snapshot: Snapshot,

    // CommittedEntries specifies entries to be committed to a
    // store/state-machine. These have previously been committed to stable
    // store.
    pub committed_entries: Option<Vec<Entry>>,

    // Messages specifies outbound messages to be sent AFTER Entries are
    // committed to stable storage.
    // If it contains a MsgSnap message, the application MUST report back to raft
    // when the snapshot has been received or has failed by calling ReportSnapshot.
    pub messages: Vec<Message>,
}

impl Ready {
    fn new<T: Storage>(raft: &mut Raft<T>, prev_ss: &SoftState, prev_hs: &HardState) -> Ready {
        let mut rd = Ready {
            entries: raft.raft_log.unstable_entries().unwrap_or(&[]).to_vec(),
            committed_entries: Some(raft.raft_log.next_entries().unwrap_or_else(Vec::new)),
            messages: raft.msgs.drain(..).collect(),
            ..Default::default()
        };
        let ss = raft.soft_state();
        if &ss != prev_ss {
            rd.ss = Some(ss);
        }
        let hs = raft.hard_state();
        if &hs != prev_hs {
            rd.hs = Some(hs);
        }
        if raft.raft_log.get_unstable().snapshot.is_some() {
            rd.snapshot = raft.raft_log.get_unstable().snapshot.clone().unwrap();
        }
        if !raft.read_states.is_empty() {
            rd.read_states = raft.read_states.clone();
        }
        rd
    }
}

// RawNode is a thread-unsafe Node.
// The methods of this struct correspond to the methods of Node and are described
// more fully there.
pub struct RawNode<T: Storage> {
    pub raft: Raft<T>,
    prev_ss: SoftState,
    prev_hs: HardState,
}

impl<T: Storage> RawNode<T> {
    // NewRawNode returns a new RawNode given configuration and a list of raft peers.
    pub fn new(config: &Config, store: T, peers: &[Peer]) -> Result<RawNode<T>> {
        assert!(config.id != 0, "config.id must not be zero");
        let r = Raft::new(config, store);
        let mut rn = RawNode {
            raft: r,
            prev_hs: Default::default(),
            prev_ss: Default::default(),
        };
        let last_index = rn.raft.get_store().last_index().expect("");
        if last_index == 0 {
            rn.raft.become_follower(1, INVALID_ID);
            let mut ents = Vec::with_capacity(peers.len());
            for (i, peer) in peers.iter().enumerate() {
                let mut cc = ConfChange::new();
                cc.set_change_type(ConfChangeType::AddNode);
                cc.set_node_id(peer.id);
                if peer.context.is_some() {
                    cc.set_context(peer.context.as_ref().unwrap().clone());
                }
                let data = protobuf::Message::write_to_bytes(&cc)
                    .expect("unexpected marshal error");
                let mut e = Entry::new();
                e.set_entry_type(EntryType::EntryConfChange);
                e.set_term(1);
                e.set_index(i as u64 + 1);
                e.set_data(data);
                ents.push(e);
            }
            rn.raft.raft_log.append(&ents);
            rn.raft.raft_log.committed = ents.len() as u64;
            for peer in peers {
                rn.raft.add_node(peer.id);
            }
        }
        rn.prev_ss = rn.raft.soft_state();
        if last_index == 0 {
            rn.prev_hs = Default::default();
        } else {
            rn.prev_hs = rn.raft.hard_state();
        }
        Ok(rn)
    }

    fn commit_ready(&mut self, rd: Ready) {
        if rd.ss.is_some() {
            self.prev_ss = rd.ss.unwrap();
        }
        if let Some(e) = rd.hs {
            if e != HardState::new() {
                self.prev_hs = e;
            }
        }
        if self.prev_hs.get_commit() != 0 {
            // In most cases, prevHardSt and rd.HardState will be the same
            // because when there are new entries to apply we just sent a
            // HardState with an updated Commit value. However, on initial
            // startup the two are different because we don't send a HardState
            // until something changes, but we do send any un-applied but
            // committed entries (and previously-committed entries may be
            // incorporated into the snapshot, even if rd.CommittedEntries is
            // empty). Therefore we mark all committed entries as applied
            // whether they were included in rd.HardState or not.
            self.raft.raft_log.applied_to(self.prev_hs.get_commit());
        }
        if !rd.entries.is_empty() {
            let e = rd.entries.last().unwrap();
            self.raft.raft_log.stable_to(e.get_index(), e.get_term());
        }
        if rd.snapshot != Snapshot::new() {
            self.raft.raft_log.stable_snap_to(rd.snapshot.get_metadata().get_index());
        }
        if !rd.read_states.is_empty() {
            self.raft.read_states.clear();
        }
    }

    // Tick advances the internal logical clock by a single tick.
    pub fn tick(&mut self) {
        self.raft.tick();
    }

    // Campaign causes this RawNode to transition to candidate state.
    pub fn campaign(&mut self) -> Result<()> {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgHup);
        self.raft.step(m)
    }

    // Propose proposes data be appended to the raft log.
    pub fn propose(&mut self, data: Vec<u8>) -> Result<()> {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgPropose);
        m.set_from(self.raft.id);
        let mut e = Entry::new();
        e.set_data(data);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m)
    }

    // ProposeConfChange proposes a config change.
    pub fn propose_conf_change(&mut self, cc: ConfChange) -> Result<()> {
        let data = box_try!(protobuf::Message::write_to_bytes(&cc));
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgPropose);
        let mut e = Entry::new();
        e.set_entry_type(EntryType::EntryConfChange);
        e.set_data(data);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m)
    }

    pub fn apply_conf_change(&mut self, cc: ConfChange) -> ConfState {
        if cc.get_node_id() == INVALID_ID {
            self.raft.reset_pending_conf();
            let mut cs = ConfState::new();
            cs.set_nodes(self.raft.nodes());
            return cs;
        }
        let nid = cc.get_node_id();
        assert!(cc.has_change_type(), "unexpected conf type");
        match cc.get_change_type() {
            ConfChangeType::AddNode => self.raft.add_node(nid),
            ConfChangeType::RemoveNode => self.raft.remove_node(nid),
        }
        let mut cs = ConfState::new();
        cs.set_nodes(self.raft.nodes());
        cs
    }

    // Step advances the state machine using the given message.
    pub fn step(&mut self, m: Message) -> Result<()> {
        // ignore unexpected local messages receiving over network
        if is_local_msg(m.get_msg_type()) {
            return Err(Error::StepLocalMsg);
        }
        if self.raft.prs.contains_key(&m.get_from()) || !is_response_msg(m.get_msg_type()) {
            return self.raft.step(m);
        }
        Err(Error::StepPeerNotFound)
    }

    // Ready returns the current point-in-time state of this RawNode.
    pub fn ready(&mut self) -> Ready {
        Ready::new(&mut self.raft, &self.prev_ss, &self.prev_hs)
    }

    // HasReady called when RawNode user need to check if any Ready pending.
    // Checking logic in this method should be consistent with Ready.containsUpdates().
    pub fn has_ready(&self) -> bool {
        let raft = &self.raft;
        if raft.soft_state() != self.prev_ss {
            return true;
        }
        let hs = raft.hard_state();
        if hs != HardState::new() && hs != self.prev_hs {
            return true;
        }
        if self.get_snap().map_or(false, |s| !is_empty_snap(s)) {
            return true;
        }
        if !raft.msgs.is_empty() || raft.raft_log.unstable_entries().is_some() ||
           raft.raft_log.has_next_entries() {
            return true;
        }
        if !raft.read_states.is_empty() {
            return true;
        }
        false
    }

    #[inline]
    pub fn get_snap(&self) -> Option<&Snapshot> {
        self.raft.get_snap()
    }

    // Advance notifies the RawNode that the application has applied and saved progress in the
    // last Ready results.
    pub fn advance(&mut self, rd: Ready) {
        self.commit_ready(rd);
    }

    // Status returns the current status of the given group.
    pub fn status(&self) -> Status {
        Status::new(&self.raft)
    }

    // ReportUnreachable reports the given node is not reachable for the last send.
    pub fn report_unreachable(&mut self, id: u64) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgUnreachable);
        m.set_from(id);
        // we don't care if it is ok actually
        self.raft.step(m).is_ok();
    }

    // ReportSnapshot reports the status of the sent snapshot.
    pub fn report_snapshot(&mut self, id: u64, status: SnapshotStatus) {
        let rej = status == SnapshotStatus::Failure;
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgSnapStatus);
        m.set_from(id);
        m.set_reject(rej);
        // we don't care if it is ok actually
        self.raft.step(m).is_ok();
    }

    // TransferLeader tries to transfer leadership to the given transferee.
    pub fn transfer_leader(&mut self, transferee: u64) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgTransferLeader);
        m.set_from(transferee);
        self.raft.step(m).is_ok();
    }

    // ReadIndex requests a read state. The read state will be set in ready.
    // Read State has a read index. Once the application advances further than the read
    // index, any linearizable read requests issued before the read request can be
    // processed safely. The read state will have the same rctx attched.
    pub fn read_index(&mut self, rctx: Vec<u8>) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgReadIndex);
        let mut e = Entry::new();
        e.set_data(rctx);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m).is_ok();
    }

    #[inline]
    pub fn get_store(&self) -> &T {
        self.raft.get_store()
    }

    #[inline]
    pub fn mut_store(&mut self) -> &mut T {
        self.raft.mut_store()
    }
}

#[cfg(test)]
mod test {
    use kvproto::eraftpb::MessageType;
    use super::is_local_msg;

    #[test]
    fn test_is_local_msg() {
        let tests = vec![(MessageType::MsgHup, true),
                         (MessageType::MsgBeat, true),
                         (MessageType::MsgUnreachable, true),
                         (MessageType::MsgSnapStatus, true),
                         (MessageType::MsgCheckQuorum, true),
                         (MessageType::MsgPropose, false),
                         (MessageType::MsgAppend, false),
                         (MessageType::MsgAppendResponse, false),
                         (MessageType::MsgRequestVote, false),
                         (MessageType::MsgRequestVoteResponse, false),
                         (MessageType::MsgSnapshot, false),
                         (MessageType::MsgHeartbeat, false),
                         (MessageType::MsgHeartbeatResponse, false),
                         (MessageType::MsgTransferLeader, false),
                         (MessageType::MsgTimeoutNow, false),
                         (MessageType::MsgReadIndex, false),
                         (MessageType::MsgReadIndexResp, false),
                         (MessageType::MsgRequestPreVote, false),
                         (MessageType::MsgRequestPreVoteResponse, false)];
        for (msg_type, result) in tests {
            assert_eq!(is_local_msg(msg_type), result);
        }
    }
}
<|endoftext|>