<commit_before>#![allow(non_camel_case_types)]
#![allow(dead_code)]

#[derive(Copy,Clone)]
pub enum PartitionType {
    PARTITION_NONE,
    PARTITION_HORZ,
    PARTITION_VERT,
    PARTITION_SPLIT
}

#[derive(Copy,Clone)]
pub enum BlockSize {
    BLOCK_4X4,
    BLOCK_4X8,
    BLOCK_8X4,
    BLOCK_8X8,
    BLOCK_8X16,
    BLOCK_16X8,
    BLOCK_16X16,
    BLOCK_16X32,
    BLOCK_32X16,
    BLOCK_32X32,
    BLOCK_32X64,
    BLOCK_64X32,
    BLOCK_64X64,
    BLOCK_4X16,
    BLOCK_16X4,
    BLOCK_8X32,
    BLOCK_32X8
}

pub const TX_SIZES: usize = 4;
pub const TX_SIZES_ALL: usize = 14;

#[derive(Copy,Clone,PartialEq,PartialOrd)]
pub enum TxSize {
    TX_4X4,
    TX_8X8,
    TX_16X16,
    TX_32X32,
    TX_4X8,
    TX_8X4,
    TX_8X16,
    TX_16X8,
    TX_16X32,
    TX_32X16,
    TX_4X16,
    TX_16X4,
    TX_8X32,
    TX_32X8,
}

pub const TX_TYPES: usize = 16;

#[derive(Copy,Clone)]
#[repr(C)]
pub enum TxType {
    DCT_DCT = 0,    // DCT  in both horizontal and vertical
    ADST_DCT = 1,   // ADST in vertical, DCT in horizontal
    DCT_ADST = 2,   // DCT  in vertical, ADST in horizontal
    ADST_ADST = 3,  // ADST in both directions
    FLIPADST_DCT = 4,
    DCT_FLIPADST = 5,
    FLIPADST_FLIPADST = 6,
    ADST_FLIPADST = 7,
    FLIPADST_ADST = 8,
    IDTX = 9,
    V_DCT = 10,
    H_DCT = 11,
    V_ADST = 12,
    H_ADST = 13,
    V_FLIPADST = 14,
    H_FLIPADST = 15,
}

#[derive(Copy,Clone,Debug)]
pub enum PredictionMode {
  DC_PRED,    // Average of above and left pixels
  V_PRED,     // Vertical
  H_PRED,     // Horizontal
  D45_PRED,   // Directional 45  deg = round(arctan(1/1) * 180/pi)
  D135_PRED,  // Directional 135 deg = 180 - 45
  D117_PRED,  // Directional 117 deg = 180 - 63
  D153_PRED,  // Directional 153 deg = 180 - 27
  D207_PRED,  // Directional 207 deg = 180 + 27
  D63_PRED,   // Directional 63  deg = round(arctan(2/1) * 180/pi)
  SMOOTH_PRED,  // Combination of horizontal and vertical interpolation
  TM_PRED,        // True-motion
  NEARESTMV,
  NEARMV,
  ZEROMV,
  NEWMV,
  // Compound ref compound modes
  NEAREST_NEARESTMV,
  NEAR_NEARMV,
  NEAREST_NEWMV,
  NEW_NEARESTMV,
  NEAR_NEWMV,
  NEW_NEARMV,
  ZERO_ZEROMV,
  NEW_NEWMV,
}

#[derive(Copy,Clone)]
pub enum TxSetType {
    // DCT only
    EXT_TX_SET_DCTONLY = 0,
    // DCT + Identity only
    EXT_TX_SET_DCT_IDTX = 1,
    // Discrete Trig transforms w/o flip (4) + Identity (1)
    EXT_TX_SET_DTT4_IDTX = 2,
    // Discrete Trig transforms w/o flip (4) + Identity (1) + 1D Hor/vert DCT (2)
    EXT_TX_SET_DTT4_IDTX_1DDCT = 3,
    // Discrete Trig transforms w/ flip (9) + Identity (1) + 1D Hor/Ver DCT (2)
    EXT_TX_SET_DTT9_IDTX_1DDCT = 4,
    // Discrete Trig transforms w/ flip (9) + Identity (1) + 1D Hor/Ver (6)
    EXT_TX_SET_ALL16 = 5,
    EXT_TX_SET_TYPES
}

#[derive(Copy,Clone)]
pub struct SubMode {
    pub mode: PredictionMode
}

impl SubMode {
    pub fn default() -> SubMode {
        SubMode {
            mode: PredictionMode::DC_PRED
        }
    }
}

#[derive(Copy,Clone)]
pub struct Mode {
    pub mode: PredictionMode,
    pub skip: bool,
}

impl Mode {
    pub fn default() -> Mode {
        Mode { mode: PredictionMode::DC_PRED,
               skip: false,
        }
    }
    pub fn is_inter(&self) -> bool {
        false
    }
}
<commit_msg>Remove unusued SubMode<commit_after>#![allow(non_camel_case_types)]
#![allow(dead_code)]

#[derive(Copy,Clone)]
pub enum PartitionType {
    PARTITION_NONE,
    PARTITION_HORZ,
    PARTITION_VERT,
    PARTITION_SPLIT
}

#[derive(Copy,Clone)]
pub enum BlockSize {
    BLOCK_4X4,
    BLOCK_4X8,
    BLOCK_8X4,
    BLOCK_8X8,
    BLOCK_8X16,
    BLOCK_16X8,
    BLOCK_16X16,
    BLOCK_16X32,
    BLOCK_32X16,
    BLOCK_32X32,
    BLOCK_32X64,
    BLOCK_64X32,
    BLOCK_64X64,
    BLOCK_4X16,
    BLOCK_16X4,
    BLOCK_8X32,
    BLOCK_32X8
}

pub const TX_SIZES: usize = 4;
pub const TX_SIZES_ALL: usize = 14;

#[derive(Copy,Clone,PartialEq,PartialOrd)]
pub enum TxSize {
    TX_4X4,
    TX_8X8,
    TX_16X16,
    TX_32X32,
    TX_4X8,
    TX_8X4,
    TX_8X16,
    TX_16X8,
    TX_16X32,
    TX_32X16,
    TX_4X16,
    TX_16X4,
    TX_8X32,
    TX_32X8,
}

pub const TX_TYPES: usize = 16;

#[derive(Copy,Clone)]
#[repr(C)]
pub enum TxType {
    DCT_DCT = 0,    // DCT  in both horizontal and vertical
    ADST_DCT = 1,   // ADST in vertical, DCT in horizontal
    DCT_ADST = 2,   // DCT  in vertical, ADST in horizontal
    ADST_ADST = 3,  // ADST in both directions
    FLIPADST_DCT = 4,
    DCT_FLIPADST = 5,
    FLIPADST_FLIPADST = 6,
    ADST_FLIPADST = 7,
    FLIPADST_ADST = 8,
    IDTX = 9,
    V_DCT = 10,
    H_DCT = 11,
    V_ADST = 12,
    H_ADST = 13,
    V_FLIPADST = 14,
    H_FLIPADST = 15,
}

#[derive(Copy,Clone,Debug)]
pub enum PredictionMode {
  DC_PRED,    // Average of above and left pixels
  V_PRED,     // Vertical
  H_PRED,     // Horizontal
  D45_PRED,   // Directional 45  deg = round(arctan(1/1) * 180/pi)
  D135_PRED,  // Directional 135 deg = 180 - 45
  D117_PRED,  // Directional 117 deg = 180 - 63
  D153_PRED,  // Directional 153 deg = 180 - 27
  D207_PRED,  // Directional 207 deg = 180 + 27
  D63_PRED,   // Directional 63  deg = round(arctan(2/1) * 180/pi)
  SMOOTH_PRED,  // Combination of horizontal and vertical interpolation
  TM_PRED,        // True-motion
  NEARESTMV,
  NEARMV,
  ZEROMV,
  NEWMV,
  // Compound ref compound modes
  NEAREST_NEARESTMV,
  NEAR_NEARMV,
  NEAREST_NEWMV,
  NEW_NEARESTMV,
  NEAR_NEWMV,
  NEW_NEARMV,
  ZERO_ZEROMV,
  NEW_NEWMV,
}

#[derive(Copy,Clone)]
pub enum TxSetType {
    // DCT only
    EXT_TX_SET_DCTONLY = 0,
    // DCT + Identity only
    EXT_TX_SET_DCT_IDTX = 1,
    // Discrete Trig transforms w/o flip (4) + Identity (1)
    EXT_TX_SET_DTT4_IDTX = 2,
    // Discrete Trig transforms w/o flip (4) + Identity (1) + 1D Hor/vert DCT (2)
    EXT_TX_SET_DTT4_IDTX_1DDCT = 3,
    // Discrete Trig transforms w/ flip (9) + Identity (1) + 1D Hor/Ver DCT (2)
    EXT_TX_SET_DTT9_IDTX_1DDCT = 4,
    // Discrete Trig transforms w/ flip (9) + Identity (1) + 1D Hor/Ver (6)
    EXT_TX_SET_ALL16 = 5,
    EXT_TX_SET_TYPES
}

#[derive(Copy,Clone)]
pub struct Mode {
    pub mode: PredictionMode,
    pub skip: bool,
}

impl Mode {
    pub fn default() -> Mode {
        Mode { mode: PredictionMode::DC_PRED,
               skip: false,
        }
    }
    pub fn is_inter(&self) -> bool {
        false
    }
}
<|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.

use std::net::TcpStream;
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{self, Sender};
use std::thread::{self, JoinHandle};
use util::codec::rpc;
use util::make_std_tcp_conn;
use protobuf::{self, MessageStatic};
use super::Result;

const MAX_PD_SEND_RETRY_COUNT: usize = 20;

pub trait TRpcClient: Sync + Send {
    fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic;
    fn post<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<()>;
}

#[derive(Debug)]
struct RpcClientCore {
    addrs: Vec<String>,
    // Try to connect pd with round-robin.
    next_index: usize,
    stream: Option<TcpStream>,
}

fn send_msg<M: protobuf::Message + ?Sized>(stream: &mut TcpStream,
                                           msg_id: u64,
                                           message: &M)
                                           -> Result<(u64, Vec<u8>)> {
    try!(stream.set_write_timeout(Some(Duration::from_secs(SOCKET_WRITE_TIMEOUT))));
    try!(rpc::encode_msg(stream, msg_id, message));

    try!(stream.set_read_timeout(Some(Duration::from_secs(SOCKET_READ_TIMEOUT))));
    let (id, data) = try!(rpc::decode_data(stream));
    Ok((id, data))
}

impl RpcClientCore {
    fn new(dsn: &str) -> RpcClientCore {
        let addrs: Vec<String> = dsn.split(',').map(From::from).collect();
        RpcClientCore {
            addrs: addrs,
            next_index: 0,
            stream: None,
        }
    }

    fn try_connect(&mut self) -> Result<()> {
        let index = self.next_index;
        self.next_index = (self.next_index + 1) % self.addrs.len();

        let addr = self.addrs.get(index).unwrap();
        let stream = try!(make_std_tcp_conn(&**addr));
        self.stream = Some(stream);
        Ok(())
    }

    fn post_msg<M: protobuf::Message + ?Sized>(&mut self,
                                               msg_id: u64,
                                               message: &M)
                                               -> Result<Vec<u8>> {
        // If we post failed, we should retry.
        for _ in 0..MAX_PD_SEND_RETRY_COUNT {
            // If no stream, try connect first.
            if self.stream.is_none() {
                if let Err(e) = self.try_connect() {
                    warn!("connect pd failed {:?}", e);
                    continue;
                }
            }

            let mut stream = self.stream.take().unwrap();
            // We may send message to a not leader pd, retry.

            let (id, data) = match send_msg(&mut stream, msg_id, message) {
                Err(e) => {
                    warn!("send message to pd failed {:?}", e);
                    continue;
                }
                Ok((id, data)) => (id, data),
            };

            if id != msg_id {
                return Err(box_err!("pd response msg_id not match, want {}, got {}", msg_id, id));
            }

            self.stream = Some(stream);
            return Ok(data);
        }

        Err(box_err!("post message to pd failed"))
    }
}

#[derive(Debug)]
pub struct RpcClient {
    core: Mutex<RpcClientCore>,
}

const SOCKET_READ_TIMEOUT: u64 = 3;
const SOCKET_WRITE_TIMEOUT: u64 = 3;

impl RpcClient {
    pub fn new(dsn: &str) -> Result<RpcClient> {
        Ok(RpcClient { core: Mutex::new(RpcClientCore::new(dsn)) })
    }
}

impl TRpcClient for RpcClient {
    fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic
    {
        let mut resp = P::new();
        let data = try!(self.core.lock().unwrap().post_msg(msg_id, message));
        try!(rpc::decode_body(&data, &mut resp));
        Ok(resp)
    }

    fn post<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<()> {
        let _ = try!(self.core.lock().unwrap().post_msg(msg_id, message));
        Ok(())
    }
}

#[derive(Debug)]
enum Msg {
    Rpc(u64, Box<protobuf::Message + Send>),
    Quit,
}

pub struct Client<C: TRpcClient + 'static> {
    msg_id: AtomicUsize,
    rpc_client: Arc<C>,
    tx: Mutex<Sender<Msg>>,
    handle: Option<JoinHandle<()>>,
}

impl<C: TRpcClient + 'static> Client<C> {
    pub fn new(rpc_client: C) -> Result<Client<C>> {
        let shared = Arc::new(rpc_client);
        let (tx, rx) = mpsc::channel();
        let handle = {
            let rpc_client = shared.clone();
            try!(thread::Builder::new()
                     .name("pd-client background worker".to_owned())
                     .spawn(move || {
                         info!("pd-client background worker starting");
                         while let Msg::Rpc(msg_id, msg) = rx.recv().unwrap() {
                             if let Err(e) = rpc_client.post(msg_id, msg.as_ref()) {
                                 error!("pd post error: {}", e);
                             } else {
                                 debug!("pd post done: {}", msg_id);
                             }
                         }
                         info!("pd-client background worker closing");
                     }))
        };
        Ok(Client {
            msg_id: AtomicUsize::new(0),
            rpc_client: shared.clone(),
            tx: Mutex::new(tx),
            handle: Some(handle),
        })
    }

    fn close(&mut self) {
        if let Err(e) = self.clone_tx().send(Msg::Quit) {
            error!("failed to send quit message to pd-client background worker: {}",
                   e);
        }
        let handle = self.handle.take().unwrap();
        if handle.join().is_err() {
            error!("failed to wait pd-client background worker quit");
        }
        info!("pd-client closed.");
    }

    pub fn send<M, P>(&self, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic
    {
        let id = self.alloc_msg_id();
        self.rpc_client.send(id, message)
    }

    pub fn post<M: protobuf::Message + Send>(&self, message: M) -> Result<()> {
        let id = self.alloc_msg_id();
        if let Err(e) = self.clone_tx().send(Msg::Rpc(id, box message)) {
            return Err(box_err!(format!("SendError: {:?}", e)));
        }
        Ok(())
    }

    fn alloc_msg_id(&self) -> u64 {
        self.msg_id.fetch_add(1, Ordering::Relaxed) as u64
    }

    fn clone_tx(&self) -> Sender<Msg> {
        let tx = self.tx.lock().unwrap();
        tx.clone()
    }
}

impl<C: TRpcClient + 'static> Drop for Client<C> {
    fn drop(&mut self) {
        self.close()
    }
}

#[cfg(test)]
mod tests {
    use std::net::TcpListener;
    use std::thread;
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};

    use super::super::{Result, PdClient};
    use super::*;
    use protobuf;
    use bytes::ByteBuf;
    use util::codec::rpc;
    use kvproto::{metapb, pdpb};
    use rand;
    use util::make_std_tcp_conn;

    struct MockRpcClient;

    impl MockRpcClient {
        fn reply(&self, req: &pdpb::Request) -> pdpb::Response {
            assert!(req.has_header());
            let header = req.get_header();
            let (uuid, cluster_id) = (header.get_uuid(), header.get_cluster_id());

            let mut resp = pdpb::Response::new();
            let mut header = pdpb::ResponseHeader::new();
            header.set_uuid(uuid.to_vec());
            header.set_cluster_id(cluster_id);

            match req.get_cmd_type() {
                pdpb::CommandType::AllocId => {
                    let mut alloc = pdpb::AllocIdResponse::new();
                    alloc.set_id(42);
                    resp.set_alloc_id(alloc);
                }
                pdpb::CommandType::PutMeta => {
                    let meta = req.get_put_meta();
                    if meta.get_meta_type() == pdpb::MetaType::StoreType {
                        let store = meta.get_store();
                        assert_eq!(store.get_id(), 233);
                        assert_eq!(store.get_address(), "localhost");
                    }
                }
                _ => {
                    let mut err = pdpb::Error::new();
                    err.set_message(String::from("I've got a bad feeling about this"));
                    header.set_error(err);
                }
            }

            resp.set_header(header);
            resp.set_cmd_type(req.get_cmd_type());
            resp
        }
    }

    impl TRpcClient for MockRpcClient {
        fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

            where M: protobuf::Message,
                  P: protobuf::Message + Default
        {
            let mut buf = ByteBuf::mut_with_capacity(128);
            rpc::encode_msg(&mut buf, msg_id, message).unwrap();
            let mut req = pdpb::Request::new();
            rpc::decode_msg(&mut buf.flip(), &mut req).unwrap();

            let resp = self.reply(&req);
            let mut buf = ByteBuf::mut_with_capacity(128);
            rpc::encode_msg(&mut buf, msg_id, &resp).unwrap();
            let mut msg = P::default();
            rpc::decode_msg(&mut buf.flip(), &mut msg).unwrap();
            Ok(msg)
        }

        fn post<M: protobuf::Message + ?Sized>(&self, _: u64, _: &M) -> Result<()> {
            Ok(())
        }
    }

    #[test]
    fn test_pd_client() {
        let mut client = Client::new(MockRpcClient).unwrap();
        assert_eq!(client.alloc_id().unwrap(), 42u64);
        assert!(client.is_cluster_bootstrapped(1).is_err());

        let mut store = metapb::Store::new();
        store.set_id(233);
        store.set_address("localhost".to_owned());
        assert!(client.put_store(1, store).is_ok());
    }

    fn start_pd_server(index: usize,
                       leader_index: Arc<AtomicUsize>,
                       quit: Arc<AtomicBool>)
                       -> (thread::JoinHandle<()>, String) {
        let l = TcpListener::bind("127.0.0.1:0").unwrap();

        let addr = format!("{}", l.local_addr().unwrap());

        let h = thread::spawn(move || {
            loop {
                let (mut stream, _) = l.accept().unwrap();

                if quit.load(Ordering::SeqCst) {
                    return;
                }

                stream.set_nodelay(true).unwrap();

                let leader = leader_index.load(Ordering::SeqCst);
                if leader != index {
                    continue;
                }

                let (id, data) = rpc::decode_data(&mut stream).unwrap();
                rpc::encode_data(&mut stream, id, &data).unwrap();
            }
        });

        (h, addr)
    }

    #[test]
    fn test_rpc_client() {
        let leader = Arc::new(AtomicUsize::new(0));
        let quit = Arc::new(AtomicBool::new(false));
        let mut handlers = vec![];
        let mut addrs = vec![];

        let count = 3;
        for i in 0..count {
            let (h, addr) = start_pd_server(i, leader.clone(), quit.clone());
            handlers.push(h);
            addrs.push(addr);
        }

        let dsn = addrs.join(",");

        let msg = pdpb::Request::new();
        let client = RpcClient::new(&dsn).unwrap();

        for i in 0..10 {
            client.post(i as u64, &msg).unwrap();

            // select a leader randomly
            leader.store(rand::random::<usize>() % 3, Ordering::SeqCst);
        }

        quit.store(true, Ordering::SeqCst);

        // connect the server so that we can close the thread.
        for addr in addrs {
            make_std_tcp_conn(&*addr).unwrap();
        }

        for h in handlers {
            h.join().unwrap();
        }
    }
}
<commit_msg>pd/client: backoff when connection refused. (#391)<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.

use std::net::TcpStream;
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{self, Sender};
use std::thread::{self, JoinHandle};
use util::codec::rpc;
use util::make_std_tcp_conn;
use protobuf::{self, MessageStatic};
use super::Result;

const MAX_PD_SEND_RETRY_COUNT: usize = 100;

pub trait TRpcClient: Sync + Send {
    fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic;
    fn post<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<()>;
}

#[derive(Debug)]
struct RpcClientCore {
    addrs: Vec<String>,
    // Try to connect pd with round-robin.
    next_index: usize,
    stream: Option<TcpStream>,
}

fn send_msg<M: protobuf::Message + ?Sized>(stream: &mut TcpStream,
                                           msg_id: u64,
                                           message: &M)
                                           -> Result<(u64, Vec<u8>)> {
    try!(stream.set_write_timeout(Some(Duration::from_secs(SOCKET_WRITE_TIMEOUT))));
    try!(rpc::encode_msg(stream, msg_id, message));

    try!(stream.set_read_timeout(Some(Duration::from_secs(SOCKET_READ_TIMEOUT))));
    let (id, data) = try!(rpc::decode_data(stream));
    Ok((id, data))
}

impl RpcClientCore {
    fn new(dsn: &str) -> RpcClientCore {
        let addrs: Vec<String> = dsn.split(',').map(From::from).collect();
        RpcClientCore {
            addrs: addrs,
            next_index: 0,
            stream: None,
        }
    }

    fn try_connect(&mut self) -> Result<()> {
        let index = self.next_index;
        self.next_index = (self.next_index + 1) % self.addrs.len();

        let addr = self.addrs.get(index).unwrap();
        let stream = try!(make_std_tcp_conn(&**addr));
        self.stream = Some(stream);
        Ok(())
    }

    fn post_msg<M: protobuf::Message + ?Sized>(&mut self,
                                               msg_id: u64,
                                               message: &M)
                                               -> Result<Vec<u8>> {
        // If we post failed, we should retry.
        for _ in 0..MAX_PD_SEND_RETRY_COUNT {
            // If no stream, try connect first.
            if self.stream.is_none() {
                if let Err(e) = self.try_connect() {
                    warn!("connect pd failed {:?}", e);
                    continue;
                }
            }

            let mut stream = self.stream.take().unwrap();
            // We may send message to a not leader pd, retry.

            let (id, data) = match send_msg(&mut stream, msg_id, message) {
                Err(e) => {
                    warn!("send message to pd failed {:?}", e);
                    // TODO: figure out a better way to do backoff
                    thread::sleep(Duration::from_millis(50));
                    continue;
                }
                Ok((id, data)) => (id, data),
            };

            if id != msg_id {
                return Err(box_err!("pd response msg_id not match, want {}, got {}", msg_id, id));
            }

            self.stream = Some(stream);
            return Ok(data);
        }

        Err(box_err!("post message to pd failed"))
    }
}

#[derive(Debug)]
pub struct RpcClient {
    core: Mutex<RpcClientCore>,
}

const SOCKET_READ_TIMEOUT: u64 = 3;
const SOCKET_WRITE_TIMEOUT: u64 = 3;

impl RpcClient {
    pub fn new(dsn: &str) -> Result<RpcClient> {
        Ok(RpcClient { core: Mutex::new(RpcClientCore::new(dsn)) })
    }
}

impl TRpcClient for RpcClient {
    fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic
    {
        let mut resp = P::new();
        let data = try!(self.core.lock().unwrap().post_msg(msg_id, message));
        try!(rpc::decode_body(&data, &mut resp));
        Ok(resp)
    }

    fn post<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<()> {
        let _ = try!(self.core.lock().unwrap().post_msg(msg_id, message));
        Ok(())
    }
}

#[derive(Debug)]
enum Msg {
    Rpc(u64, Box<protobuf::Message + Send>),
    Quit,
}

pub struct Client<C: TRpcClient + 'static> {
    msg_id: AtomicUsize,
    rpc_client: Arc<C>,
    tx: Mutex<Sender<Msg>>,
    handle: Option<JoinHandle<()>>,
}

impl<C: TRpcClient + 'static> Client<C> {
    pub fn new(rpc_client: C) -> Result<Client<C>> {
        let shared = Arc::new(rpc_client);
        let (tx, rx) = mpsc::channel();
        let handle = {
            let rpc_client = shared.clone();
            try!(thread::Builder::new()
                     .name("pd-client background worker".to_owned())
                     .spawn(move || {
                         info!("pd-client background worker starting");
                         while let Msg::Rpc(msg_id, msg) = rx.recv().unwrap() {
                             if let Err(e) = rpc_client.post(msg_id, msg.as_ref()) {
                                 error!("pd post error: {}", e);
                             } else {
                                 debug!("pd post done: {}", msg_id);
                             }
                         }
                         info!("pd-client background worker closing");
                     }))
        };
        Ok(Client {
            msg_id: AtomicUsize::new(0),
            rpc_client: shared.clone(),
            tx: Mutex::new(tx),
            handle: Some(handle),
        })
    }

    fn close(&mut self) {
        if let Err(e) = self.clone_tx().send(Msg::Quit) {
            error!("failed to send quit message to pd-client background worker: {}",
                   e);
        }
        let handle = self.handle.take().unwrap();
        if handle.join().is_err() {
            error!("failed to wait pd-client background worker quit");
        }
        info!("pd-client closed.");
    }

    pub fn send<M, P>(&self, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic
    {
        let id = self.alloc_msg_id();
        self.rpc_client.send(id, message)
    }

    pub fn post<M: protobuf::Message + Send>(&self, message: M) -> Result<()> {
        let id = self.alloc_msg_id();
        if let Err(e) = self.clone_tx().send(Msg::Rpc(id, box message)) {
            return Err(box_err!(format!("SendError: {:?}", e)));
        }
        Ok(())
    }

    fn alloc_msg_id(&self) -> u64 {
        self.msg_id.fetch_add(1, Ordering::Relaxed) as u64
    }

    fn clone_tx(&self) -> Sender<Msg> {
        let tx = self.tx.lock().unwrap();
        tx.clone()
    }
}

impl<C: TRpcClient + 'static> Drop for Client<C> {
    fn drop(&mut self) {
        self.close()
    }
}

#[cfg(test)]
mod tests {
    use std::net::TcpListener;
    use std::thread;
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};

    use super::super::{Result, PdClient};
    use super::*;
    use protobuf;
    use bytes::ByteBuf;
    use util::codec::rpc;
    use kvproto::{metapb, pdpb};
    use rand;
    use util::make_std_tcp_conn;

    struct MockRpcClient;

    impl MockRpcClient {
        fn reply(&self, req: &pdpb::Request) -> pdpb::Response {
            assert!(req.has_header());
            let header = req.get_header();
            let (uuid, cluster_id) = (header.get_uuid(), header.get_cluster_id());

            let mut resp = pdpb::Response::new();
            let mut header = pdpb::ResponseHeader::new();
            header.set_uuid(uuid.to_vec());
            header.set_cluster_id(cluster_id);

            match req.get_cmd_type() {
                pdpb::CommandType::AllocId => {
                    let mut alloc = pdpb::AllocIdResponse::new();
                    alloc.set_id(42);
                    resp.set_alloc_id(alloc);
                }
                pdpb::CommandType::PutMeta => {
                    let meta = req.get_put_meta();
                    if meta.get_meta_type() == pdpb::MetaType::StoreType {
                        let store = meta.get_store();
                        assert_eq!(store.get_id(), 233);
                        assert_eq!(store.get_address(), "localhost");
                    }
                }
                _ => {
                    let mut err = pdpb::Error::new();
                    err.set_message(String::from("I've got a bad feeling about this"));
                    header.set_error(err);
                }
            }

            resp.set_header(header);
            resp.set_cmd_type(req.get_cmd_type());
            resp
        }
    }

    impl TRpcClient for MockRpcClient {
        fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

            where M: protobuf::Message,
                  P: protobuf::Message + Default
        {
            let mut buf = ByteBuf::mut_with_capacity(128);
            rpc::encode_msg(&mut buf, msg_id, message).unwrap();
            let mut req = pdpb::Request::new();
            rpc::decode_msg(&mut buf.flip(), &mut req).unwrap();

            let resp = self.reply(&req);
            let mut buf = ByteBuf::mut_with_capacity(128);
            rpc::encode_msg(&mut buf, msg_id, &resp).unwrap();
            let mut msg = P::default();
            rpc::decode_msg(&mut buf.flip(), &mut msg).unwrap();
            Ok(msg)
        }

        fn post<M: protobuf::Message + ?Sized>(&self, _: u64, _: &M) -> Result<()> {
            Ok(())
        }
    }

    #[test]
    fn test_pd_client() {
        let mut client = Client::new(MockRpcClient).unwrap();
        assert_eq!(client.alloc_id().unwrap(), 42u64);
        assert!(client.is_cluster_bootstrapped(1).is_err());

        let mut store = metapb::Store::new();
        store.set_id(233);
        store.set_address("localhost".to_owned());
        assert!(client.put_store(1, store).is_ok());
    }

    fn start_pd_server(index: usize,
                       leader_index: Arc<AtomicUsize>,
                       quit: Arc<AtomicBool>)
                       -> (thread::JoinHandle<()>, String) {
        let l = TcpListener::bind("127.0.0.1:0").unwrap();

        let addr = format!("{}", l.local_addr().unwrap());

        let h = thread::spawn(move || {
            loop {
                let (mut stream, _) = l.accept().unwrap();

                if quit.load(Ordering::SeqCst) {
                    return;
                }

                stream.set_nodelay(true).unwrap();

                let leader = leader_index.load(Ordering::SeqCst);
                if leader != index {
                    continue;
                }

                let (id, data) = rpc::decode_data(&mut stream).unwrap();
                rpc::encode_data(&mut stream, id, &data).unwrap();
            }
        });

        (h, addr)
    }

    #[test]
    fn test_rpc_client() {
        let leader = Arc::new(AtomicUsize::new(0));
        let quit = Arc::new(AtomicBool::new(false));
        let mut handlers = vec![];
        let mut addrs = vec![];

        let count = 3;
        for i in 0..count {
            let (h, addr) = start_pd_server(i, leader.clone(), quit.clone());
            handlers.push(h);
            addrs.push(addr);
        }

        let dsn = addrs.join(",");

        let msg = pdpb::Request::new();
        let client = RpcClient::new(&dsn).unwrap();

        for i in 0..10 {
            client.post(i as u64, &msg).unwrap();

            // select a leader randomly
            leader.store(rand::random::<usize>() % 3, Ordering::SeqCst);
        }

        quit.store(true, Ordering::SeqCst);

        // connect the server so that we can close the thread.
        for addr in addrs {
            make_std_tcp_conn(&*addr).unwrap();
        }

        for h in handlers {
            h.join().unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::Deref;

use qvariant::*;
use types::*;
use qurl::*;
use qmeta::*;

extern "C" {
    fn dos_qapplication_create();
    fn dos_qapplication_exec();
    fn dos_qapplication_quit();
    fn dos_qapplication_delete();

    fn dos_qqmlapplicationengine_create() -> DosQmlApplicationEngine;
    fn dos_qqmlapplicationengine_load(vptr: DosQmlApplicationEngine, filename: DosCStr);
    fn dos_qqmlapplicationengine_load_url(vptr: DosQmlApplicationEngine, url: DosQUrl);
    fn dos_qqmlapplicationengine_load_data(vptr: DosQmlApplicationEngine, data: DosCStr);
    // fn dos_qqmlapplicationengine_add_import_path(vptr: *mut DosQQmlApplicationEngine, const char *path);
    fn dos_qqmlapplicationengine_context(vptr: DosQmlApplicationEngine) -> DosQQmlContext;
    fn dos_qqmlapplicationengine_delete(vptr: DosQmlApplicationEngine);

    fn dos_qqmlcontext_setcontextproperty(vptr: DosQQmlContext,
                                          name: DosCStr,
                                          value: DosQVariant);

}

/// Provides an entry point for building QML applications from Rust
pub struct QmlEngine {
    ptr: DosQmlApplicationEngine,
    stored: Vec<QVariant>,
}

impl QmlEngine {
    /// Creates a QML context of a non-headless application
    pub fn new() -> Self {
        unsafe {
            dos_qapplication_create();
            QmlEngine {
                ptr: dos_qqmlapplicationengine_create(),
                stored: Vec::new(),
            }
        }
    }

    pub fn registered_type<T: Deref<Target = QObjectMacro>>(&mut self, id: i32, registered: T) {}
    /// Loads a file as a qml file
    pub fn load_file(&self, path: &str) {
        let path_raw = ::std::env::current_dir().unwrap().join(path);
        let path = if cfg!(windows) {
            format!("file:///{}", path_raw.display())
        } else {
            format!("file://{}", path_raw.display())
        };
        unsafe { dos_qqmlapplicationengine_load_url(self.ptr, construct_qurl(&path)) }
    }

    /// Loads qml from a specified url (`file://`, `qrc://`, `http://`)
    pub fn load_url(&self, uri: &str) {
        unsafe { dos_qqmlapplicationengine_load_url(self.ptr, construct_qurl(uri)) }
    }

    /// Loads a string as a qml file
    pub fn load_data(&self, data: &str) {
        unsafe { dos_qqmlapplicationengine_load_data(self.ptr, stoptr(data)) }
    }

    /// Launches the application
    pub fn exec(&self) {
        unsafe {
            dos_qapplication_exec();
        }
    }
    /// Closes the application
    pub fn quit(&self) {
        unsafe {
            dos_qapplication_quit();
        }
    }

    /// Sets a property for this QML context
    ///
    /// This variant stores qvariant, so it is removed, only when this QmlEngine is removed.
    pub fn set_and_store_property<T: Into<QVariant>>(&mut self, name: &str, value: T) {
        let val = value.into();
        unsafe {
            let context = dos_qqmlapplicationengine_context(self.ptr);
            dos_qqmlcontext_setcontextproperty(context, stoptr(name), get_private_variant(&val));
        }
        self.stored.push(val);
    }

    /// Sets a property for this QML context
    pub fn set_property(&self, name: &str, value: &QVariant) {
        unsafe {
            let context = dos_qqmlapplicationengine_context(self.ptr);
            dos_qqmlcontext_setcontextproperty(context, stoptr(name), get_private_variant(value));
        }
    }
}

use utils::*;

impl Default for QmlEngine {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for QmlEngine {
    fn drop(&mut self) {
        unsafe {
            dos_qapplication_quit();
            dos_qqmlapplicationengine_delete(self.ptr);
            dos_qapplication_delete();
        }
    }
}
<commit_msg>Removed unused function<commit_after>
use qvariant::*;
use types::*;
use qurl::*;

extern "C" {
    fn dos_qapplication_create();
    fn dos_qapplication_exec();
    fn dos_qapplication_quit();
    fn dos_qapplication_delete();

    fn dos_qqmlapplicationengine_create() -> DosQmlApplicationEngine;
    fn dos_qqmlapplicationengine_load(vptr: DosQmlApplicationEngine, filename: DosCStr);
    fn dos_qqmlapplicationengine_load_url(vptr: DosQmlApplicationEngine, url: DosQUrl);
    fn dos_qqmlapplicationengine_load_data(vptr: DosQmlApplicationEngine, data: DosCStr);
    // fn dos_qqmlapplicationengine_add_import_path(vptr: *mut DosQQmlApplicationEngine, const char *path);
    fn dos_qqmlapplicationengine_context(vptr: DosQmlApplicationEngine) -> DosQQmlContext;
    fn dos_qqmlapplicationengine_delete(vptr: DosQmlApplicationEngine);

    fn dos_qqmlcontext_setcontextproperty(vptr: DosQQmlContext,
                                          name: DosCStr,
                                          value: DosQVariant);

}

/// Provides an entry point for building QML applications from Rust
pub struct QmlEngine {
    ptr: DosQmlApplicationEngine,
    stored: Vec<QVariant>,
}

impl QmlEngine {
    /// Creates a QML context of a non-headless application
    pub fn new() -> Self {
        unsafe {
            dos_qapplication_create();
            QmlEngine {
                ptr: dos_qqmlapplicationengine_create(),
                stored: Vec::new(),
            }
        }
    }

    /// Loads a file as a qml file
    pub fn load_file(&self, path: &str) {
        let path_raw = ::std::env::current_dir().unwrap().join(path);
        let path = if cfg!(windows) {
            format!("file:///{}", path_raw.display())
        } else {
            format!("file://{}", path_raw.display())
        };
        unsafe { dos_qqmlapplicationengine_load_url(self.ptr, construct_qurl(&path)) }
    }

    /// Loads qml from a specified url (`file://`, `qrc://`, `http://`)
    pub fn load_url(&self, uri: &str) {
        unsafe { dos_qqmlapplicationengine_load_url(self.ptr, construct_qurl(uri)) }
    }

    /// Loads a string as a qml file
    pub fn load_data(&self, data: &str) {
        unsafe { dos_qqmlapplicationengine_load_data(self.ptr, stoptr(data)) }
    }

    /// Launches the application
    pub fn exec(&self) {
        unsafe {
            dos_qapplication_exec();
        }
    }
    /// Closes the application
    pub fn quit(&self) {
        unsafe {
            dos_qapplication_quit();
        }
    }

    /// Sets a property for this QML context
    ///
    /// This variant stores qvariant, so it is removed, only when this QmlEngine is removed.
    pub fn set_and_store_property<T: Into<QVariant>>(&mut self, name: &str, value: T) {
        let val = value.into();
        unsafe {
            let context = dos_qqmlapplicationengine_context(self.ptr);
            dos_qqmlcontext_setcontextproperty(context, stoptr(name), get_private_variant(&val));
        }
        self.stored.push(val);
    }

    /// Sets a property for this QML context
    pub fn set_property(&self, name: &str, value: &QVariant) {
        unsafe {
            let context = dos_qqmlapplicationengine_context(self.ptr);
            dos_qqmlcontext_setcontextproperty(context, stoptr(name), get_private_variant(value));
        }
    }
}

use utils::*;

impl Default for QmlEngine {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for QmlEngine {
    fn drop(&mut self) {
        unsafe {
            dos_qapplication_quit();
            dos_qqmlapplicationengine_delete(self.ptr);
            dos_qapplication_delete();
        }
    }
}
<|endoftext|>


<commit_before>//! [β-reduction](https://en.wikipedia.org/wiki/Beta_normal_form) for lambda `Term`s

use term::*;
use term::Term::*;

/// Applies two terms with substitution and variable update, consuming the first one in the process.
///
/// # Example
/// ```
/// use lambda_calculus::reduction::apply;
/// use lambda_calculus::parser::parse;
///
/// let lhs    = parse(&"λλ42(λ13)").unwrap();
/// let rhs    = parse(&"λ51").unwrap();
/// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
///
/// assert_eq!(apply(lhs, &rhs), Ok(result));
/// ```
pub fn apply(mut lhs: Term, rhs: &Term) -> Result<Term, Error> {
    _apply(&mut lhs, rhs, 0);

    lhs.unabs()
}

fn _apply(lhs: &mut Term, rhs: &Term, depth: usize) {
    match *lhs {
        Var(i) => if i == depth {
            *lhs = rhs.clone(); // substitute a top-level variable from lhs with rhs
            update_free_variables(lhs, depth - 1, 0); // update indices of free variables from rhs
        } else if i > depth {
            *lhs = Var(i - 1) // decrement a free variable's index
        },
        Abs(_) => {
            _apply(lhs.unabs_ref_mut().unwrap(), rhs, depth + 1)
        },
        App(_, _) => {
            _apply(lhs.lhs_ref_mut().unwrap(), rhs, depth);
            _apply(lhs.rhs_ref_mut().unwrap(), rhs, depth)
        }
    }
}

fn update_free_variables(term: &mut Term, added_depth: usize, own_depth: usize) {
    match *term {
        Var(i) => if i > own_depth {
            *term = Var(i + added_depth)
        },
        Abs(_) => {
            update_free_variables(term.unabs_ref_mut().unwrap(), added_depth, own_depth + 1)
        },
        App(_, _) => {
            update_free_variables(term.lhs_ref_mut().unwrap(), added_depth, own_depth);
            update_free_variables(term.rhs_ref_mut().unwrap(), added_depth, own_depth)
        }
    }
}

/// Set to `true` to see all the steps of β-reductions. The default is `false`.
pub const SHOW_REDUCTIONS: bool = false;

impl Term {
    /// Applies `self` to another term with substitution and variable update, consuming it
    /// in the process.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::parser::parse;
    ///
    /// let lhs    = parse(&"λλ42(λ13)").unwrap();
    /// let rhs    = parse(&"λ51").unwrap();
    /// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
    ///
    /// assert_eq!(lhs.apply(&rhs), Ok(result));
    /// ```
    pub fn apply(self, rhs: &Term) -> Result<Term, Error> {
        apply(self, rhs)
    }

    /// Reduces an `App`lication by substitution and variable update.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::{app, abs};
    /// use lambda_calculus::term::Term::Var;
    /// use lambda_calculus::arithmetic::zero;
    /// use lambda_calculus::combinators::i;
    ///
    /// assert_eq!(app(i(), zero()).eval(), Ok(zero()));
    /// ```
    pub fn eval(self) -> Result<Term, Error> {
        let (lhs, rhs) = try!(self.unapp());

        apply(lhs, &rhs)
    }

    /// Performs a single normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::succ;
    ///
    /// let mut succ_one = succ().app(1.into());
    /// succ_one.beta_once();
    ///
    /// assert_eq!(succ_one, succ().apply(&1.into()).unwrap());
    /// ```
    pub fn beta_once(&mut self) {
        let mut done = false;
        self._beta_once(&mut done, 0);
    }

    fn _beta_once(&mut self, done: &mut bool, depth: u32) {
        if *done { return }

        match *self {
            Var(_) => (),
            Abs(_) => self.unabs_ref_mut().unwrap()._beta_once(done, depth + 1),
            App(_, _) => {
                if self.lhs_ref().unwrap().unabs_ref().is_ok() {
                    let copy = self.clone();
                    if SHOW_REDUCTIONS { print!("    {} reduces to ", show_precedence(self, 0, depth)) };
                    *self = copy.eval().unwrap();
                    *done = true;
                } else {
                    self.lhs_ref_mut().unwrap()._beta_once(done, depth);
                    self.rhs_ref_mut().unwrap()._beta_once(done, depth)
                }
            }
        }
    }

    /// Performs full normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::pred;
    ///
    /// let mut pred_one = pred().app(1.into());
    /// pred_one.beta_full();
    ///
    /// assert_eq!(pred_one, 0.into());
    /// ```
    pub fn beta_full(&mut self) {
        let mut tmp;
        loop {
            if SHOW_REDUCTIONS { println!("reducing {}", self) }
            tmp = self.clone();
            self.beta_once();
            if *self == tmp { break }
        }

        if SHOW_REDUCTIONS { println!("    doesn't reduce") }
    }
}

/// Performs full normal-order β-reduction on a `Term`, consuming it in the process.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::pred;
/// use lambda_calculus::reduction::beta_full;
///
/// let pred_one = pred().app(1.into());
///
/// assert_eq!(beta_full(pred_one), 0.into());
/// ```
pub fn beta_full(mut term: Term) -> Term {
    term.beta_full();
    term
}

/// Performs a single normal-order β-reduction on `self`.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::succ;
/// use lambda_calculus::reduction::beta_once;
///
/// let succ_one = succ().app(1.into());
///
/// assert_eq!(beta_once(succ_one), succ().apply(&1.into()).unwrap());
/// ```
pub fn beta_once(mut term: Term) -> Term {
    term.beta_once();
    term
}

#[cfg(test)]
mod test {

}
<commit_msg>missed one line<commit_after>//! [β-reduction](https://en.wikipedia.org/wiki/Beta_normal_form) for lambda `Term`s

use term::*;
use term::Term::*;

/// Applies two terms with substitution and variable update, consuming the first one in the process.
///
/// # Example
/// ```
/// use lambda_calculus::reduction::apply;
/// use lambda_calculus::parser::parse;
///
/// let lhs    = parse(&"λλ42(λ13)").unwrap();
/// let rhs    = parse(&"λ51").unwrap();
/// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
///
/// assert_eq!(apply(lhs, &rhs), Ok(result));
/// ```
pub fn apply(mut lhs: Term, rhs: &Term) -> Result<Term, Error> {
    _apply(&mut lhs, rhs, 0);

    lhs.unabs()
}

fn _apply(lhs: &mut Term, rhs: &Term, depth: usize) {
    match *lhs {
        Var(i) => if i == depth {
            *lhs = rhs.clone(); // substitute a top-level variable from lhs with rhs
            update_free_variables(lhs, depth - 1, 0); // update indices of free variables from rhs
        } else if i > depth {
            *lhs = Var(i - 1) // decrement a free variable's index
        },
        Abs(_) => {
            _apply(lhs.unabs_ref_mut().unwrap(), rhs, depth + 1)
        },
        App(_, _) => {
            _apply(lhs.lhs_ref_mut().unwrap(), rhs, depth);
            _apply(lhs.rhs_ref_mut().unwrap(), rhs, depth)
        }
    }
}

fn update_free_variables(term: &mut Term, added_depth: usize, own_depth: usize) {
    match *term {
        Var(i) => if i > own_depth {
            *term = Var(i + added_depth)
        },
        Abs(_) => {
            update_free_variables(term.unabs_ref_mut().unwrap(), added_depth, own_depth + 1)
        },
        App(_, _) => {
            update_free_variables(term.lhs_ref_mut().unwrap(), added_depth, own_depth);
            update_free_variables(term.rhs_ref_mut().unwrap(), added_depth, own_depth)
        }
    }
}

/// Set to `true` to see all the steps of β-reductions. The default is `false`.
pub const SHOW_REDUCTIONS: bool = false;

impl Term {
    /// Applies `self` to another term with substitution and variable update, consuming it
    /// in the process.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::parser::parse;
    ///
    /// let lhs    = parse(&"λλ42(λ13)").unwrap();
    /// let rhs    = parse(&"λ51").unwrap();
    /// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
    ///
    /// assert_eq!(lhs.apply(&rhs), Ok(result));
    /// ```
    pub fn apply(self, rhs: &Term) -> Result<Term, Error> {
        apply(self, rhs)
    }

    /// Reduces an `App`lication by substitution and variable update.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::{app, abs};
    /// use lambda_calculus::term::Term::Var;
    /// use lambda_calculus::arithmetic::zero;
    /// use lambda_calculus::combinators::i;
    ///
    /// assert_eq!(app(i(), zero()).eval(), Ok(zero()));
    /// ```
    pub fn eval(self) -> Result<Term, Error> {
        let (lhs, rhs) = try!(self.unapp());

        apply(lhs, &rhs)
    }

    /// Performs a single normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::succ;
    ///
    /// let mut succ_one = succ().app(1.into());
    /// succ_one.beta_once();
    ///
    /// assert_eq!(succ_one, succ().apply(&1.into()).unwrap());
    /// ```
    pub fn beta_once(&mut self) {
        let mut done = false;
        self._beta_once(&mut done, 0);
    }

    fn _beta_once(&mut self, done: &mut bool, depth: u32) {
        if *done { return }

        match *self {
            Var(_) => (),
            Abs(_) => self.unabs_ref_mut().unwrap()._beta_once(done, depth + 1),
            App(_, _) => {
                if self.lhs_ref().unwrap().unabs_ref().is_ok() {
                    let copy = self.clone();
                    if SHOW_REDUCTIONS { print!("    {} reduces to ", show_precedence(self, 0, depth)) };
                    *self = copy.eval().unwrap();
                    if SHOW_REDUCTIONS { println!("{}", show_precedence(self, 0, depth + 1)) }
                    *done = true;
                } else {
                    self.lhs_ref_mut().unwrap()._beta_once(done, depth);
                    self.rhs_ref_mut().unwrap()._beta_once(done, depth)
                }
            }
        }
    }

    /// Performs full normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::pred;
    ///
    /// let mut pred_one = pred().app(1.into());
    /// pred_one.beta_full();
    ///
    /// assert_eq!(pred_one, 0.into());
    /// ```
    pub fn beta_full(&mut self) {
        let mut tmp;
        loop {
            if SHOW_REDUCTIONS { println!("reducing {}", self) }
            tmp = self.clone();
            self.beta_once();
            if *self == tmp { break }
        }

        if SHOW_REDUCTIONS { println!("    doesn't reduce") }
    }
}

/// Performs full normal-order β-reduction on a `Term`, consuming it in the process.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::pred;
/// use lambda_calculus::reduction::beta_full;
///
/// let pred_one = pred().app(1.into());
///
/// assert_eq!(beta_full(pred_one), 0.into());
/// ```
pub fn beta_full(mut term: Term) -> Term {
    term.beta_full();
    term
}

/// Performs a single normal-order β-reduction on `self`.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::succ;
/// use lambda_calculus::reduction::beta_once;
///
/// let succ_one = succ().app(1.into());
///
/// assert_eq!(beta_once(succ_one), succ().apply(&1.into()).unwrap());
/// ```
pub fn beta_once(mut term: Term) -> Term {
    term.beta_once();
    term
}

#[cfg(test)]
mod test {

}
<|endoftext|>


<commit_before>extern crate regex;

mod matching;
mod support;
mod tokens;
mod lexer;
mod files;
mod parser;

use std::vec::Vec;
use tokens::*;
use lexer::*;
use parser::*;

fn main()
{
    let source_file = "sampleData/BasicArithmatic.java";
    let lex_output_file = "sampleData/output/stable/BasicArithmatic.java.lexed";
    let preprocessed_output_file = "sampleData/output/stable/BasicArithmatic.java.preprocessed";

    let mut tokens: Vec<Token> = lex_file(source_file);

    println!("\n\nFound Tokens:");
    tokens.print_to(lex_output_file, true);

    remove_meta(&mut tokens);
    println!("\n\nPerged Tokens:");
    tokens.print_to(preprocessed_output_file, true);

    let invalid_types = get_invalid_token_types();
    let invalid_values = get_invalid_token_values();

    let min_index = 0;
    for (index, token) in tokens.iter().enumerate()
    {
        if index < min_index
        {
            continue;
        }

        if invalid_types.contains(&token.name)
        {
            panic!("Unsupported token type: {}", token.name);
        }
        else if invalid_values.contains(&&*token.value)
        {
            panic!("Unsupported token value: {}", token.value);
        }

        if token.value == "class"
        {
            // parse class body
            let (string, unused) = class_to_plp(&tokens, index);
        }
        /*else if token.name == "type" // || token.type == "identifier"
        {
            // look ahead
            // parse variable declaration
            // OR parse method declaration
        }
        else if token.value == "if"
        {
            // parse if body
            // Unsupported for now
        }
        else if token.name == "construct.conditional"
        {
            // parse conditional
            // Unsupported for now
        }*/
        else
        {
            panic!("Unexpected token: {}\t{}", token.name, token.value);
        }
    }
}

fn class_to_plp(tokens: &Vec<Token>, start_index: usize) -> (usize, String)
{
    let mut plp_string: String = String::new();
    let mut current_index: usize = start_index;

    for (index, token) in tokens.iter().enumerate()
    {
        current_index = index;
    }

    (current_index + 1, plp_string)
}

fn remove_meta(tokens: &mut Vec<Token>)
{
    // Indecies of tokens vector to be removed
    let mut invalid_indecies: Vec<usize> = Vec::new();

    let mut min_index: usize = 0;
    for (index, token) in tokens.iter().enumerate()
    {
        // Allow forward skipping (by setting min_index)
        if index < min_index
        {
            invalid_indecies.push(index);
        }
        // Remove imports
        else if token.name == "special.import"
        {
            invalid_indecies.push(index);
            min_index = index + 2; // skip the next token (semi-colon)
        }
        // Remove comments
        else if token.name.starts_with("comment")
        {
            invalid_indecies.push(index);
        }
        // Remove all modifiers (public, private, volatile, transient, static, etc.)
        else if token.name.starts_with("mod")
        {
            invalid_indecies.push(index);
        }
        // Remove package declarations
        else if token.name == "special.package"
        {
            invalid_indecies.push(index);
            min_index = find_next_semicolon(tokens, index) + 1;
        }
    }

    // count := how many indecies have already been removed
    // index := the index in the original tokens vector that should be removed
    for (count, index) in invalid_indecies.iter().enumerate()
    {
        // "index" refers to the index before any others were removed. Therefore, it must be offset by the number of removed tokens
        tokens.remove(index - count);
    }
}

fn find_next_semicolon(tokens: &Vec<Token>, start: usize) -> usize
{
    for (index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == ";" { return index + start; }
    }

    return 0;
}
<commit_msg>Refactor<commit_after>extern crate regex;

mod matching;
mod support;
mod tokens;
mod lexer;
mod files;
mod parser;

use std::vec::Vec;
use tokens::*;
use lexer::*;
use parser::*;

fn main()
{
    let source_file = "sampleData/BasicArithmatic.java";
    let lex_output_file = "sampleData/output/stable/BasicArithmatic.java.lexed";
    let preprocessed_output_file = "sampleData/output/stable/BasicArithmatic.java.preprocessed";

    let mut tokens: Vec<Token> = lex_file(source_file);

    println!("\n\nFound Tokens:");
    tokens.print_to(lex_output_file, true);

    remove_meta(&mut tokens);
    println!("\n\nPerged Tokens:");
    tokens.print_to(preprocessed_output_file, true);

    compile(tokens);
}

fn compile(tokens: Vec<Token>) -> String
{
    let invalid_types = get_invalid_token_types();
    let invalid_values = get_invalid_token_values();

    let min_index = 0;
    for (index, token) in tokens.iter().enumerate()
    {
        if index < min_index
        {
            continue;
        }

        if invalid_types.contains(&token.name)
        {
            panic!("Unsupported token type: {}", token.name);
        }
        else if invalid_values.contains(&&*token.value)
        {
            panic!("Unsupported token value: {}", token.value);
        }

        if token.value == "class"
        {
            // parse class body
            let (min_index, plp_code) = class_to_plp(&tokens, index);
        }
        /*else if token.name == "type" // || token.type == "identifier"
        {
            // look ahead
            // parse variable declaration
            // OR parse method declaration
        }
        else if token.value == "if"
        {
            // parse if body
            // Unsupported for now
        }
        else if token.name == "construct.conditional"
        {
            // parse conditional
            // Unsupported for now
        }*/
        else
        {
            panic!("Unexpected token: {}\t{}", token.name, token.value);
        }
    }

    String::new()
}

fn class_to_plp(tokens: &Vec<Token>, start_index: usize) -> (usize, String)
{
    let mut plp_string: String = String::new();
    let mut current_index: usize = start_index;

    for (index, token) in tokens.iter().enumerate()
    {
        current_index = index;
    }

    (current_index + 1, plp_string)
}

fn remove_meta(tokens: &mut Vec<Token>)
{
    // Indecies of tokens vector to be removed
    let mut invalid_indecies: Vec<usize> = Vec::new();

    let mut min_index: usize = 0;
    for (index, token) in tokens.iter().enumerate()
    {
        // Allow forward skipping (by setting min_index)
        if index < min_index
        {
            invalid_indecies.push(index);
        }
        // Remove imports
        else if token.name == "special.import"
        {
            invalid_indecies.push(index);
            min_index = index + 2; // skip the next token (semi-colon)
        }
        // Remove comments
        else if token.name.starts_with("comment")
        {
            invalid_indecies.push(index);
        }
        // Remove all modifiers (public, private, volatile, transient, static, etc.)
        else if token.name.starts_with("mod")
        {
            invalid_indecies.push(index);
        }
        // Remove package declarations
        else if token.name == "special.package"
        {
            invalid_indecies.push(index);
            min_index = find_next_semicolon(tokens, index) + 1;
        }
    }

    // count := how many indecies have already been removed
    // index := the index in the original tokens vector that should be removed
    for (count, index) in invalid_indecies.iter().enumerate()
    {
        // "index" refers to the index before any others were removed. Therefore, it must be offset by the number of removed tokens
        tokens.remove(index - count);
    }
}

fn find_next_semicolon(tokens: &Vec<Token>, start: usize) -> usize
{
    for (index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == ";" { return index + start; }
    }

    return 0;
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

use color::Color;
use util::lift_tuple;

pub type Coords = (usize, usize);

pub struct Program {
    size: Coords,
    image: Vec<Color>,
}

impl Program {
    pub fn new(size: Coords, image: Vec<Color>) -> Self {
        Program {
            size: size,
            image: image,
        }
    }

    pub fn get(&self, coords: Coords) -> Option<Color> {
        coords_to_index(coords, &self.size).map(|index| self.image[index])
    }

    /// Find the coordinates of a contiguous area of codels of the same color,
    /// starting from a coordinate.
    ///
    /// TODO: This implementation is recursive, probably not the most optimal.
    /// Fix it if necessary. (Or if you've had enough of the terrible code.)
    /// See also: https://en.wikipedia.org/wiki/Flood_fill
    pub fn color_block(&self, start_coords: Coords) -> HashSet<Coords> {
        let mut result = HashSet::new();

        let start_color = self.get(start_coords).unwrap();
        // TODO: decide if this needs actual error handling

        self.mark_blocks(start_coords, start_color, &mut result);

        result
    }

    /// The recursive part of `color_block`.
    fn mark_blocks(&self, coords: Coords, start_color: Color, marked: &mut HashSet<Coords>) {
        if marked.contains(&coords) {
            return;
        }

        if let Some(color) = self.get(coords) {
            if color != start_color {
                return;
            }

            marked.insert(coords);

            let (x, y) = coords; for neighbor in self.neighbors(coords).iter().filter_map(|&x| x) {
                self.mark_blocks(neighbor, start_color, marked);
            }
        }
    }

    fn neighbors(&self, coords: Coords) -> [Option<Coords>; 4] {
        let (x, y) = coords;

        let right = lift_tuple((Some(x + 1), Some(y)));
        let left = lift_tuple((x.checked_sub(1), Some(y)));
        let above = lift_tuple((Some(x), Some(y + 1)));
        let below = lift_tuple((Some(x), y.checked_sub(1)));

        // I would have written this with iterators, but AFAIK it's not possible
        // to `.collect()` into a fixed size array.
        [right.and_then(|c| self.check_coords(c)),
         left.and_then(|c| self.check_coords(c)),
         above.and_then(|c| self.check_coords(c)),
         below.and_then(|c| self.check_coords(c))]
    }

    fn coords_to_index(&self, coords: Coords) -> Option<usize> {
        coords_to_index(coords, &self.size)
    }

    fn index_to_coords(&self, index: usize) -> Option<Coords> {
        index_to_coords(index, &self.size)
    }

    fn check_coords(&self, coords: Coords) -> Option<Coords> {
        check_coords(coords, &self.size)
    }
}

fn coords_to_index(coords: Coords, size: &(usize, usize)) -> Option<usize> {
    let (x, y) = coords;
    let (width, height) = *size;

    check_coords(coords, size).and(Some(width * y + x % width))
}

fn index_to_coords(index: usize, size: &(usize, usize)) -> Option<Coords> {
    let (width, height) = *size;

    if index >= width * height {
        return None;
    }

    let x = index % width;
    let y = index / width;

    Some((x, y))
}

fn check_coords(coords: Coords, size: &(usize, usize)) -> Option<Coords> {
    let (x, y) = coords;
    let (width, height) = *size;

    if x >= width || y >= height {
        None
    } else {
        Some(coords)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::{coords_to_index, index_to_coords, check_coords};

    #[test]
    fn test_coords_to_index() {
        let size = (5, 5);
        assert_eq!(coords_to_index((0, 0), &size), Some(0));
        assert_eq!(coords_to_index((2, 0), &size), Some(2));
        assert_eq!(coords_to_index((0, 2), &size), Some(10));
        assert_eq!(coords_to_index((2, 2), &size), Some(12));
        assert_eq!(coords_to_index((4, 4), &size), Some(24));
        assert_eq!(coords_to_index((5, 5), &size), None);
    }

    #[test]
    fn test_index_to_coords() {
        let size = (5, 5);
        assert_eq!(index_to_coords(0, &size), Some((0, 0)));
        assert_eq!(index_to_coords(2, &size), Some((2, 0)));
        assert_eq!(index_to_coords(10, &size), Some((0, 2)));
        assert_eq!(index_to_coords(12, &size), Some((2, 2)));
        assert_eq!(index_to_coords(24, &size), Some((4, 4)));
        assert_eq!(index_to_coords(25, &size), None);
    }

    #[test]
    fn test_check_coords() {
        let size =(5, 5);
        assert!(check_coords((0, 0), &size).is_some());
        assert!(check_coords((4, 0), &size).is_some());
        assert!(check_coords((0, 4), &size).is_some());
        assert!(check_coords((4, 4), &size).is_some());
        assert!(check_coords((5, 4), &size).is_none());
        assert!(check_coords((4, 5), &size).is_none());
        assert!(check_coords((5, 5), &size).is_none());
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_program_color_block() {
        use super::super::Color::White as W;
        use super::super::Color::Black as B;

        let program = Program::new((5, 5),
                                   vec![W, W, W, W, W,
                                        W, W, W, W, W,
                                        W, W, B, W, W,
                                        W, W, W, W, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((2, 2)), vec![(2, 2)].into_iter().collect());

        let program = Program::new((5, 5),
                                   vec![B, W, W, W, W,
                                        W, W, W, W, W,
                                        W, W, W, W, W,
                                        W, W, W, W, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((0, 0)), vec![(0, 0)] .into_iter().collect());

        let program = Program::new((5, 5),
                                   vec![W, W, W, W, W,
                                        W, B, B, B, W,
                                        W, B, B, B, W,
                                        W, B, B, B, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((2, 2)), vec![(1, 1), (2, 1), (3, 1),
                                                     (1, 2), (2, 2), (3, 2),
                                                     (1, 3), (2, 3), (3, 3)]
                                                    .into_iter().collect());

        let program = Program::new((5, 5),
                                   vec![W, W, W, W, W,
                                        W, B, B, B, W,
                                        W, B, W, B, W,
                                        W, B, W, B, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((1, 1)), vec![(1, 1), (2, 1), (3, 1),
                                                     (1, 2),         (3, 2),
                                                     (1, 3),         (3, 3)]
                                                    .into_iter().collect());

        let program = Program::new((5, 5),
                                   vec![W, W, W, W, W,
                                        W, B, W, B, W,
                                        W, B, W, B, W,
                                        W, B, W, B, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((1, 1)), vec![(1, 1),
                                                     (1, 2),
                                                     (1, 3)]
                                                    .into_iter().collect());
    }
}
<commit_msg>Make all freestanding `Program`-related functions methods instead<commit_after>use std::collections::HashSet;

use color::Color;
use util::lift_tuple;

pub type Coords = (usize, usize);

pub struct Program {
    size: Coords,
    image: Vec<Color>,
}

impl Program {
    pub fn new(size: Coords, image: Vec<Color>) -> Self {
        Program {
            size: size,
            image: image,
        }
    }

    pub fn get(&self, coords: Coords) -> Option<Color> {
        self.coords_to_index(coords).map(|index| self.image[index])
    }

    /// Find the coordinates of a contiguous area of codels of the same color,
    /// starting from a coordinate.
    ///
    /// TODO: This implementation is recursive, probably not the most optimal.
    /// Fix it if necessary. (Or if you've had enough of the terrible code.)
    /// See also: https://en.wikipedia.org/wiki/Flood_fill
    pub fn color_block(&self, start_coords: Coords) -> HashSet<Coords> {
        let mut result = HashSet::new();

        let start_color = self.get(start_coords).unwrap();
        // TODO: decide if this needs actual error handling

        self.mark_blocks(start_coords, start_color, &mut result);

        result
    }

    /// The recursive part of `color_block`.
    fn mark_blocks(&self, coords: Coords, start_color: Color, marked: &mut HashSet<Coords>) {
        if marked.contains(&coords) {
            return;
        }

        if let Some(color) = self.get(coords) {
            if color != start_color {
                return;
            }

            marked.insert(coords);

            let (x, y) = coords; for neighbor in self.neighbors(coords).iter().filter_map(|&x| x) {
                self.mark_blocks(neighbor, start_color, marked);
            }
        }
    }

    fn neighbors(&self, coords: Coords) -> [Option<Coords>; 4] {
        let (x, y) = coords;

        let right = lift_tuple((Some(x + 1), Some(y)));
        let left = lift_tuple((x.checked_sub(1), Some(y)));
        let above = lift_tuple((Some(x), Some(y + 1)));
        let below = lift_tuple((Some(x), y.checked_sub(1)));

        // I would have written this with iterators, but AFAIK it's not possible
        // to `.collect()` into a fixed size array.
        [right.and_then(|c| self.check_coords(c)),
         left.and_then(|c| self.check_coords(c)),
         above.and_then(|c| self.check_coords(c)),
         below.and_then(|c| self.check_coords(c))]
    }

    fn coords_to_index(&self, coords: Coords) -> Option<usize> {
        let (x, y) = coords;
        let (width, height) = self.size;

        self.check_coords(coords).and(Some(width * y + x % width))
    }

    fn index_to_coords(&self, index: usize) -> Option<Coords> {
        let (width, height) = self.size;

        if index >= width * height {
            return None;
        }

        let x = index % width;
        let y = index / width;

        Some((x, y))
    }

    fn check_coords(&self, coords: Coords) -> Option<Coords> {
        let (x, y) = coords;
        let (width, height) = self.size;

        if x >= width || y >= height {
            None
        } else {
            Some(coords)
        }
    }
}

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

    #[test]
    fn test_program_coords_to_index() {
        let program = Program::new((5, 5), vec![]);
        assert_eq!(program.coords_to_index((0, 0)), Some(0));
        assert_eq!(program.coords_to_index((2, 0)), Some(2));
        assert_eq!(program.coords_to_index((0, 2)), Some(10));
        assert_eq!(program.coords_to_index((2, 2)), Some(12));
        assert_eq!(program.coords_to_index((4, 4)), Some(24));
        assert_eq!(program.coords_to_index((5, 5)), None);
    }

    #[test]
    fn test_program_index_to_coords() {
        let program = Program::new((5, 5), vec![]);
        assert_eq!(program.index_to_coords(0), Some((0, 0)));
        assert_eq!(program.index_to_coords(2), Some((2, 0)));
        assert_eq!(program.index_to_coords(10), Some((0, 2)));
        assert_eq!(program.index_to_coords(12), Some((2, 2)));
        assert_eq!(program.index_to_coords(24), Some((4, 4)));
        assert_eq!(program.index_to_coords(25), None);
    }

    #[test]
    fn test_program_check_coords() {
        let program = Program::new((5, 5), vec![]);
        assert!(program.check_coords((0, 0)).is_some());
        assert!(program.check_coords((4, 0)).is_some());
        assert!(program.check_coords((0, 4)).is_some());
        assert!(program.check_coords((4, 4)).is_some());
        assert!(program.check_coords((5, 4)).is_none());
        assert!(program.check_coords((4, 5)).is_none());
        assert!(program.check_coords((5, 5)).is_none());
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_program_color_block() {
        use super::super::Color::White as W;
        use super::super::Color::Black as B;

        let program = Program::new((5, 5),
                                   vec![W, W, W, W, W,
                                        W, W, W, W, W,
                                        W, W, B, W, W,
                                        W, W, W, W, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((2, 2)), vec![(2, 2)].into_iter().collect());

        let program = Program::new((5, 5),
                                   vec![B, W, W, W, W,
                                        W, W, W, W, W,
                                        W, W, W, W, W,
                                        W, W, W, W, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((0, 0)), vec![(0, 0)] .into_iter().collect());

        let program = Program::new((5, 5),
                                   vec![W, W, W, W, W,
                                        W, B, B, B, W,
                                        W, B, B, B, W,
                                        W, B, B, B, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((2, 2)), vec![(1, 1), (2, 1), (3, 1),
                                                     (1, 2), (2, 2), (3, 2),
                                                     (1, 3), (2, 3), (3, 3)]
                                                    .into_iter().collect());

        let program = Program::new((5, 5),
                                   vec![W, W, W, W, W,
                                        W, B, B, B, W,
                                        W, B, W, B, W,
                                        W, B, W, B, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((1, 1)), vec![(1, 1), (2, 1), (3, 1),
                                                     (1, 2),         (3, 2),
                                                     (1, 3),         (3, 3)]
                                                    .into_iter().collect());

        let program = Program::new((5, 5),
                                   vec![W, W, W, W, W,
                                        W, B, W, B, W,
                                        W, B, W, B, W,
                                        W, B, W, B, W,
                                        W, W, W, W, W]);
        assert_eq!(program.color_block((1, 1)), vec![(1, 1),
                                                     (1, 2),
                                                     (1, 3)]
                                                    .into_iter().collect());
    }
}
<|endoftext|>


<commit_before><commit_msg>remove accidentally committed sensitive data<commit_after><|endoftext|>


<commit_before>//! Represents the state of the engine.

#![allow(dead_code)]

use std::time::Duration;

use game::{Position, Color, Move, NumMoves, NumPlies};
use types::NumNodes;

pub use self::TimeData::{TimeLeft, ExactTime};

pub struct State {
    pub is_debug: bool,
    pub my_side: Color,
    pub pos: Position,
    pub start_search: u64,
    pub search_param: SearchParam,
    pub time_data: TimeData,
}
impl State {
    pub fn is_my_turn(&self) -> bool {
        self.my_side == self.pos.side_to_move()
    }
}

pub struct SearchParam {
    pub search_moves: Option<Vec<Move>>,
    pub depth: Option<NumPlies>,
    pub nodes: Option<NumNodes>,
    pub mate: Option<NumMoves>,
}

#[deriving(Copy, Clone)]
pub enum TimeData {
    TimeLeft(TimeLeftData),
    ExactTime(Duration),
}

#[deriving(Copy, Clone)]
pub struct TimeLeftData {
    pub w_time: Duration,
    pub b_time: Duration,
    pub w_inc: Duration,
    pub b_inc: Duration,
    pub moves_to_go: NumMoves,
}
<commit_msg>Edit state module.<commit_after>//! Represents the state of the engine.

#![allow(dead_code)]

use std::time::Duration;

use game::{Position, Color, Move, NumMoves, NumPlies};
use types::NumNodes;

pub use self::TimeData::{TimeLeft, ExactTime};

#[deriving(Clone)]
pub struct State {
    pub is_debug: bool,
    pub pos: Position,
    pub start_search: u64,
    pub search_param: SearchParam,
    pub time_data: TimeData,
}

#[deriving(Clone)]
pub struct SearchParam {
    pub ponder: Option<(Position, Move)>,
    pub search_moves: Option<Vec<Move>>,
    pub depth: Option<NumPlies>,
    pub nodes: Option<NumNodes>,
    pub mate: Option<NumMoves>,
}

#[deriving(Copy, Clone)]
pub enum TimeData {
    TimeLeft(TimeLeftData),
    ExactTime(Duration),
}

#[deriving(Copy, Clone)]
pub struct TimeLeftData {
    pub w_time: Duration,
    pub b_time: Duration,
    pub w_inc: Duration,
    pub b_inc: Duration,
    pub moves_to_go: NumMoves,
}
impl TimeLeftData {
    pub fn time(&self, c: Color) -> Duration {
        match c {
            Color::White => self.w_time,
            Color::Black => self.b_time,
        }
    }
    pub fn set_time(&mut self, c: Color, val: Duration) {
        match c {
            Color::White => self.w_time = val,
            Color::Black => self.b_time = val,
        }
    }
    pub fn inc(&self, c: Color) -> Duration {
        match c {
            Color::White => self.w_inc,
            Color::Black => self.b_inc,
        }
    }
    pub fn set_inc(&mut self, c: Color, val: Duration) {
        match c {
            Color::White => self.w_inc = val,
            Color::Black => self.b_inc = val,
        }
    }
}
<|endoftext|>


<commit_before>use position::Position;
use cppn::{Cppn, CppnNodeType};
use std::fmt::Debug;

/// Represents a node in the substrate. `T` is an arbitrary
/// type used to store additional information about that node.
pub struct Node<P: Position, T> {
    pub position: P,
    pub data: T,
}

pub struct Substrate<P: Position, T> {
    nodes: Vec<Node<P, T>>,
}

pub struct LinkIterator<'a,
                        N: CppnNodeType + 'a,
                        L: Copy + Debug + Send + Sized + Into<f64> + 'a,
                        EXTID: Copy + Debug + Send + Sized + Ord + 'a,
                        P: Position + 'a,
                        T: 'a>
{
    nodes: &'a [Node<P, T>],
    cppn: &'a mut Cppn<'a, N, L, EXTID>,
    inner: usize,
    outer: usize,
    max_distance: Option<f64>,
}

#[derive(Copy, Clone)]
pub struct Link<'a, P: Position + 'a, T: 'a> {
    pub source: &'a Node<P, T>,
    pub target: &'a Node<P, T>,
    pub source_idx: usize,
    pub target_idx: usize,
    pub weight: f64,
    pub distance: f64,
}

impl<'a, N: CppnNodeType + 'a,
   L: Copy + Debug + Send + Sized + Into<f64> + 'a,
    EXTID: Copy + Debug + Send + Sized + Ord + 'a,
P: Position + 'a, T: 'a> Iterator for LinkIterator<'a, N, L, EXTID, P, T> {
    type Item = Link<'a, P, T>;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.inner >= self.nodes.len() {
                self.inner = 0;
                self.outer += 1;
            }
            if self.outer >= self.nodes.len() {
                return None;
            }
            if self.inner == self.outer {
                self.inner += 1;
                continue;
            }

            assert!(self.inner < self.nodes.len() && self.outer < self.nodes.len() &&
                    self.inner != self.outer);
            let source = &self.nodes[self.inner];
            let target = &self.nodes[self.outer];
            let distance = source.position.distance(&target.position);

// reject a pair of nodes based on `max_distance`.
            if let Some(max_d) = self.max_distance {
                if distance > max_d {
                    self.inner += 1;
                    continue;
                }
            }

// Calculate the weight between source and target using the CPPN.
            let inputs_to_cppn = [source.position.coords(), target.position.coords()];
            let outputs_from_cppn = self.cppn.calculate(&inputs_to_cppn);
            assert!(outputs_from_cppn.len() == 1);
            let weight = outputs_from_cppn[0];

            let link = Link {
                source: source,
                target: target,
                source_idx: self.inner,
                target_idx: self.outer,
                weight: weight,
                distance: distance,
            };
            self.inner += 1;
            return Some(link);
        }
    }
}

impl<P: Position, T> Substrate<P, T> {
    pub fn new() -> Substrate<P, T> {
        Substrate { nodes: Vec::new() }
    }

    pub fn nodes(&self) -> &[Node<P, T>] {
        &self.nodes
    }

    pub fn add_node(&mut self, position: P, data: T) {
        self.nodes.push(Node {
            position: position,
            data: data,
        });
    }

    /// Iterate over all produced links of Cppn.
    pub fn iter_links<'a, N, L, EXTID>(&'a self,
                                       cppn: &'a mut Cppn<'a, N, L, EXTID>,
                                       max_distance: Option<f64>)
                                       -> LinkIterator<'a, N, L, EXTID, P, T>
        where N: CppnNodeType,
              L: Copy + Debug + Send + Sized + Into<f64> + 'a,
              EXTID: Copy + Debug + Send + Sized + Ord + 'a
    {
        LinkIterator {
            nodes: &self.nodes,
            cppn: cppn,
            inner: 0,
            outer: 0,
            max_distance: max_distance,
        }
    }
}
<commit_msg>Reject invalid connections<commit_after>use position::Position;
use cppn::{Cppn, CppnNodeType};
use acyclic_network::NodeType;
use std::fmt::Debug;

/// Represents a node in the substrate. `T` stores  additional information about that node.

pub struct Node<P: Position, T: NodeType> {
    pub position: P,
    pub node_type: T,
}

pub struct Substrate<P: Position, T: NodeType> {
    nodes: Vec<Node<P, T>>,
}

pub struct LinkIterator<'a,
                        N: CppnNodeType + 'a,
                        L: Copy + Debug + Send + Sized + Into<f64> + 'a,
                        EXTID: Copy + Debug + Send + Sized + Ord + 'a,
                        P: Position + 'a,
                        T: NodeType + 'a>
{
    nodes: &'a [Node<P, T>],
    cppn: &'a mut Cppn<'a, N, L, EXTID>,
    inner: usize,
    outer: usize,
    max_distance: Option<f64>,
}

#[derive(Copy, Clone)]
pub struct Link<'a, P: Position + 'a, T: NodeType + 'a> {
    pub source: &'a Node<P, T>,
    pub target: &'a Node<P, T>,
    pub source_idx: usize,
    pub target_idx: usize,
    pub weight: f64,
    pub distance: f64,
}

impl<'a, N: CppnNodeType + 'a,
   L: Copy + Debug + Send + Sized + Into<f64> + 'a,
    EXTID: Copy + Debug + Send + Sized + Ord + 'a,
P: Position + 'a, T: NodeType + 'a> Iterator for LinkIterator<'a, N, L, EXTID, P, T> {
    type Item = Link<'a, P, T>;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.inner >= self.nodes.len() {
                self.inner = 0;
                self.outer += 1;
            }
            if self.outer >= self.nodes.len() {
                return None;
            }
            if self.inner == self.outer {
                self.inner += 1;
                continue;
            }

            assert!(self.inner < self.nodes.len() && self.outer < self.nodes.len() &&
                    self.inner != self.outer);
            let source = &self.nodes[self.inner];
            let target = &self.nodes[self.outer];

            // Reject invalid connections.
            if !source.node_type.accept_outgoing_links() || !target.node_type.accept_incoming_links() {
                    self.inner += 1;
                    continue;
            }

            let distance = source.position.distance(&target.position);

// reject a pair of nodes based on `max_distance`.
            if let Some(max_d) = self.max_distance {
                if distance > max_d {
                    self.inner += 1;
                    continue;
                }
            }

// Calculate the weight between source and target using the CPPN.
            let inputs_to_cppn = [source.position.coords(), target.position.coords()];
            let outputs_from_cppn = self.cppn.calculate(&inputs_to_cppn);
            assert!(outputs_from_cppn.len() == 1);
            let weight = outputs_from_cppn[0];

            let link = Link {
                source: source,
                target: target,
                source_idx: self.inner,
                target_idx: self.outer,
                weight: weight,
                distance: distance,
            };
            self.inner += 1;
            return Some(link);
        }
    }
}

impl<P: Position, T: NodeType> Substrate<P, T> {
    pub fn new() -> Substrate<P, T> {
        Substrate { nodes: Vec::new() }
    }

    pub fn nodes(&self) -> &[Node<P, T>] {
        &self.nodes
    }

    pub fn add_node(&mut self, position: P, node_type: T) {
        self.nodes.push(Node {
            position: position,
            node_type: node_type,
        });
    }

    /// Iterate over all produced links of Cppn.
    pub fn iter_links<'a, N, L, EXTID>(&'a self,
                                       cppn: &'a mut Cppn<'a, N, L, EXTID>,
                                       max_distance: Option<f64>)
                                       -> LinkIterator<'a, N, L, EXTID, P, T>
        where N: CppnNodeType,
              L: Copy + Debug + Send + Sized + Into<f64> + 'a,
              EXTID: Copy + Debug + Send + Sized + Ord + 'a
    {
        LinkIterator {
            nodes: &self.nodes,
            cppn: cppn,
            inner: 0,
            outer: 0,
            max_distance: max_distance,
        }
    }
}
<|endoftext|>