<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

#![crate_name="calculator"]
#![crate_type="bin"]

extern crate thrift;

use std::io::net::ip;
use thrift::protocol::{MessageType, Type};
use thrift::transport::Transport;
use thrift::protocol::Protocol;
use thrift::protocol::binary_protocol::BinaryProtocol;

trait Readable {
    fn read(& mut self, iprot: &Protocol, transport: & mut Transport) -> bool;
}

// TODO: shall be generated
//#[allow(dead_code)]
struct CalculatorPingArgs;

impl CalculatorPingArgs {

    #[allow(unused_variables)]
    fn write(&self, oprot: &Protocol, transport: & mut Transport) {
        oprot.write_struct_begin(transport, "Calculator_ping_args");
        oprot.write_field_stop(transport);
        oprot.write_struct_end(transport);
    }
}

struct CalculatorPingResult;

impl CalculatorPingResult {

    fn read(&self, iprot: &Protocol, transport: & mut Transport) {
        iprot.skip(transport, Type::TStruct);
    }
}

struct CalculatorAddArgs {
    num1: i32,
    num2: i32,
}

impl CalculatorAddArgs {

    #[allow(unused_variables)]
    fn write(&self, oprot: &Protocol, transport: & mut Transport) {
        oprot.write_struct_begin(transport, "Calculator_add_args");

        oprot.write_field_begin(transport, "num1", Type::TI32, 1);
        oprot.write_i32(transport, self.num1);
        oprot.write_field_end(transport);

        oprot.write_field_begin(transport, "num2", Type::TI32, 2);
        oprot.write_i32(transport, self.num2);
        oprot.write_field_end(transport);

        oprot.write_field_stop(transport);
        oprot.write_struct_end(transport);
    }
}

struct CalculatorAddResult {
    success: Option<i32>,
}

impl Readable for CalculatorAddResult {

    #[allow(unused_variables)]
    fn read(& mut self, iprot: &Protocol, transport: & mut Transport) -> bool {
        let mut have_result = false;

        iprot.read_struct_begin(transport);

        loop {
            let (fname, ftype, fid) = iprot.read_field_begin(transport);
            if ftype == Type::TStop {
                break;
            }
            match (fid, ftype) {
                (0, Type::TI32) => {
                    self.success = Some(iprot.read_i32(transport));
                    have_result = true
                }
                _ => {
                    iprot.skip(transport, ftype);
                }
            }
            iprot.read_field_end(transport);
        }
        iprot.read_struct_end(transport);
        have_result
    }
}

#[derive(Copy)]
#[allow(dead_code)]
enum Operation {
    ADD = 1,
    SUBTRACT = 2,
    MULTIPLY = 3,
    DIVIDE = 4,
}

struct Work {
    num1: i32,
    num2: i32,
    op: Operation,
    comment: Option<String>,
}

impl Work {

    #[allow(unused_variables)]
    fn write(&self, oprot: &Protocol, transport: & mut Transport) {
        oprot.write_struct_begin(transport, "Work");

        oprot.write_field_begin(transport, "num1", Type::TI32, 1);
        oprot.write_i32(transport, self.num1);
        oprot.write_field_end(transport);

        oprot.write_field_begin(transport, "num2", Type::TI32, 2);
        oprot.write_i32(transport, self.num2);
        oprot.write_field_end(transport);

        oprot.write_field_begin(transport, "op", Type::TI32, 3);
        oprot.write_i32(transport, self.op as i32);
        oprot.write_field_end(transport);

        if self.comment.is_some() {
            // FIXME
            //oprot.write_field_begin(transport, "comment", Type::TString, 4);
            //oprot.write_string(transport, self.comment.unwrap().as_slice());
            //oprot.write_field_end(transport);
        }

        oprot.write_field_stop(transport);
        oprot.write_struct_end(transport);
    }
}

struct CalculatorCalculateArgs {
    logid: i32,
    w: Work,
}

impl CalculatorCalculateArgs {

    #[allow(unused_variables)]
    fn write(&self, oprot: &Protocol, transport: & mut Transport) {
        oprot.write_struct_begin(transport, "Calculator_calculate_args");

        oprot.write_field_begin(transport, "logid", Type::TI32, 1);
        oprot.write_i32(transport, self.logid);
        oprot.write_field_end(transport);

        oprot.write_field_begin(transport, "work", Type::TStruct, 2);
        self.w.write(oprot, transport);
        oprot.write_field_end(transport);

        oprot.write_field_stop(transport);
        oprot.write_struct_end(transport);
    }
}

struct Exception;

#[allow(dead_code)]
struct CalculatorCalculateResult {
    success: Option<i32>,
    ouch: Exception
}

impl Readable for CalculatorCalculateResult {

    #[allow(unused_variables)]
    fn read(& mut self, iprot: &Protocol, transport: & mut Transport) -> bool {
        let mut have_result = false;

        iprot.read_struct_begin(transport);

        loop {
            let (fname, ftype, fid) = iprot.read_field_begin(transport);
            if ftype == Type::TStop {
                break;
            }
            match (fid, ftype) {
                (0, Type::TI32) => {
                    self.success = Some(iprot.read_i32(transport));
                    have_result = true;
                }
                (1, Type::TStruct) => {
                    // FIXME read ouch
                    iprot.skip(transport, ftype);
                }
                _ => {
                    iprot.skip(transport, ftype);
                }
            }
            iprot.read_field_end(transport);
        }
        iprot.read_struct_end(transport);
        have_result
    }
}

struct CalculatorClient<T: Transport, P: Protocol> {
    transport: T,
    protocol: P,
}

impl <T: Transport, P: Protocol> CalculatorClient<T, P> {

    fn ping(& mut self) {
        self.send_ping();
        self.receive_ping();
    }

    #[allow(unused_variables)]
    fn send_ping(& mut self) {
        let cseqid: i32 = 0;
        self.protocol.write_message_begin(& mut self.transport, "ping", MessageType::MtCall, cseqid);

        let args = CalculatorPingArgs;
        args.write(&self.protocol, & mut self.transport);

        self.protocol.write_message_end(& mut self.transport);

        //self.transport.write_end();
        self.transport.flush().unwrap();
    }

    #[allow(unused_variables)]
    fn receive_ping(& mut self) {
      let (fname, mtype, rseqid) = self.protocol.read_message_begin(& mut self.transport);
      match mtype {
        MessageType::MtException => {
            // TODO
            //let x = ApplicationException;
            //x.read(& mut self protocol)
            //self.protocol.read_message_end();
            //transport.read_end();
            //throw x
        }
        MessageType::MtReply => {
            match fname.as_slice() {
                "ping" => {
                    let result = CalculatorPingResult;
                    result.read(&self.protocol, & mut self.transport);
                }
                _ => {
                    self.protocol.skip(& mut self.transport, Type::TStruct);
                }
            }
            self.protocol.read_message_end(& mut self.transport);
            //self.transport.read_end();
        }
        _ => {
            self.protocol.skip(& mut self.transport, Type::TStruct);
            self.protocol.read_message_end(& mut self.transport);
            //self.transport.read_end();
        }
      }
    }

    fn add(& mut self, num1: i32, num2: i32) -> Option<i32> {
        self.send_add(num1, num2);
        self.receive_add()
    }

    fn send_add(& mut self, num1: i32, num2: i32) {
        let cseqid: i32 = 0;
        self.protocol.write_message_begin(& mut self.transport, "add", MessageType::MtCall, cseqid);

        let args = CalculatorAddArgs { num1: num1, num2: num2 };
        args.write(&self.protocol, & mut self.transport);

        self.protocol.write_message_end(& mut self.transport);

        //self.transport.write_end();
        self.transport.flush().unwrap();
    }

    fn receive_add(& mut self) -> Option<i32> {
        let mut result = CalculatorAddResult { success: None };
        if self.receive("add", &mut result) { result.success } else { None }
    }

    #[allow(unused_variables)]
    fn receive<R: Readable>(& mut self, op: &'static str, result: &mut R) -> bool {
        let mut have_result = false;
        let (fname, mtype, rseqid) = self.protocol.read_message_begin(& mut self.transport);
        match mtype {
            MessageType::MtException => {
                // TODO
                //let x = ApplicationException;
                //x.read(& mut self protocol)
                //self.protocol.read_message_end();
                //transport.read_end();
                //throw x
            }
            MessageType::MtReply => {
                if fname.as_slice() == op {
                    have_result = result.read(&self.protocol, & mut self.transport);
                }
                else {
                    self.protocol.skip(& mut self.transport, Type::TStruct);
                }
                self.protocol.read_message_end(& mut self.transport);
                //self.transport.read_end();
            }
            _ => {
                self.protocol.skip(& mut self.transport, Type::TStruct);
                self.protocol.read_message_end(& mut self.transport);
                //self.transport.read_end();
            }
        }
        have_result
    }

    fn calculate(& mut self, logid: i32, w: Work) -> Option<i32> {
        self.send_calculate(logid, w);
        self.receive_calculate()
    }

    fn send_calculate(& mut self, logid: i32,  w: Work) {
        let cseqid: i32 = 0;
        self.protocol.write_message_begin(& mut self.transport, "calculate", MessageType::MtCall, cseqid);

        let args = CalculatorCalculateArgs { logid: logid, w: w };
        args.write(&self.protocol, & mut self.transport);

        self.protocol.write_message_end(& mut self.transport);

        //self.transport.write_end();
        self.transport.flush().unwrap();
    }

    fn receive_calculate(& mut self) -> Option<i32> {
        let mut result = CalculatorCalculateResult { success: None, ouch: Exception };
        // FIXME: handle exception
        if self.receive("calculate", &mut result) { result.success } else { None }
    }

}

pub fn main() {
    let server_address = "127.0.0.1:9090";
    let addr: ip::SocketAddr = std::str::FromStr::from_str(server_address)
        .expect("bad server address");
    let tcp = std::io::TcpStream::connect(addr).unwrap();

    let mut client = CalculatorClient{ protocol: BinaryProtocol, transport: tcp };

    client.ping();
    println!("ping()");

    println!("1 + 1 = {}", client.add(1, 1).unwrap());

    let work = Work { op: Operation::DIVIDE, num1: 1, num2: 0, comment: None };

    match client.calculate(1, work) {
      Some(_) => {
        println!("Whoa? We can divide by zero!");
      }
      None => {
        // FIXME: use thrift exceptions
        println!("Invalid operation")
      }
    }

    let work = Work { op: Operation::SUBTRACT, num1: 15, num2: 10, comment: None };
    println!("15 - 10 = {}", client.calculate(2, work).unwrap());

    println!("PASS");
}
<commit_msg>Fixed writing the comment field by using matching<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

#![crate_name="calculator"]
#![crate_type="bin"]

extern crate thrift;

use std::io::net::ip;
use thrift::protocol::{MessageType, Type};
use thrift::transport::Transport;
use thrift::protocol::Protocol;
use thrift::protocol::binary_protocol::BinaryProtocol;

trait Readable {
    fn read(& mut self, iprot: &Protocol, transport: & mut Transport) -> bool;
}

// TODO: shall be generated
//#[allow(dead_code)]
struct CalculatorPingArgs;

impl CalculatorPingArgs {

    #[allow(unused_variables)]
    fn write(&self, oprot: &Protocol, transport: & mut Transport) {
        oprot.write_struct_begin(transport, "Calculator_ping_args");
        oprot.write_field_stop(transport);
        oprot.write_struct_end(transport);
    }
}

struct CalculatorPingResult;

impl CalculatorPingResult {

    fn read(&self, iprot: &Protocol, transport: & mut Transport) {
        iprot.skip(transport, Type::TStruct);
    }
}

struct CalculatorAddArgs {
    num1: i32,
    num2: i32,
}

impl CalculatorAddArgs {

    #[allow(unused_variables)]
    fn write(&self, oprot: &Protocol, transport: & mut Transport) {
        oprot.write_struct_begin(transport, "Calculator_add_args");

        oprot.write_field_begin(transport, "num1", Type::TI32, 1);
        oprot.write_i32(transport, self.num1);
        oprot.write_field_end(transport);

        oprot.write_field_begin(transport, "num2", Type::TI32, 2);
        oprot.write_i32(transport, self.num2);
        oprot.write_field_end(transport);

        oprot.write_field_stop(transport);
        oprot.write_struct_end(transport);
    }
}

struct CalculatorAddResult {
    success: Option<i32>,
}

impl Readable for CalculatorAddResult {

    #[allow(unused_variables)]
    fn read(& mut self, iprot: &Protocol, transport: & mut Transport) -> bool {
        let mut have_result = false;

        iprot.read_struct_begin(transport);

        loop {
            let (fname, ftype, fid) = iprot.read_field_begin(transport);
            if ftype == Type::TStop {
                break;
            }
            match (fid, ftype) {
                (0, Type::TI32) => {
                    self.success = Some(iprot.read_i32(transport));
                    have_result = true
                }
                _ => {
                    iprot.skip(transport, ftype);
                }
            }
            iprot.read_field_end(transport);
        }
        iprot.read_struct_end(transport);
        have_result
    }
}

#[derive(Copy)]
#[allow(dead_code)]
enum Operation {
    ADD = 1,
    SUBTRACT = 2,
    MULTIPLY = 3,
    DIVIDE = 4,
}

struct Work {
    num1: i32,
    num2: i32,
    op: Operation,
    comment: Option<String>,
}

impl Work {

    #[allow(unused_variables)]
    fn write(&self, oprot: &Protocol, transport: & mut Transport) {
        oprot.write_struct_begin(transport, "Work");

        oprot.write_field_begin(transport, "num1", Type::TI32, 1);
        oprot.write_i32(transport, self.num1);
        oprot.write_field_end(transport);

        oprot.write_field_begin(transport, "num2", Type::TI32, 2);
        oprot.write_i32(transport, self.num2);
        oprot.write_field_end(transport);

        oprot.write_field_begin(transport, "op", Type::TI32, 3);
        oprot.write_i32(transport, self.op as i32);
        oprot.write_field_end(transport);

        match self.comment {
            Some(ref s) => {
                oprot.write_field_begin(transport, "comment", Type::TString, 4);
                oprot.write_string(transport, s.as_slice());
                oprot.write_field_end(transport);
            }
            _ => {}
        }

        oprot.write_field_stop(transport);
        oprot.write_struct_end(transport);
    }
}

struct CalculatorCalculateArgs {
    logid: i32,
    w: Work,
}

impl CalculatorCalculateArgs {

    #[allow(unused_variables)]
    fn write(&self, oprot: &Protocol, transport: & mut Transport) {
        oprot.write_struct_begin(transport, "Calculator_calculate_args");

        oprot.write_field_begin(transport, "logid", Type::TI32, 1);
        oprot.write_i32(transport, self.logid);
        oprot.write_field_end(transport);

        oprot.write_field_begin(transport, "work", Type::TStruct, 2);
        self.w.write(oprot, transport);
        oprot.write_field_end(transport);

        oprot.write_field_stop(transport);
        oprot.write_struct_end(transport);
    }
}

struct Exception;

#[allow(dead_code)]
struct CalculatorCalculateResult {
    success: Option<i32>,
    ouch: Exception
}

impl Readable for CalculatorCalculateResult {

    #[allow(unused_variables)]
    fn read(& mut self, iprot: &Protocol, transport: & mut Transport) -> bool {
        let mut have_result = false;

        iprot.read_struct_begin(transport);

        loop {
            let (fname, ftype, fid) = iprot.read_field_begin(transport);
            if ftype == Type::TStop {
                break;
            }
            match (fid, ftype) {
                (0, Type::TI32) => {
                    self.success = Some(iprot.read_i32(transport));
                    have_result = true;
                }
                (1, Type::TStruct) => {
                    // FIXME read ouch
                    iprot.skip(transport, ftype);
                }
                _ => {
                    iprot.skip(transport, ftype);
                }
            }
            iprot.read_field_end(transport);
        }
        iprot.read_struct_end(transport);
        have_result
    }
}

struct CalculatorClient<T: Transport, P: Protocol> {
    transport: T,
    protocol: P,
}

impl <T: Transport, P: Protocol> CalculatorClient<T, P> {

    fn ping(& mut self) {
        self.send_ping();
        self.receive_ping();
    }

    #[allow(unused_variables)]
    fn send_ping(& mut self) {
        let cseqid: i32 = 0;
        self.protocol.write_message_begin(& mut self.transport, "ping", MessageType::MtCall, cseqid);

        let args = CalculatorPingArgs;
        args.write(&self.protocol, & mut self.transport);

        self.protocol.write_message_end(& mut self.transport);

        //self.transport.write_end();
        self.transport.flush().unwrap();
    }

    #[allow(unused_variables)]
    fn receive_ping(& mut self) {
      let (fname, mtype, rseqid) = self.protocol.read_message_begin(& mut self.transport);
      match mtype {
        MessageType::MtException => {
            // TODO
            //let x = ApplicationException;
            //x.read(& mut self protocol)
            //self.protocol.read_message_end();
            //transport.read_end();
            //throw x
        }
        MessageType::MtReply => {
            match fname.as_slice() {
                "ping" => {
                    let result = CalculatorPingResult;
                    result.read(&self.protocol, & mut self.transport);
                }
                _ => {
                    self.protocol.skip(& mut self.transport, Type::TStruct);
                }
            }
            self.protocol.read_message_end(& mut self.transport);
            //self.transport.read_end();
        }
        _ => {
            self.protocol.skip(& mut self.transport, Type::TStruct);
            self.protocol.read_message_end(& mut self.transport);
            //self.transport.read_end();
        }
      }
    }

    fn add(& mut self, num1: i32, num2: i32) -> Option<i32> {
        self.send_add(num1, num2);
        self.receive_add()
    }

    fn send_add(& mut self, num1: i32, num2: i32) {
        let cseqid: i32 = 0;
        self.protocol.write_message_begin(& mut self.transport, "add", MessageType::MtCall, cseqid);

        let args = CalculatorAddArgs { num1: num1, num2: num2 };
        args.write(&self.protocol, & mut self.transport);

        self.protocol.write_message_end(& mut self.transport);

        //self.transport.write_end();
        self.transport.flush().unwrap();
    }

    fn receive_add(& mut self) -> Option<i32> {
        let mut result = CalculatorAddResult { success: None };
        if self.receive("add", &mut result) { result.success } else { None }
    }

    #[allow(unused_variables)]
    fn receive<R: Readable>(& mut self, op: &'static str, result: &mut R) -> bool {
        let mut have_result = false;
        let (fname, mtype, rseqid) = self.protocol.read_message_begin(& mut self.transport);
        match mtype {
            MessageType::MtException => {
                // TODO
                //let x = ApplicationException;
                //x.read(& mut self protocol)
                //self.protocol.read_message_end();
                //transport.read_end();
                //throw x
            }
            MessageType::MtReply => {
                if fname.as_slice() == op {
                    have_result = result.read(&self.protocol, & mut self.transport);
                }
                else {
                    self.protocol.skip(& mut self.transport, Type::TStruct);
                }
                self.protocol.read_message_end(& mut self.transport);
                //self.transport.read_end();
            }
            _ => {
                self.protocol.skip(& mut self.transport, Type::TStruct);
                self.protocol.read_message_end(& mut self.transport);
                //self.transport.read_end();
            }
        }
        have_result
    }

    fn calculate(& mut self, logid: i32, w: Work) -> Option<i32> {
        self.send_calculate(logid, w);
        self.receive_calculate()
    }

    fn send_calculate(& mut self, logid: i32,  w: Work) {
        let cseqid: i32 = 0;
        self.protocol.write_message_begin(& mut self.transport, "calculate", MessageType::MtCall, cseqid);

        let args = CalculatorCalculateArgs { logid: logid, w: w };
        args.write(&self.protocol, & mut self.transport);

        self.protocol.write_message_end(& mut self.transport);

        //self.transport.write_end();
        self.transport.flush().unwrap();
    }

    fn receive_calculate(& mut self) -> Option<i32> {
        let mut result = CalculatorCalculateResult { success: None, ouch: Exception };
        // FIXME: handle exception
        if self.receive("calculate", &mut result) { result.success } else { None }
    }

}

pub fn main() {
    let server_address = "127.0.0.1:9090";
    let addr: ip::SocketAddr = std::str::FromStr::from_str(server_address)
        .expect("bad server address");
    let tcp = std::io::TcpStream::connect(addr).unwrap();

    let mut client = CalculatorClient{ protocol: BinaryProtocol, transport: tcp };

    client.ping();
    println!("ping()");

    println!("1 + 1 = {}", client.add(1, 1).unwrap());

    let work = Work { op: Operation::DIVIDE, num1: 1, num2: 0, comment: None };

    match client.calculate(1, work) {
      Some(_) => {
        println!("Whoa? We can divide by zero!");
      }
      None => {
        // FIXME: use thrift exceptions
        println!("Invalid operation")
      }
    }

    let work = Work { op: Operation::SUBTRACT, num1: 15, num2: 10, comment: None };
    println!("15 - 10 = {}", client.calculate(2, work).unwrap());

    println!("PASS");
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;
extern crate fake;
extern crate maxminddb;
extern crate rayon;

use criterion::Criterion;
use fake::faker::internet::raw::*;
use fake::locales::EN;
use fake::Fake;
use maxminddb::geoip2;
use rayon::prelude::*;

use std::net::IpAddr;
use std::str::FromStr;

// Generate `count` IPv4 addresses
pub fn generate_ipv4(count: u64) -> Vec<IpAddr> {
    let mut ips = Vec::new();
    for _i in 0..count {
        let val: String = IPv4(EN).fake();
        let ip: IpAddr = FromStr::from_str(&val).unwrap();
        ips.push(ip);
    }
    ips
}

// Single-threaded
pub fn bench_maxminddb(ips: &Vec<IpAddr>, reader: &maxminddb::Reader<Vec<u8>>) {
    ips.iter().for_each(|ip| {
        let _ = reader.lookup::<geoip2::City>(*ip);
    });
}

// Using rayon for parallel execution
pub fn bench_par_maxminddb(ips: &Vec<IpAddr>, reader: &maxminddb::Reader<Vec<u8>>) {
    ips.par_iter().for_each(|ip| {
        let _ = reader.lookup::<geoip2::City>(*ip);
    });
}

pub fn criterion_benchmark(c: &mut Criterion) {
    let ips = generate_ipv4(100);
    let reader = maxminddb::Reader::open_readfile("GeoIP2-City.mmdb").unwrap();

    c.bench_function("maxminddb", |b| b.iter(|| bench_maxminddb(&ips, &reader)));
}

pub fn criterion_par_benchmark(c: &mut Criterion) {
    let ips = generate_ipv4(100);
    let reader = maxminddb::Reader::open_readfile("GeoIP2-City.mmdb").unwrap();

    c.bench_function("maxminddb_par", |b| {
        b.iter(|| bench_par_maxminddb(&ips, &reader))
    });
}

criterion_group! {
    name = benches;
    config = Criterion::default()
        .sample_size(10);

    targets = criterion_benchmark, criterion_par_benchmark
}
criterion_main!(benches);
<commit_msg>Make clippy happy<commit_after>#[macro_use]
extern crate criterion;
extern crate fake;
extern crate maxminddb;
extern crate rayon;

use criterion::Criterion;
use fake::faker::internet::raw::*;
use fake::locales::EN;
use fake::Fake;
use maxminddb::geoip2;
use rayon::prelude::*;

use std::net::IpAddr;
use std::str::FromStr;

// Generate `count` IPv4 addresses
pub fn generate_ipv4(count: u64) -> Vec<IpAddr> {
    let mut ips = Vec::new();
    for _i in 0..count {
        let val: String = IPv4(EN).fake();
        let ip: IpAddr = FromStr::from_str(&val).unwrap();
        ips.push(ip);
    }
    ips
}

// Single-threaded
pub fn bench_maxminddb(ips: &[IpAddr], reader: &maxminddb::Reader<Vec<u8>>) {
    ips.iter().for_each(|ip| {
        let _ = reader.lookup::<geoip2::City>(*ip);
    });
}

// Using rayon for parallel execution
pub fn bench_par_maxminddb(ips: &[IpAddr], reader: &maxminddb::Reader<Vec<u8>>) {
    ips.par_iter().for_each(|ip| {
        let _ = reader.lookup::<geoip2::City>(*ip);
    });
}

pub fn criterion_benchmark(c: &mut Criterion) {
    let ips = generate_ipv4(100);
    let reader = maxminddb::Reader::open_readfile("GeoIP2-City.mmdb").unwrap();

    c.bench_function("maxminddb", |b| b.iter(|| bench_maxminddb(&ips, &reader)));
}

pub fn criterion_par_benchmark(c: &mut Criterion) {
    let ips = generate_ipv4(100);
    let reader = maxminddb::Reader::open_readfile("GeoIP2-City.mmdb").unwrap();

    c.bench_function("maxminddb_par", |b| {
        b.iter(|| bench_par_maxminddb(&ips, &reader))
    });
}

criterion_group! {
    name = benches;
    config = Criterion::default()
        .sample_size(10);

    targets = criterion_benchmark, criterion_par_benchmark
}
criterion_main!(benches);
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate lea;

use test::Bencher;

use lea::parser::block;

#[bench]
fn parse_simple(b: &mut Bencher) {
    b.iter(|| {
        block(r#"
local i, j, k = 0, 1, 2+3
i, j = j, i*2
"#).unwrap();
    });
}
<commit_msg>Added simple expression benchmark<commit_after>#![feature(test)]

extern crate test;
extern crate lea;

use test::Bencher;

use lea::parser::*;

#[bench]
fn bench_simple(b: &mut Bencher) {
    b.iter(|| {
        block(r#"
local i, j, k = 0, 1, 2+3
i, j = j, i*2
"#).unwrap();
    });
}

#[bench]
fn bench_expression(b: &mut Bencher) {
    b.iter(|| {
        expression("f(1,2,3,4,5,6,6,7,87,8,9,9,5,5,4)").unwrap();
    });
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 The predicates-rs Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::reflection;
use std::fmt;
use crate::Predicate;

use normalize_line_endings::normalized;
use std::iter::FromIterator;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Predicate adapter that normalizes the newlines contained in the variable being tested.
///
/// This is created by `pred.normalize()`.
pub struct NormalizedPredicate

where
    P: Predicate<str>,
{
    pub(crate) p: P,
}

impl
 reflection::PredicateReflection for NormalizedPredicate

where
    P: Predicate<str>,
{
    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Child<'a>> + 'a> {
        let params = vec![reflection::Child::new("predicate", &self.p)];
        Box::new(params.into_iter())
    }
}

impl
 Predicate<str> for NormalizedPredicate

where
    P: Predicate<str>,
{
    fn eval(&self, variable: &str) -> bool {
        self.p
            .eval(&String::from_iter(normalized(variable.chars())))
    }

    fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
        let variable = String::from_iter(normalized(variable.chars()));
        self.p.find_case(expected, &variable)
    }
}

impl
 fmt::Display for NormalizedPredicate

where
    P: Predicate<str>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.p)
    }
}
<commit_msg>style: Run rustfmt<commit_after>// Copyright (c) 2018 The predicates-rs Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::reflection;
use crate::Predicate;
use std::fmt;

use normalize_line_endings::normalized;
use std::iter::FromIterator;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Predicate adapter that normalizes the newlines contained in the variable being tested.
///
/// This is created by `pred.normalize()`.
pub struct NormalizedPredicate

where
    P: Predicate<str>,
{
    pub(crate) p: P,
}

impl
 reflection::PredicateReflection for NormalizedPredicate

where
    P: Predicate<str>,
{
    fn children<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Child<'a>> + 'a> {
        let params = vec![reflection::Child::new("predicate", &self.p)];
        Box::new(params.into_iter())
    }
}

impl
 Predicate<str> for NormalizedPredicate

where
    P: Predicate<str>,
{
    fn eval(&self, variable: &str) -> bool {
        self.p
            .eval(&String::from_iter(normalized(variable.chars())))
    }

    fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
        let variable = String::from_iter(normalized(variable.chars()));
        self.p.find_case(expected, &variable)
    }
}

impl
 fmt::Display for NormalizedPredicate

where
    P: Predicate<str>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.p)
    }
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Tagged stream
//!
//! A tagged stream recursively applies tags to regions of an input stream. A stream consisting of a single tag forms a tree,
//! so this stream type is useful for representing the parsed represention of an input.
//!
//! The simplest form of tagged stream is one that's just a set of untagged symbols. This can be created using the `TaggedStream::from_reader`
//! method.
//!
//! ```
//! # use concordance::*;
//! #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
//! enum SomeTag {
//!     Identifier
//! };
//!
//! let simple_tagged = TaggedStream::from_reader(&mut "Hello, world".read_symbols());
//! let with_tag      = simple_tagged.with_tags(vec![(0..5, SomeTag::Identifier)].iter().cloned());
//! ```
//!

use std::slice::Iter;
use std::ops::Index;
use std::ops::Range;

use super::symbol_reader::*;
use super::tokenizer::*;
use super::symbol_range_dfa::*;

///
/// Represents a symbol in a tagged stream.
///
/// A symbol can either be a sequence of untagged base symbols, or it can be a tag (which itself can contain any number of tagged symbol)
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TagSymbol<Base: Clone+Ord, Tag: Clone+Ord> {
    /// An untagged element in this stream
    Untagged(Base),

    /// A tagged region of the stream
    Tagged(Tag, TaggedStream<Base, Tag>)
}

///
/// Represents a stream of tagged symbols
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TaggedStream<Base: Clone+Ord, Tag: Clone+Ord> {
    /// The data in this stream
    data: Vec<TagSymbol<Base, Tag>>
}

impl<Base: Ord+Clone, Tag: Ord+Clone> TaggedStream<Base, Tag> {
    ///
    /// Creates a basic tagged stream from a source of the base symbol
    ///
    pub fn from_reader(reader: &mut SymbolReader<Base>) -> TaggedStream<Base, Tag> {
        // Read from the reader into an array
        let mut symbols = vec![];

        while let Some(next_symbol) = reader.next_symbol() {
            symbols.push(TagSymbol::Untagged(next_symbol));
        }

        // Generate a simple tagged stream from the result
        TaggedStream { data: symbols }
    }

    ///
    /// The number of symbols in this stream
    ///
    pub fn len(&self) -> usize {
        self.data.len()
    }

    ///
    /// Replaces a range in this stream with a tag
    ///
    pub fn tag(&mut self, tag: Tag, range: Range<usize>) {
        // Create a tag to replace the range
        let replaced_symbols    = self.data[range.clone()].to_vec();
        let tag_symbol          = TagSymbol::Tagged(tag, TaggedStream { data: replaced_symbols });

        // Draining seems to be for reading a range but does double duty for deleting a range?
        // I don't think rust has a way to replace a range in a vector, or at least not one that's easy to find in the docs.
        self.data.drain(range.clone());

        // Draining then inserting is inefficient compared to flat out replacing items :-/ This may be possible but the vec docs aren't very easy to read
        self.data.insert(range.start, tag_symbol);
    }

    ///
    /// Creates a tag symbol by tagging a particular range within this stream
    ///
    pub fn tag_range(&self, range: Range<usize>, tag: Tag) -> TagSymbol<Base, Tag> {
        let tag_data = self.data[range].to_vec();

        TagSymbol::Tagged(tag, TaggedStream { data: tag_data })
    }

    ///
    /// Applies tags to the specified ranges in this stream
    ///
    /// The tag ranges must be in ascending order and must not overlap
    ///
    pub fn with_tags<I>(&self, tags: I) -> TaggedStream<Base, Tag>
        where I : Iterator<Item=(Range<usize>, Tag)> {
        // The data that will make up the new stream
        let mut new_stream = vec![];

        // The last processed range (we haven't processed any range yet, so this starts at 0..0)
        let mut last_range = 0..0;

        // Build up the result from the tag list and the last range
        for tag in tags {
            // Fetch the information for this tag and check ordering
            let (next_range, next_tag)  = tag;
            let end                     = last_range.end;

            if end > next_range.start {
                panic!("Tags for with_tags must be sorted in order");
            }

            // Sometimes need to leave some data from this stream untagged
            if end < next_range.start {
                new_stream.extend(self.data[end..next_range.start].iter().cloned());
            }

            // Push the tag
            new_stream.push(self.tag_range(next_range.clone(), next_tag));

            // Update state
            last_range = next_range;
        }

        // Append anything left in the stream
        if last_range.end < self.data.len() {
            new_stream.extend(self.data[last_range.end..self.data.len()].iter().cloned());
        }

        // Final result
        TaggedStream { data: new_stream }
    }

    ///
    /// Runs the current values of this tagged stream through a tokenizer and tags anything it matches
    ///
    pub fn tokenize<DfaSymbol: Ord>(&self, dfa: &SymbolRangeDfa<DfaSymbol, Tag>) -> TaggedStream<Base, Tag> {
        unimplemented!();
    }
}

impl<Base: Clone+Ord, Tag: Clone+Ord> Index<usize> for TaggedStream<Base, Tag> {
    type Output = TagSymbol<Base, Tag>;

    fn index(&self, index: usize) -> &TagSymbol<Base, Tag> {
        &self.data[index]
    }
}

impl<'a, Base: Clone+Ord, Tag: Clone+Ord> SymbolSource<'a, TagSymbol<Base, Tag>> for &'a TaggedStream<Base, Tag> {
    type SymbolReader = Iter<'a, TagSymbol<Base, Tag>>;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader {
        self.data.read_symbols()
    }
}

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

    #[test]
    fn can_tag_range() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let mut tagged: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());

        tagged.tag(Tags::Hello, 0..5);
        tagged.tag(Tags::World, 1..6);

        assert!(tagged.len() == 2);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[1] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn can_tag_everything_with_tags() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..5, Tags::Hello), (5..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 2);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[1] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn with_tags_preserves_middle() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..4, Tags::Hello), (6..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 4);
        assert!(tagged[1] == TagSymbol::Untagged('o'));
        assert!(tagged[2] == TagSymbol::Untagged('W'));

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 4);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[3] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 4);
            assert!(stream[0] == TagSymbol::Untagged('o'));
            assert!(stream[1] == TagSymbol::Untagged('r'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn with_tags_preserves_end() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..5, Tags::Hello)].iter().cloned());

        assert!(tagged.len() == 6);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        assert!(tagged[1] == TagSymbol::Untagged('W'));
        assert!(tagged[2] == TagSymbol::Untagged('o'));
        assert!(tagged[3] == TagSymbol::Untagged('r'));
        assert!(tagged[4] == TagSymbol::Untagged('l'));
        assert!(tagged[5] == TagSymbol::Untagged('d'));
    }

    #[test]
    fn with_tags_preserves_start() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(5..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 6);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[5] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }

        assert!(tagged[0] == TagSymbol::Untagged('H'));
        assert!(tagged[1] == TagSymbol::Untagged('e'));
        assert!(tagged[2] == TagSymbol::Untagged('l'));
        assert!(tagged[3] == TagSymbol::Untagged('l'));
        assert!(tagged[4] == TagSymbol::Untagged('o'));
    }
}
<commit_msg>Redeclare the tokenization function so that it has mapping<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Tagged stream
//!
//! A tagged stream recursively applies tags to regions of an input stream. A stream consisting of a single tag forms a tree,
//! so this stream type is useful for representing the parsed represention of an input.
//!
//! The simplest form of tagged stream is one that's just a set of untagged symbols. This can be created using the `TaggedStream::from_reader`
//! method.
//!
//! ```
//! # use concordance::*;
//! #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
//! enum SomeTag {
//!     Identifier
//! };
//!
//! let simple_tagged = TaggedStream::from_reader(&mut "Hello, world".read_symbols());
//! let with_tag      = simple_tagged.with_tags(vec![(0..5, SomeTag::Identifier)].iter().cloned());
//! ```
//!

// TODO: a possibly better way to design this would be to make it so that there's an underlying stream we read from when generating tag
// symbols so that we don't need to store the contents of the stream in memory

use std::slice::Iter;
use std::ops::Index;
use std::ops::Range;

use super::symbol_reader::*;
use super::tokenizer::*;
use super::symbol_range_dfa::*;

///
/// Represents a symbol in a tagged stream.
///
/// A symbol can either be a sequence of untagged base symbols, or it can be a tag (which itself can contain any number of tagged symbol)
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TagSymbol<Base: Clone+Ord, Tag: Clone+Ord> {
    /// An untagged element in this stream
    Untagged(Base),

    /// A tagged region of the stream
    Tagged(Tag, TaggedStream<Base, Tag>)
}

///
/// Represents a stream of tagged symbols
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TaggedStream<Base: Clone+Ord, Tag: Clone+Ord> {
    /// The data in this stream
    data: Vec<TagSymbol<Base, Tag>>
}

impl<Base: Ord+Clone, Tag: Ord+Clone> TaggedStream<Base, Tag> {
    ///
    /// Creates a basic tagged stream from a source of the base symbol
    ///
    pub fn from_reader(reader: &mut SymbolReader<Base>) -> TaggedStream<Base, Tag> {
        // Read from the reader into an array
        let mut symbols = vec![];

        while let Some(next_symbol) = reader.next_symbol() {
            symbols.push(TagSymbol::Untagged(next_symbol));
        }

        // Generate a simple tagged stream from the result
        TaggedStream { data: symbols }
    }

    ///
    /// The number of symbols in this stream
    ///
    pub fn len(&self) -> usize {
        self.data.len()
    }

    ///
    /// Replaces a range in this stream with a tag
    ///
    pub fn tag(&mut self, tag: Tag, range: Range<usize>) {
        // Create a tag to replace the range
        let replaced_symbols    = self.data[range.clone()].to_vec();
        let tag_symbol          = TagSymbol::Tagged(tag, TaggedStream { data: replaced_symbols });

        // Draining seems to be for reading a range but does double duty for deleting a range?
        // I don't think rust has a way to replace a range in a vector, or at least not one that's easy to find in the docs.
        self.data.drain(range.clone());

        // Draining then inserting is inefficient compared to flat out replacing items :-/ This may be possible but the vec docs aren't very easy to read
        self.data.insert(range.start, tag_symbol);
    }

    ///
    /// Creates a tag symbol by tagging a particular range within this stream
    ///
    pub fn tag_range(&self, range: Range<usize>, tag: Tag) -> TagSymbol<Base, Tag> {
        let tag_data = self.data[range].to_vec();

        TagSymbol::Tagged(tag, TaggedStream { data: tag_data })
    }

    ///
    /// Applies tags to the specified ranges in this stream
    ///
    /// The tag ranges must be in ascending order and must not overlap
    ///
    pub fn with_tags<I>(&self, tags: I) -> TaggedStream<Base, Tag>
        where I : Iterator<Item=(Range<usize>, Tag)> {
        // The data that will make up the new stream
        let mut new_stream = vec![];

        // The last processed range (we haven't processed any range yet, so this starts at 0..0)
        let mut last_range = 0..0;

        // Build up the result from the tag list and the last range
        for tag in tags {
            // Fetch the information for this tag and check ordering
            let (next_range, next_tag)  = tag;
            let end                     = last_range.end;

            if end > next_range.start {
                panic!("Tags for with_tags must be sorted in order");
            }

            // Sometimes need to leave some data from this stream untagged
            if end < next_range.start {
                new_stream.extend(self.data[end..next_range.start].iter().cloned());
            }

            // Push the tag
            new_stream.push(self.tag_range(next_range.clone(), next_tag));

            // Update state
            last_range = next_range;
        }

        // Append anything left in the stream
        if last_range.end < self.data.len() {
            new_stream.extend(self.data[last_range.end..self.data.len()].iter().cloned());
        }

        // Final result
        TaggedStream { data: new_stream }
    }

    ///
    /// Runs the current values of this tagged stream through a tokenizer and tags anything it matches
    ///
    /// This takes a mapping function: the idea is that
    ///
    pub fn tokenize<DfaSymbol: Ord>(&self, dfa: &SymbolRangeDfa<DfaSymbol, Tag>, map_symbol: Fn(TagSymbol<Base, Tag>) -> Option<DfaSymbol>) -> TaggedStream<Base, Tag> {
        unimplemented!();
    }
}

impl<Base: Clone+Ord, Tag: Clone+Ord> Index<usize> for TaggedStream<Base, Tag> {
    type Output = TagSymbol<Base, Tag>;

    fn index(&self, index: usize) -> &TagSymbol<Base, Tag> {
        &self.data[index]
    }
}

impl<'a, Base: Clone+Ord, Tag: Clone+Ord> SymbolSource<'a, TagSymbol<Base, Tag>> for &'a TaggedStream<Base, Tag> {
    type SymbolReader = Iter<'a, TagSymbol<Base, Tag>>;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader {
        self.data.read_symbols()
    }
}

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

    #[test]
    fn can_tag_range() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let mut tagged: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());

        tagged.tag(Tags::Hello, 0..5);
        tagged.tag(Tags::World, 1..6);

        assert!(tagged.len() == 2);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[1] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn can_tag_everything_with_tags() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..5, Tags::Hello), (5..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 2);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[1] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn with_tags_preserves_middle() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..4, Tags::Hello), (6..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 4);
        assert!(tagged[1] == TagSymbol::Untagged('o'));
        assert!(tagged[2] == TagSymbol::Untagged('W'));

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 4);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[3] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 4);
            assert!(stream[0] == TagSymbol::Untagged('o'));
            assert!(stream[1] == TagSymbol::Untagged('r'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn with_tags_preserves_end() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..5, Tags::Hello)].iter().cloned());

        assert!(tagged.len() == 6);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        assert!(tagged[1] == TagSymbol::Untagged('W'));
        assert!(tagged[2] == TagSymbol::Untagged('o'));
        assert!(tagged[3] == TagSymbol::Untagged('r'));
        assert!(tagged[4] == TagSymbol::Untagged('l'));
        assert!(tagged[5] == TagSymbol::Untagged('d'));
    }

    #[test]
    fn with_tags_preserves_start() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(5..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 6);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[5] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }

        assert!(tagged[0] == TagSymbol::Untagged('H'));
        assert!(tagged[1] == TagSymbol::Untagged('e'));
        assert!(tagged[2] == TagSymbol::Untagged('l'));
        assert!(tagged[3] == TagSymbol::Untagged('l'));
        assert!(tagged[4] == TagSymbol::Untagged('o'));
    }
}
<|endoftext|>


<commit_before>macro_rules! impl_traits {
    { $type:ident, $scalar:ty } => {
        impl<const LANES: usize> core::iter::Sum<Self> for crate::$type<LANES>
        where
            Self: crate::LanesAtMost32,
        {
            fn sum<I: core::iter::Iterator<Item = Self>>(iter: I) -> Self {
                iter.fold(Default::default(), core::ops::Add::add)
            }
        }

        impl<const LANES: usize> core::iter::Product<Self> for crate::$type<LANES>
        where
            Self: crate::LanesAtMost32,
        {
            fn product<I: core::iter::Iterator<Item = Self>>(iter: I) -> Self {
                iter.fold(Default::default(), core::ops::Mul::mul)
            }
        }

        impl<const LANES: usize> core::iter::Sum<crate::$type<LANES>> for $scalar
        where
            crate::$type<LANES>: crate::LanesAtMost32,
        {
            fn sum<I: core::iter::Iterator<Item = crate::$type<LANES>>>(iter: I) -> Self {
                iter.sum::<crate::$type<LANES>>().horizontal_sum()
            }
        }

        impl<const LANES: usize> core::iter::Product<crate::$type<LANES>> for $scalar
        where
            crate::$type<LANES>: crate::LanesAtMost32,
        {
            fn product<I: core::iter::Iterator<Item = crate::$type<LANES>>>(iter: I) -> Self {
                iter.product::<crate::$type<LANES>>().horizontal_product()
            }
        }
    }
}

impl_traits! { SimdF32, f32 }
impl_traits! { SimdF64, f64 }
impl_traits! { SimdU8, u8 }
impl_traits! { SimdU16, u16 }
impl_traits! { SimdU32, u32 }
impl_traits! { SimdU64, u64 }
impl_traits! { SimdUsize, usize }
impl_traits! { SimdI8, i8 }
impl_traits! { SimdI16, i16 }
impl_traits! { SimdI32, i32 }
impl_traits! { SimdI64, i64 }
impl_traits! { SimdIsize, isize }
<commit_msg>Implement Sum/Product over references<commit_after>macro_rules! impl_traits {
    { $type:ident, $scalar:ty } => {
        impl<const LANES: usize> core::iter::Sum<Self> for crate::$type<LANES>
        where
            Self: crate::LanesAtMost32,
        {
            fn sum<I: core::iter::Iterator<Item = Self>>(iter: I) -> Self {
                iter.fold(Default::default(), core::ops::Add::add)
            }
        }

        impl<const LANES: usize> core::iter::Product<Self> for crate::$type<LANES>
        where
            Self: crate::LanesAtMost32,
        {
            fn product<I: core::iter::Iterator<Item = Self>>(iter: I) -> Self {
                iter.fold(Default::default(), core::ops::Mul::mul)
            }
        }

        impl<const LANES: usize> core::iter::Sum<crate::$type<LANES>> for $scalar
        where
            crate::$type<LANES>: crate::LanesAtMost32,
        {
            fn sum<I: core::iter::Iterator<Item = crate::$type<LANES>>>(iter: I) -> Self {
                iter.sum::<crate::$type<LANES>>().horizontal_sum()
            }
        }

        impl<const LANES: usize> core::iter::Product<crate::$type<LANES>> for $scalar
        where
            crate::$type<LANES>: crate::LanesAtMost32,
        {
            fn product<I: core::iter::Iterator<Item = crate::$type<LANES>>>(iter: I) -> Self {
                iter.product::<crate::$type<LANES>>().horizontal_product()
            }
        }

        impl<'a, const LANES: usize> core::iter::Sum<&'a Self> for crate::$type<LANES>
        where
            Self: crate::LanesAtMost32,
        {
            fn sum<I: core::iter::Iterator<Item = &'a Self>>(iter: I) -> Self {
                iter.fold(Default::default(), core::ops::Add::add)
            }
        }

        impl<'a, const LANES: usize> core::iter::Product<&'a Self> for crate::$type<LANES>
        where
            Self: crate::LanesAtMost32,
        {
            fn product<I: core::iter::Iterator<Item = &'a Self>>(iter: I) -> Self {
                iter.fold(Default::default(), core::ops::Mul::mul)
            }
        }

        impl<'a, const LANES: usize> core::iter::Sum<&'a crate::$type<LANES>> for $scalar
        where
            crate::$type<LANES>: crate::LanesAtMost32,
        {
            fn sum<I: core::iter::Iterator<Item = &'a crate::$type<LANES>>>(iter: I) -> Self {
                iter.sum::<crate::$type<LANES>>().horizontal_sum()
            }
        }

        impl<'a, const LANES: usize> core::iter::Product<&'a crate::$type<LANES>> for $scalar
        where
            crate::$type<LANES>: crate::LanesAtMost32,
        {
            fn product<I: core::iter::Iterator<Item = &'a crate::$type<LANES>>>(iter: I) -> Self {
                iter.product::<crate::$type<LANES>>().horizontal_product()
            }
        }
    }
}

impl_traits! { SimdF32, f32 }
impl_traits! { SimdF64, f64 }
impl_traits! { SimdU8, u8 }
impl_traits! { SimdU16, u16 }
impl_traits! { SimdU32, u32 }
impl_traits! { SimdU64, u64 }
impl_traits! { SimdUsize, usize }
impl_traits! { SimdI8, i8 }
impl_traits! { SimdI16, i16 }
impl_traits! { SimdI32, i32 }
impl_traits! { SimdI64, i64 }
impl_traits! { SimdIsize, isize }
<|endoftext|>


<commit_before>//! [GET /_matrix/client/r0/user/{userId}/filter/{filterId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-user-userid-filter-filterid)

use ruma_api::ruma_api;
use ruma_identifiers::UserId;

use super::IncomingFilterDefinition;

ruma_api! {
    metadata: {
        description: "Retrieve a previously created filter.",
        method: GET,
        name: "get_filter",
        path: "/_matrix/client/r0/user/:user_id/filter/:filter_id",
        rate_limited: false,
        authentication: AccessToken,
    }

    request: {
        /// The user ID to download a filter for.
        #[ruma_api(path)]
        pub user_id: &'a UserId,

        /// The ID of the filter to download.
        #[ruma_api(path)]
        pub filter_id: &'a str,
    }

    response: {
        /// The filter definition.
        #[ruma_api(body)]
        pub filter: IncomingFilterDefinition,
    }

    error: crate::Error
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given user ID and filter ID.
    pub fn new(user_id: &'a UserId, filter_id: &'a str) -> Self {
        Self { user_id, filter_id }
    }
}

impl Response {
    /// Creates a new `Response` with the given filter definition.
    pub fn new(filter: IncomingFilterDefinition) -> Self {
        Self { filter }
    }
}

#[cfg(all(test, any(feature = "client", feature = "server")))]
mod tests {
    use matches::assert_matches;

    use crate::r0::filter::IncomingFilterDefinition;

    #[cfg(feature = "client")]
    #[test]
    fn deserialize_response() {
        use ruma_api::IncomingResponse;

        assert_matches!(
            super::Response::try_from_http_response(
                http::Response::builder().body(b"{}" as &[u8]).unwrap(),
            ),
            Ok(Incoming)
        );
    }

    #[cfg(feature = "server")]
    #[test]
    fn serialize_response() {
        use ruma_api::OutgoingResponse;

        assert_matches!(
            super::Response::new(IncomingFilterDefinition::default())
                .try_into_http_response::<Vec<u8>>(),
            Ok(res) if res.body() == b"{}"
        );
    }
}
<commit_msg>client-api: Fix previously introduced test<commit_after>//! [GET /_matrix/client/r0/user/{userId}/filter/{filterId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-user-userid-filter-filterid)

use ruma_api::ruma_api;
use ruma_identifiers::UserId;

use super::IncomingFilterDefinition;

ruma_api! {
    metadata: {
        description: "Retrieve a previously created filter.",
        method: GET,
        name: "get_filter",
        path: "/_matrix/client/r0/user/:user_id/filter/:filter_id",
        rate_limited: false,
        authentication: AccessToken,
    }

    request: {
        /// The user ID to download a filter for.
        #[ruma_api(path)]
        pub user_id: &'a UserId,

        /// The ID of the filter to download.
        #[ruma_api(path)]
        pub filter_id: &'a str,
    }

    response: {
        /// The filter definition.
        #[ruma_api(body)]
        pub filter: IncomingFilterDefinition,
    }

    error: crate::Error
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given user ID and filter ID.
    pub fn new(user_id: &'a UserId, filter_id: &'a str) -> Self {
        Self { user_id, filter_id }
    }
}

impl Response {
    /// Creates a new `Response` with the given filter definition.
    pub fn new(filter: IncomingFilterDefinition) -> Self {
        Self { filter }
    }
}

#[cfg(all(test, any(feature = "client", feature = "server")))]
mod tests {
    use matches::assert_matches;

    use crate::r0::filter::IncomingFilterDefinition;

    #[cfg(feature = "client")]
    #[test]
    fn deserialize_response() {
        use ruma_api::IncomingResponse;

        assert_matches!(
            super::Response::try_from_http_response(
                http::Response::builder().body(b"{}" as &[u8]).unwrap(),
            ),
            Ok(super::Response { filter }) if filter.is_empty()
        );
    }

    #[cfg(feature = "server")]
    #[test]
    fn serialize_response() {
        use ruma_api::OutgoingResponse;

        assert_matches!(
            super::Response::new(IncomingFilterDefinition::default())
                .try_into_http_response::<Vec<u8>>(),
            Ok(res) if res.body() == b"{}"
        );
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::cmp;

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ProgressState {
    Probe,
    Replicate,
    Snapshot,
}

impl Default for ProgressState {
    fn default() -> ProgressState {
        ProgressState::Probe
    }
}

#[derive(Debug, Default, Clone)]
pub struct Progress {
    pub matched: u64,
    pub next_idx: u64,
    // When in ProgressStateProbe, leader sends at most one replication message
    // per heartbeat interval. It also probes actual progress of the follower.
    //
    // When in ProgressStateReplicate, leader optimistically increases next
    // to the latest entry sent after sending replication message. This is
    // an optimized state for fast replicating log entries to the follower.
    //
    // When in ProgressStateSnapshot, leader should have sent out snapshot
    // before and stops sending any replication message.
    pub state: ProgressState,
    // Paused is used in ProgressStateProbe.
    // When Paused is true, raft should pause sending replication message to this peer.
    pub paused: bool,
    // pending_snapshot is used in ProgressStateSnapshot.
    // If there is a pending snapshot, the pendingSnapshot will be set to the
    // index of the snapshot. If pendingSnapshot is set, the replication process of
    // this Progress will be paused. raft will not resend snapshot until the pending one
    // is reported to be failed.
    pub pending_snapshot: u64,

    // recent_active is true if the progress is recently active. Receiving any messages
    // from the corresponding follower indicates the progress is active.
    // RecentActive can be reset to false after an election timeout.
    pub recent_active: bool,

    // Inflights is a sliding window for the inflight messages.
    // When inflights is full, no more message should be sent.
    // When a leader sends out a message, the index of the last
    // entry should be added to inflights. The index MUST be added
    // into inflights in order.
    // When a leader receives a reply, the previous inflights should
    // be freed by calling inflights.freeTo.
    pub ins: Inflights,
}

impl Progress {
    pub fn reset_state(&mut self, state: ProgressState) {
        self.paused = false;
        self.recent_active = false;
        self.pending_snapshot = 0;
        self.state = state;
        self.ins.reset();
    }

    pub fn become_probe(&mut self) {
        // If the original state is ProgressStateSnapshot, progress knows that
        // the pending snapshot has been sent to this peer successfully, then
        // probes from pendingSnapshot + 1.
        if self.state == ProgressState::Snapshot {
            let pending_snapshot = self.pending_snapshot;
            self.reset_state(ProgressState::Probe);
            self.next_idx = cmp::max(self.matched + 1, pending_snapshot + 1);
        } else {
            self.reset_state(ProgressState::Probe);
            self.next_idx = self.matched + 1;
        }
    }

    pub fn become_replicate(&mut self) {
        self.reset_state(ProgressState::Replicate);
        self.next_idx = self.matched + 1;
    }

    pub fn become_snapshot(&mut self, snapshot_idx: u64) {
        self.reset_state(ProgressState::Snapshot);
        self.pending_snapshot = snapshot_idx;
    }

    pub fn snapshot_failure(&self) -> bool {
        self.pending_snapshot == 0
    }

    // maybe_snapshot_abort unsets pendingSnapshot if Match is equal or higher than
    // the pendingSnapshot
    pub fn maybe_snapshot_abort(&self) -> bool {
        self.state == ProgressState::Snapshot && self.matched >= self.pending_snapshot
    }

    // maybe_update returns false if the given n index comes from an outdated message.
    // Otherwise it updates the progress and returns true.
    pub fn maybe_update(&mut self, n: u64) -> bool {
        let mut updated = false;
        if self.matched < n {
            self.matched = n;
            updated = true;
            self.resume()
        }

        if self.next_idx < n + 1 {
            self.next_idx = n + 1
        }

        updated
    }

    pub fn optimistic_update(&mut self, n: u64) {
        self.next_idx = n + 1;
    }

    // maybe_decr_to returns false if the given to index comes from an out of order message.
    // Otherwise it decreases the progress next index to min(rejected, last) and returns true.
    pub fn maybe_decr_to(&mut self, rejected: u64, last: u64) -> bool {
        if self.state == ProgressState::Replicate {
            // the rejection must be stale if the progress has matched and "rejected"
            // is smaller than "match".
            if rejected <= self.matched {
                return false;
            }
            self.next_idx = self.matched + 1;
            return true;
        }

        // the rejection must be stale if "rejected" does not match next - 1
        if self.next_idx == 0 || self.next_idx - 1 != rejected {
            return false;
        }

        self.next_idx = cmp::min(rejected, last + 1);
        if self.next_idx < 1 {
            self.next_idx = 1;
        }
        self.resume();
        true
    }

    pub fn is_paused(&self) -> bool {
        match self.state {
            ProgressState::Probe => self.paused,
            ProgressState::Replicate => self.ins.full(),
            ProgressState::Snapshot => true,
        }
    }

    pub fn resume(&mut self) {
        self.paused = false;
    }

    pub fn pause(&mut self) {
        self.paused = true;
    }
}

#[derive(Debug, Default, Clone)]
pub struct Inflights {
    // the starting index in the buffer
    start: usize,
    // number of inflights in the buffer
    count: usize,

    // ring buffer
    buffer: Vec<u64>,
}

impl Inflights {
    pub fn new(cap: usize) -> Inflights {
        Inflights { buffer: Vec::with_capacity(cap), ..Default::default() }
    }

    // full returns true if the inflights is full.
    pub fn full(&self) -> bool {
        self.count == self.cap()
    }

    pub fn cap(&self) -> usize {
        self.buffer.capacity()
    }

    // add adds an inflight into inflights
    pub fn add(&mut self, inflight: u64) {
        if self.full() {
            panic!("cannot add into a full inflights")
        }

        let mut next = self.start + self.count;
        if next >= self.cap() {
            next -= self.cap();
        }
        assert!(next <= self.buffer.len());
        if next == self.buffer.len() {
            self.buffer.push(inflight);
        } else {
            self.buffer[next] = inflight;
        }
        self.count += 1;
    }

    // free_to frees the inflights smaller or equal to the given `to` flight.
    pub fn free_to(&mut self, to: u64) {
        if self.count == 0 || to < self.buffer[self.start] {
            // out of the left side of the window
            return;
        }

        let mut i = 0usize;
        let mut idx = self.start;
        while i < self.count {
            if to < self.buffer[idx] {
                // found the first large inflight
                break;
            }

            // increase index and maybe rotate
            idx += 1;
            if idx >= self.cap() {
                idx -= self.cap();
            }

            i += 1;
        }

        // free i inflights and set new start index
        self.count -= i;
        self.start = idx;
    }

    pub fn free_first_one(&mut self) {
        let start = self.buffer[self.start];
        self.free_to(start);
    }

    // resets frees all inflights.
    pub fn reset(&mut self) {
        self.count = 0;
        self.start = 0;
    }
}
<commit_msg>port raft_snap tests<commit_after>#![allow(dead_code)]

use std::cmp;

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ProgressState {
    Probe,
    Replicate,
    Snapshot,
}

impl Default for ProgressState {
    fn default() -> ProgressState {
        ProgressState::Probe
    }
}

#[derive(Debug, Default, Clone)]
pub struct Progress {
    pub matched: u64,
    pub next_idx: u64,
    // When in ProgressStateProbe, leader sends at most one replication message
    // per heartbeat interval. It also probes actual progress of the follower.
    //
    // When in ProgressStateReplicate, leader optimistically increases next
    // to the latest entry sent after sending replication message. This is
    // an optimized state for fast replicating log entries to the follower.
    //
    // When in ProgressStateSnapshot, leader should have sent out snapshot
    // before and stops sending any replication message.
    pub state: ProgressState,
    // Paused is used in ProgressStateProbe.
    // When Paused is true, raft should pause sending replication message to this peer.
    pub paused: bool,
    // pending_snapshot is used in ProgressStateSnapshot.
    // If there is a pending snapshot, the pendingSnapshot will be set to the
    // index of the snapshot. If pendingSnapshot is set, the replication process of
    // this Progress will be paused. raft will not resend snapshot until the pending one
    // is reported to be failed.
    pub pending_snapshot: u64,

    // recent_active is true if the progress is recently active. Receiving any messages
    // from the corresponding follower indicates the progress is active.
    // RecentActive can be reset to false after an election timeout.
    pub recent_active: bool,

    // Inflights is a sliding window for the inflight messages.
    // When inflights is full, no more message should be sent.
    // When a leader sends out a message, the index of the last
    // entry should be added to inflights. The index MUST be added
    // into inflights in order.
    // When a leader receives a reply, the previous inflights should
    // be freed by calling inflights.freeTo.
    pub ins: Inflights,
}

impl Progress {
    pub fn reset_state(&mut self, state: ProgressState) {
        self.paused = false;
        self.recent_active = false;
        self.pending_snapshot = 0;
        self.state = state;
        self.ins.reset();
    }

    pub fn become_probe(&mut self) {
        // If the original state is ProgressStateSnapshot, progress knows that
        // the pending snapshot has been sent to this peer successfully, then
        // probes from pendingSnapshot + 1.
        if self.state == ProgressState::Snapshot {
            let pending_snapshot = self.pending_snapshot;
            self.reset_state(ProgressState::Probe);
            self.next_idx = cmp::max(self.matched + 1, pending_snapshot + 1);
        } else {
            self.reset_state(ProgressState::Probe);
            self.next_idx = self.matched + 1;
        }
    }

    pub fn become_replicate(&mut self) {
        self.reset_state(ProgressState::Replicate);
        self.next_idx = self.matched + 1;
    }

    pub fn become_snapshot(&mut self, snapshot_idx: u64) {
        self.reset_state(ProgressState::Snapshot);
        self.pending_snapshot = snapshot_idx;
    }

    pub fn snapshot_failure(&mut self) {
        self.pending_snapshot = 0;
    }

    // maybe_snapshot_abort unsets pendingSnapshot if Match is equal or higher than
    // the pendingSnapshot
    pub fn maybe_snapshot_abort(&self) -> bool {
        self.state == ProgressState::Snapshot && self.matched >= self.pending_snapshot
    }

    // maybe_update returns false if the given n index comes from an outdated message.
    // Otherwise it updates the progress and returns true.
    pub fn maybe_update(&mut self, n: u64) -> bool {
        let mut updated = false;
        if self.matched < n {
            self.matched = n;
            updated = true;
            self.resume()
        }

        if self.next_idx < n + 1 {
            self.next_idx = n + 1
        }

        updated
    }

    pub fn optimistic_update(&mut self, n: u64) {
        self.next_idx = n + 1;
    }

    // maybe_decr_to returns false if the given to index comes from an out of order message.
    // Otherwise it decreases the progress next index to min(rejected, last) and returns true.
    pub fn maybe_decr_to(&mut self, rejected: u64, last: u64) -> bool {
        if self.state == ProgressState::Replicate {
            // the rejection must be stale if the progress has matched and "rejected"
            // is smaller than "match".
            if rejected <= self.matched {
                return false;
            }
            self.next_idx = self.matched + 1;
            return true;
        }

        // the rejection must be stale if "rejected" does not match next - 1
        if self.next_idx == 0 || self.next_idx - 1 != rejected {
            return false;
        }

        self.next_idx = cmp::min(rejected, last + 1);
        if self.next_idx < 1 {
            self.next_idx = 1;
        }
        self.resume();
        true
    }

    pub fn is_paused(&self) -> bool {
        match self.state {
            ProgressState::Probe => self.paused,
            ProgressState::Replicate => self.ins.full(),
            ProgressState::Snapshot => true,
        }
    }

    pub fn resume(&mut self) {
        self.paused = false;
    }

    pub fn pause(&mut self) {
        self.paused = true;
    }
}

#[derive(Debug, Default, Clone)]
pub struct Inflights {
    // the starting index in the buffer
    start: usize,
    // number of inflights in the buffer
    count: usize,

    // ring buffer
    buffer: Vec<u64>,
}

impl Inflights {
    pub fn new(cap: usize) -> Inflights {
        Inflights { buffer: Vec::with_capacity(cap), ..Default::default() }
    }

    // full returns true if the inflights is full.
    pub fn full(&self) -> bool {
        self.count == self.cap()
    }

    pub fn cap(&self) -> usize {
        self.buffer.capacity()
    }

    // add adds an inflight into inflights
    pub fn add(&mut self, inflight: u64) {
        if self.full() {
            panic!("cannot add into a full inflights")
        }

        let mut next = self.start + self.count;
        if next >= self.cap() {
            next -= self.cap();
        }
        assert!(next <= self.buffer.len());
        if next == self.buffer.len() {
            self.buffer.push(inflight);
        } else {
            self.buffer[next] = inflight;
        }
        self.count += 1;
    }

    // free_to frees the inflights smaller or equal to the given `to` flight.
    pub fn free_to(&mut self, to: u64) {
        if self.count == 0 || to < self.buffer[self.start] {
            // out of the left side of the window
            return;
        }

        let mut i = 0usize;
        let mut idx = self.start;
        while i < self.count {
            if to < self.buffer[idx] {
                // found the first large inflight
                break;
            }

            // increase index and maybe rotate
            idx += 1;
            if idx >= self.cap() {
                idx -= self.cap();
            }

            i += 1;
        }

        // free i inflights and set new start index
        self.count -= i;
        self.start = idx;
    }

    pub fn free_first_one(&mut self) {
        let start = self.buffer[self.start];
        self.free_to(start);
    }

    // resets frees all inflights.
    pub fn reset(&mut self) {
        self.count = 0;
        self.start = 0;
    }
}
<|endoftext|>


<commit_before>// same as threaded.rs, except that the counter is thread safe
// and report the correct number of requests, parallel or not

extern crate rotor;
extern crate rotor_http;

use std::env;
use std::thread;
use std::time::Duration;

use rotor::{Scope, Time};
use rotor_http::server::{Fsm, RecvMode, Server, Head, Response};
use rotor::mio::tcp::TcpListener;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

struct Context {
    counter: Arc<AtomicUsize>,
}

trait Counter {
    fn increment(&mut self);
    fn get(&self) -> usize;
}

impl Counter for Context {
    fn increment(&mut self) { self.counter.fetch_add(1, Ordering::SeqCst); }
    fn get(&self) -> usize { self.counter.load(Ordering::SeqCst) }
}

#[derive(Debug, Clone)]
enum HelloWorld {
    Hello,
    GetNum,
    HelloName(String),
    PageNotFound,
}

fn send_string(res: &mut Response, data: &[u8]) {
    res.status(200, "OK");
    res.add_length(data.len() as u64).unwrap();
    res.done_headers().unwrap();
    res.write_body(data);
    res.done();
}

impl Server for HelloWorld {
    type Seed = ();
    type Context = Context;
    fn headers_received(_seed: (), head: Head, _res: &mut Response,
        scope: &mut Scope<Context>)
        -> Option<(Self, RecvMode, Time)>
    {
        use self::HelloWorld::*;
        scope.increment();
        Some((match head.path {
            "/" => Hello,
            "/num" => GetNum,
            p if p.starts_with('/') => HelloName(p[1..].to_string()),
            _ => PageNotFound
        }, RecvMode::Buffered(1024), scope.now() + Duration::new(10, 0)))
    }
    fn request_received(self, _data: &[u8], res: &mut Response,
        scope: &mut Scope<Context>)
        -> Option<Self>
    {
        use self::HelloWorld::*;
        match self {
            Hello => {
                send_string(res, b"Hello World!");
            }
            GetNum => {
                send_string(res,
                    format!("This host has been visited {} times",
                        scope.get())
                    .as_bytes());
            }
            HelloName(name) => {
                send_string(res, format!("Hello {}!", name).as_bytes());
            }
            PageNotFound => {
                let data = b"404 - Page not found";
                res.status(404, "Not Found");
                res.add_length(data.len() as u64).unwrap();
                res.done_headers().unwrap();
                res.write_body(data);
                res.done();
            }
        }
        None
    }
    fn request_chunk(self, _chunk: &[u8], _response: &mut Response,
        _scope: &mut Scope<Context>)
        -> Option<Self>
    {
        unreachable!();
    }

    /// End of request body, only for Progressive requests
    fn request_end(self, _response: &mut Response, _scope: &mut Scope<Context>)
        -> Option<Self>
    {
        unreachable!();
    }

    fn timeout(self, _response: &mut Response, _scope: &mut Scope<Context>)
        -> Option<(Self, Time)>
    {
        unimplemented!();
    }
    fn wakeup(self, _response: &mut Response, _scope: &mut Scope<Context>)
        -> Option<Self>
    {
        unimplemented!();
    }
}

fn main() {
    let lst = TcpListener::bind(&"127.0.0.1:3000".parse().unwrap()).unwrap();
    let threads = env::var("THREADS").unwrap_or("2".to_string())
        .parse().unwrap();
    let mut children = Vec::new();
    let counter = Arc::new(AtomicUsize::new(0));
    for _ in 0..threads {
        let counter_ref = counter.clone();
        let listener = lst.try_clone().unwrap();
        children.push(thread::spawn(move || {
            let event_loop = rotor::Loop::new(
                &rotor::Config::new()).unwrap();
            let mut loop_inst = event_loop.instantiate(Context {
                counter: counter_ref,
            });
            loop_inst.add_machine_with(|scope| {
                Fsm::<HelloWorld, _>::new(listener, (), scope)
            }).unwrap();
            loop_inst.run().unwrap();
        }));
    }
    for child in children {
        child.join().unwrap();
    }
}
<commit_msg>AtomicUsize does not need a mutable reference to be increment<commit_after>// same as threaded.rs, except that the counter is thread safe
// and report the correct number of requests, parallel or not

extern crate rotor;
extern crate rotor_http;

use std::env;
use std::thread;
use std::time::Duration;

use rotor::{Scope, Time};
use rotor_http::server::{Fsm, RecvMode, Server, Head, Response};
use rotor::mio::tcp::TcpListener;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

struct Context {
    counter: Arc<AtomicUsize>,
}

trait Counter {
    fn increment(&self);
    fn get(&self) -> usize;
}

impl Counter for Context {
    fn increment(&self) { self.counter.fetch_add(1, Ordering::SeqCst); }
    fn get(&self) -> usize { self.counter.load(Ordering::SeqCst) }
}

#[derive(Debug, Clone)]
enum HelloWorld {
    Hello,
    GetNum,
    HelloName(String),
    PageNotFound,
}

fn send_string(res: &mut Response, data: &[u8]) {
    res.status(200, "OK");
    res.add_length(data.len() as u64).unwrap();
    res.done_headers().unwrap();
    res.write_body(data);
    res.done();
}

impl Server for HelloWorld {
    type Seed = ();
    type Context = Context;
    fn headers_received(_seed: (), head: Head, _res: &mut Response,
        scope: &mut Scope<Context>)
        -> Option<(Self, RecvMode, Time)>
    {
        use self::HelloWorld::*;
        scope.increment();
        Some((match head.path {
            "/" => Hello,
            "/num" => GetNum,
            p if p.starts_with('/') => HelloName(p[1..].to_string()),
            _ => PageNotFound
        }, RecvMode::Buffered(1024), scope.now() + Duration::new(10, 0)))
    }
    fn request_received(self, _data: &[u8], res: &mut Response,
        scope: &mut Scope<Context>)
        -> Option<Self>
    {
        use self::HelloWorld::*;
        match self {
            Hello => {
                send_string(res, b"Hello World!");
            }
            GetNum => {
                send_string(res,
                    format!("This host has been visited {} times",
                        scope.get())
                    .as_bytes());
            }
            HelloName(name) => {
                send_string(res, format!("Hello {}!", name).as_bytes());
            }
            PageNotFound => {
                let data = b"404 - Page not found";
                res.status(404, "Not Found");
                res.add_length(data.len() as u64).unwrap();
                res.done_headers().unwrap();
                res.write_body(data);
                res.done();
            }
        }
        None
    }
    fn request_chunk(self, _chunk: &[u8], _response: &mut Response,
        _scope: &mut Scope<Context>)
        -> Option<Self>
    {
        unreachable!();
    }

    /// End of request body, only for Progressive requests
    fn request_end(self, _response: &mut Response, _scope: &mut Scope<Context>)
        -> Option<Self>
    {
        unreachable!();
    }

    fn timeout(self, _response: &mut Response, _scope: &mut Scope<Context>)
        -> Option<(Self, Time)>
    {
        unimplemented!();
    }
    fn wakeup(self, _response: &mut Response, _scope: &mut Scope<Context>)
        -> Option<Self>
    {
        unimplemented!();
    }
}

fn main() {
    let lst = TcpListener::bind(&"127.0.0.1:3000".parse().unwrap()).unwrap();
    let threads = env::var("THREADS").unwrap_or("2".to_string())
        .parse().unwrap();
    let mut children = Vec::new();
    let counter = Arc::new(AtomicUsize::new(0));
    for _ in 0..threads {
        let counter_ref = counter.clone();
        let listener = lst.try_clone().unwrap();
        children.push(thread::spawn(move || {
            let event_loop = rotor::Loop::new(
                &rotor::Config::new()).unwrap();
            let mut loop_inst = event_loop.instantiate(Context {
                counter: counter_ref,
            });
            loop_inst.add_machine_with(|scope| {
                Fsm::<HelloWorld, _>::new(listener, (), scope)
            }).unwrap();
            loop_inst.run().unwrap();
        }));
    }
    for child in children {
        child.join().unwrap();
    }
}
<|endoftext|>


<commit_before>use orbclient::{Color, Renderer};
use std::cell::{Cell, RefCell};
use std::sync::Arc;

use cell::{CloneCell, CheckSet};
use event::Event;
use point::Point;
use rect::Rect;
use theme::{LABEL_BACKGROUND, LABEL_BORDER, LABEL_FOREGROUND};
use traits::{Border, Click, Place, Text};
use widgets::Widget;

pub struct Label {
    pub rect: Cell<Rect>,
    pub bg: Color,
    pub fg: Color,
    pub fg_border: Color,
    pub border: Cell<bool>,
    pub border_radius: Cell<u32>,
    pub text: CloneCell<String>,
    pub text_offset: Cell<Point>,
    click_callback: RefCell<Option<Arc<Fn(&Label, Point)>>>,
    pressed: Cell<bool>,
}

impl Label {
    pub fn new() -> Arc<Self> {
        Arc::new(Label {
            rect: Cell::new(Rect::default()),
            bg: LABEL_BACKGROUND,
            fg: LABEL_FOREGROUND,
            fg_border: LABEL_BORDER,
            border: Cell::new(false),
            border_radius: Cell::new(0),
            text: CloneCell::new(String::new()),
            text_offset: Cell::new(Point::default()),
            click_callback: RefCell::new(None),
            pressed: Cell::new(false),
        })
    }
}

impl Border for Label {
    fn border(&self, enabled: bool) -> &Self {
        self.border.set(enabled);
        self
    }

    fn border_radius(&self, radius: u32) -> &Self {
        self.border_radius.set(radius);
        self
    }
}

impl Click for Label {
    fn emit_click(&self, point: Point) {
        if let Some(ref click_callback) = *self.click_callback.borrow() {
            click_callback(self, point);
        }
    }

    fn on_click<T: Fn(&Self, Point) + 'static>(&self, func: T) -> &Self {
        *self.click_callback.borrow_mut() = Some(Arc::new(func));
        self
    }
}

impl Place for Label {}

impl Text for Label {
    fn text<S: Into<String>>(&self, text: S) -> &Self {
        self.text.set(text.into());
        self
    }

    fn text_offset(&self, x: i32, y: i32) -> &Self {
        self.text_offset.set(Point::new(x, y));
        self
    }
}

impl Widget for Label {
    fn rect(&self) -> &Cell<Rect> {
        &self.rect
    }

    fn draw(&self, renderer: &mut Renderer, _focused: bool) {
        let rect = self.rect.get();

        let b_r = self.border_radius.get();
        renderer.rounded_rect(rect.x, rect.y, rect.width, rect.height, b_r, true, self.bg);
        if self.border.get() {
            renderer.rounded_rect(rect.x, rect.y, rect.width, rect.height, b_r, false, self.fg_border);
        }

        let text = self.text.borrow();

        let mut point = self.text_offset.get();
        for c in text.chars() {
            if c == '\n' {
                point.x = 0;
                point.y += 16;
            } else {
                if point.x + 8 <= rect.width as i32 && point.y + 16 <= rect.height as i32 {
                    renderer.char(point.x + rect.x, point.y + rect.y, c, self.fg);
                }
                point.x += 8;
            }
        }
    }

    fn event(&self, event: Event, focused: bool, redraw: &mut bool) -> bool {
        match event {
            Event::Mouse { point, left_button, .. } => {
                let mut click = false;

                let rect = self.rect.get();
                if rect.contains(point) {
                    if left_button {
                        if self.pressed.check_set(true) {
                            *redraw = true;
                        }
                    } else {
                        if self.pressed.check_set(false) {
                            click = true;
                            *redraw = true;
                        }
                    }
                } else {
                    if !left_button {
                        if self.pressed.check_set(false) {
                            *redraw = true;
                        }
                    }
                }

                if click {
                    let click_point: Point = point - rect.point();
                    self.emit_click(click_point);
                }
            }
            _ => (),
        }

        focused
    }
}
<commit_msg>Allow setting label bg and fg<commit_after>use orbclient::{Color, Renderer};
use std::cell::{Cell, RefCell};
use std::sync::Arc;

use cell::{CloneCell, CheckSet};
use event::Event;
use point::Point;
use rect::Rect;
use theme::{LABEL_BACKGROUND, LABEL_BORDER, LABEL_FOREGROUND};
use traits::{Border, Click, Place, Text};
use widgets::Widget;

pub struct Label {
    pub rect: Cell<Rect>,
    pub bg: Cell<Color>,
    pub fg: Cell<Color>,
    pub fg_border: Cell<Color>,
    pub border: Cell<bool>,
    pub border_radius: Cell<u32>,
    pub text: CloneCell<String>,
    pub text_offset: Cell<Point>,
    click_callback: RefCell<Option<Arc<Fn(&Label, Point)>>>,
    pressed: Cell<bool>,
}

impl Label {
    pub fn new() -> Arc<Self> {
        Arc::new(Label {
            rect: Cell::new(Rect::default()),
            bg: Cell::new(LABEL_BACKGROUND),
            fg: Cell::new(LABEL_FOREGROUND),
            fg_border: Cell::new(LABEL_BORDER),
            border: Cell::new(false),
            border_radius: Cell::new(0),
            text: CloneCell::new(String::new()),
            text_offset: Cell::new(Point::default()),
            click_callback: RefCell::new(None),
            pressed: Cell::new(false),
        })
    }
}

impl Border for Label {
    fn border(&self, enabled: bool) -> &Self {
        self.border.set(enabled);
        self
    }

    fn border_radius(&self, radius: u32) -> &Self {
        self.border_radius.set(radius);
        self
    }
}

impl Click for Label {
    fn emit_click(&self, point: Point) {
        if let Some(ref click_callback) = *self.click_callback.borrow() {
            click_callback(self, point);
        }
    }

    fn on_click<T: Fn(&Self, Point) + 'static>(&self, func: T) -> &Self {
        *self.click_callback.borrow_mut() = Some(Arc::new(func));
        self
    }
}

impl Place for Label {}

impl Text for Label {
    fn text<S: Into<String>>(&self, text: S) -> &Self {
        self.text.set(text.into());
        self
    }

    fn text_offset(&self, x: i32, y: i32) -> &Self {
        self.text_offset.set(Point::new(x, y));
        self
    }
}

impl Widget for Label {
    fn rect(&self) -> &Cell<Rect> {
        &self.rect
    }

    fn draw(&self, renderer: &mut Renderer, _focused: bool) {
        let rect = self.rect.get();

        let b_r = self.border_radius.get();
        renderer.rounded_rect(rect.x, rect.y, rect.width, rect.height, b_r, true, self.bg.get());
        if self.border.get() {
            renderer.rounded_rect(rect.x, rect.y, rect.width, rect.height, b_r, false, self.fg_border.get());
        }

        let fg = self.fg.get();
        let text = self.text.borrow();

        let mut point = self.text_offset.get();
        for c in text.chars() {
            if c == '\n' {
                point.x = 0;
                point.y += 16;
            } else {
                if point.x + 8 <= rect.width as i32 && point.y + 16 <= rect.height as i32 {
                    renderer.char(point.x + rect.x, point.y + rect.y, c, fg);
                }
                point.x += 8;
            }
        }
    }

    fn event(&self, event: Event, focused: bool, redraw: &mut bool) -> bool {
        match event {
            Event::Mouse { point, left_button, .. } => {
                let mut click = false;

                let rect = self.rect.get();
                if rect.contains(point) {
                    if left_button {
                        if self.pressed.check_set(true) {
                            *redraw = true;
                        }
                    } else {
                        if self.pressed.check_set(false) {
                            click = true;
                            *redraw = true;
                        }
                    }
                } else {
                    if !left_button {
                        if self.pressed.check_set(false) {
                            *redraw = true;
                        }
                    }
                }

                if click {
                    let click_point: Point = point - rect.point();
                    self.emit_click(click_point);
                }
            }
            _ => (),
        }

        focused
    }
}
<|endoftext|>