<commit_before>extern crate rand;
extern crate timely;
extern crate timely_sort;
extern crate differential_dataflow;
extern crate vec_map;

use timely::dataflow::*;
use timely::dataflow::operators::*;

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::AsCollection;
use differential_dataflow::operators::arrange::ArrangeByKey;
use differential_dataflow::operators::group::GroupArranged;
use differential_dataflow::trace::implementations::ord::OrdValSpine;
use differential_dataflow::trace::Cursor;
use differential_dataflow::trace::Batch;
use differential_dataflow::trace::Trace;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();

    // define a new timely dataflow computation.
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        let index = worker.index();
        let peers = worker.peers();

    	// create a a degree counting differential dataflow
    	let (mut input, probe, mut trace) = worker.dataflow(|scope| {

            // create edge input, count a few ways.
            let (input, edges) = scope.new_input();

            // pull off source, and count.
            let arranged = edges.as_collection()
                                .arrange_by_key_hashed();

            (input, arranged.stream.probe().0, arranged.trace.clone())
        });

        let mut trace2 = trace.clone();
        worker.dataflow(move |scope| {

            trace2.create_in(scope)
                  .group_arranged(|_k, s, t| t.push((s[0].0, 1)), OrdValSpine::new());

        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions

        // load up graph dataz
        let &time = input.time();
        for edge in 0..edges {
            if edge % peers == index {
                input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
            }

            // move the data along a bit
            if edge % 10000 == 9999 {
                worker.step();
            }
        }

        let timer = ::std::time::Instant::now();

        input.advance_to(1);
        worker.step_while(|| probe.lt(input.time()));

        if index == 0 {
            let timer = timer.elapsed();
            let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
            println!("Loading finished after {:?}", nanos);
        }

        // change graph, forever
        if batch > 0 {

            for edge in 0usize .. {
                let &time = input.time();
                if edge % peers == index {
                    input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
                    input.send(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), time,-1));
                }

                if edge % batch == (batch - 1) {

                    let timer = ::std::time::Instant::now();

                    trace.advance_by(&[input.time().clone()]);
                    trace.distinguish_since(&[input.time().clone()]);

                    let next = input.epoch() + 1;
                    input.advance_to(next);
                    worker.step_while(|| probe.lt(input.time()));

                    if index == 0 {
                        let timer = timer.elapsed();
                        let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
                        println!("Round {} finished after {:?}", next - 1, nanos);

                        let mut count = 0;

                        // we can directly interrogate the trace...
                        let timer = ::std::time::Instant::now();
                        let mut cursor = trace.cursor();
                        while cursor.key_valid() {
                            while cursor.val_valid() {
                                let mut sum = 0;
                                cursor.map_times(|_,d| sum += d);
                                if sum > 0 { count += 1; }
                                cursor.step_val();
                            }

                            cursor.step_key()
                        }

                        println!("count: {} in {:?}", count, timer.elapsed());

                        // or we can monitor data from a shared queue...
                        let queue = trace.new_listener();
                        let mut borrow = queue.borrow_mut();
                        while let Some((frontier, batch)) = borrow.pop_front() {
                            println!("received from queue:");
                            println!("  frontier: {:?}", frontier);
                            if let Some((time, batch)) = batch {
                                println!("  batch from: {:?} -> {:?}, since: {:?} @ {:?}", batch.lower(), batch.upper(), batch.description().since(), time);
                            }
                        }
                    }
                }
            }
        }

    }).unwrap();
}<commit_msg>made example more mental, to exercise arrange<commit_after>extern crate rand;
extern crate timely;
extern crate timely_sort;
extern crate differential_dataflow;
extern crate vec_map;

// use timely::dataflow::*;
use timely::dataflow::operators::*;

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::AsCollection;
use differential_dataflow::operators::arrange::ArrangeByKey;
use differential_dataflow::operators::group::GroupArranged;
use differential_dataflow::trace::implementations::ord::OrdValSpine;
use differential_dataflow::trace::{Cursor, Trace};
// use differential_dataflow::trace::Batch;
use differential_dataflow::hashable::OrdWrapper;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();

    // define a new timely dataflow computation.
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        let index = worker.index();
        let peers = worker.peers();

    	// create a a degree counting differential dataflow
    	let (mut input, probe, mut trace) = worker.dataflow(|scope| {

            // create edge input, count a few ways.
            let (input, edges) = scope.new_input();

            // pull off source, and count.
            let arranged = edges.as_collection()
                                .arrange_by_key_hashed();

            (input, arranged.stream.probe().0, arranged.trace.clone())
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions

        // load up graph dataz
        let &time = input.time();
        for edge in 0..edges {
            if edge % peers == index {
                input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
            }

            // move the data along a bit
            if edge % 10000 == 9999 {
                worker.step();
            }
        }

        let timer = ::std::time::Instant::now();

        input.advance_to(1);
        worker.step_while(|| probe.lt(input.time()));

        if index == 0 {
            let timer = timer.elapsed();
            let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
            println!("Loading finished after {:?}", nanos);
        }

        // change graph, forever
        if batch > 0 {

            for edge in 0usize .. {
                let &time = input.time();
                if edge % peers == index {
                    input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
                    input.send(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), time,-1));
                }

                if edge % batch == (batch - 1) {

                    let mut trace2 = trace.clone();
                    worker.dataflow(move |scope| {
                        trace2.create_in(scope)
                              .group_arranged(|_k, s, t| t.push((s[0].0, 1)), OrdValSpine::new())
                              .as_collection(|k: &OrdWrapper<u32>, v: &u32| (k.item.clone(),v.clone()))
                              .inspect(|x| println!("{:?}", x));
                    });

                    let timer = ::std::time::Instant::now();

                    trace.advance_by(&[input.time().clone()]);
                    trace.distinguish_since(&[input.time().clone()]);

                    let next = input.epoch() + 1;
                    input.advance_to(next);
                    worker.step_while(|| probe.lt(input.time()));

                    if index == 0 {
                        let timer = timer.elapsed();
                        let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
                        println!("Round {} finished after {:?}", next - 1, nanos);

                        let mut count = 0;

                        // we can directly interrogate the trace...
                        let timer = ::std::time::Instant::now();
                        let mut cursor = trace.cursor();
                        while cursor.key_valid() {
                            while cursor.val_valid() {
                                let mut sum = 0;
                                cursor.map_times(|_,d| sum += d);
                                if sum > 0 { count += 1; }
                                cursor.step_val();
                            }

                            cursor.step_key()
                        }

                        println!("count: {} in {:?}", count, timer.elapsed());
                    }
                }
            }
        }

    }).unwrap();
}<|endoftext|>


<commit_before>extern crate timely;

use timely::dataflow::channels::pact::Pipeline;
use timely::progress::timestamp::RootTimestamp;
use timely::progress::nested::Summary::Local;

use timely::dataflow::*;
use timely::dataflow::operators::*;

fn main() {

    timely::execute_from_args(std::env::args(), |root| {

        root.scoped(|graph| {
            let (handle, stream) = graph.loop_variable::<u64>(RootTimestamp::new(1_000_000), Local(1));
            stream.unary_notify(Pipeline,
                                "Barrier",
                                vec![RootTimestamp::new(0u64)],
                                |_, _, notificator| {
                      while let Some((mut time, _count)) = notificator.next() {
                          println!("iterating");
                          time.inner += 1;
                          notificator.notify_at(&time);
                      }
                  })
                  .connect_loop(handle);
        });

        // spin
        while root.step() { }
    })
}
<commit_msg>accepts argument for number of iterations<commit_after>extern crate timely;

use timely::dataflow::channels::pact::Pipeline;
use timely::progress::timestamp::RootTimestamp;
use timely::progress::nested::Summary::Local;

use timely::dataflow::*;
use timely::dataflow::operators::*;

fn main() {

    let iterations = std::env::args().nth(1).unwrap().parse::<usize>().unwrap_or(1_000_000);

    timely::execute_from_args(std::env::args().skip(2), move |root| {

        root.scoped(move |graph| {
            let (handle, stream) = graph.loop_variable::<u64>(RootTimestamp::new(iterations), Local(1));
            stream.unary_notify(Pipeline,
                                "Barrier",
                                vec![RootTimestamp::new(0)],
                                move |_, _, notificator| {
                      while let Some((mut time, _count)) = notificator.next() {
                        //   println!("iterating");
                          time.inner += 1;
                          if time.inner < iterations {
                              notificator.notify_at(&time);
                          }
                      }
                  })
                  .connect_loop(handle);
        });

        // spin
        while root.step() { }
    })
}
<|endoftext|>


<commit_before>#![deny(warnings)]

use hyper::service::{make_service_fn, service_fn};
use hyper::{Client, Error, Server};
use std::net::SocketAddr;

#[tokio::main]
async fn main() {
    pretty_env_logger::init();

    let in_addr = ([127, 0, 0, 1], 3001).into();
    let out_addr: SocketAddr = ([127, 0, 0, 1], 3000).into();

    let client_main = Client::new();

    let out_addr_clone = out_addr.clone();

    // The closure inside `make_service_fn` is run for each connection,
    // creating a 'service' to handle requests for that specific connection.
    let make_service = make_service_fn(move |_| {
        let client = client_main.clone();

        async move {
            // This is the `Service` that will handle the connection.
            // `service_fn` is a helper to convert a function that
            // returns a Response into a `Service`.
            Ok::<_, Error>(service_fn(move |mut req| {
                let uri_string = format!(
                    "http://{}/{}",
                    out_addr_clone,
                    req.uri().path_and_query().map(|x| x.as_str()).unwrap_or("")
                );
                let uri = uri_string.parse().unwrap();
                *req.uri_mut() = uri;
                client.request(req)
            }))
        }
    });

    let server = Server::bind(&in_addr).serve(make_service);

    println!("Listening on http://{}", in_addr);
    println!("Proxying on http://{}", out_addr);

    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}
<commit_msg>docs(examples): gateway: remove extra slash for uri (#2351)<commit_after>#![deny(warnings)]

use hyper::service::{make_service_fn, service_fn};
use hyper::{Client, Error, Server};
use std::net::SocketAddr;

#[tokio::main]
async fn main() {
    pretty_env_logger::init();

    let in_addr = ([127, 0, 0, 1], 3001).into();
    let out_addr: SocketAddr = ([127, 0, 0, 1], 3000).into();

    let client_main = Client::new();

    let out_addr_clone = out_addr.clone();

    // The closure inside `make_service_fn` is run for each connection,
    // creating a 'service' to handle requests for that specific connection.
    let make_service = make_service_fn(move |_| {
        let client = client_main.clone();

        async move {
            // This is the `Service` that will handle the connection.
            // `service_fn` is a helper to convert a function that
            // returns a Response into a `Service`.
            Ok::<_, Error>(service_fn(move |mut req| {
                let uri_string = format!(
                    "http://{}{}",
                    out_addr_clone,
                    req.uri()
                        .path_and_query()
                        .map(|x| x.as_str())
                        .unwrap_or("/")
                );
                let uri = uri_string.parse().unwrap();
                *req.uri_mut() = uri;
                client.request(req)
            }))
        }
    });

    let server = Server::bind(&in_addr).serve(make_service);

    println!("Listening on http://{}", in_addr);
    println!("Proxying on http://{}", out_addr);

    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::HashSet;
use std::rc::Rc;

use rand::{self, Rng};

use slackbot::{CommandHandler,Sender};

pub struct RegisterCommandHandler {
    registered_users: Rc<RefCell<HashSet<String>>>
}

impl RegisterCommandHandler {
    pub fn new(user_store: Rc<RefCell<HashSet<String>>>) -> Self {
        RegisterCommandHandler {
            registered_users: user_store
        }
    }
}

impl CommandHandler for RegisterCommandHandler {
    fn handle(&mut self, sender: &mut Sender, args: &Vec<String>) {
        let username = if args.len() > 0 { args[0].clone() } else { sender.user.name.clone() };
        if self.registered_users.borrow_mut().insert(username.clone()) {
            sender.channel.write(format!("Added {0} to the daily foosball pool!", username)).unwrap();
        } else {
            sender.channel.write(format!("{0} is already in the daily foosball pool.", username)).unwrap();
        }
    }
}

pub struct UnregisterCommandHandler {
    registered_users: Rc<RefCell<HashSet<String>>>
}

impl UnregisterCommandHandler {
    pub fn new(user_store: Rc<RefCell<HashSet<String>>>) -> Self {
        UnregisterCommandHandler {
            registered_users: user_store
        }
    }
}

impl CommandHandler for UnregisterCommandHandler {
    fn handle(&mut self, sender: &mut Sender, _: &Vec<String>) {
        if self.registered_users.borrow_mut().remove(&sender.user.name[..]) {
            sender.channel.write(format!("Removed {0} from the daily foosball pool!", sender.user.name)).unwrap();
        } else {
            sender.channel.write(format!("{0} was not in the daily foosball pool.", sender.user.name)).unwrap();
        }
    }
}

pub struct InfoCommandHandler {
    registered_users: Rc<RefCell<HashSet<String>>>
}

impl InfoCommandHandler {
    pub fn new(user_store: Rc<RefCell<HashSet<String>>>) -> Self {
        InfoCommandHandler {
            registered_users: user_store
        }
    }
}

impl CommandHandler for InfoCommandHandler {
    fn handle(&mut self, sender: &mut Sender, _: &Vec<String>) {
        let users = self.registered_users.borrow();
        sender.channel.write(format!("Users in the pool: {:?}", users)).unwrap();
    }
}

pub struct GameCommandHandler {
    registered_users: Rc<RefCell<HashSet<String>>>
}

impl GameCommandHandler {
    pub fn new(user_store: Rc<RefCell<HashSet<String>>>) -> Self {
        GameCommandHandler {
            registered_users: user_store
        }
    }
}

impl CommandHandler for GameCommandHandler {
    fn handle(&mut self, sender: &mut Sender, _: &Vec<String>) {
        let users = self.registered_users.borrow();
        if users.len() < 4 {
            sender.channel.write("Not enough players! Need 4 players to be registered to start a game.").unwrap();
        } else {
            let mut users = &mut users.iter().collect::<Vec<_>>()[..];
            let mut rng = rand::thread_rng();
            rng.shuffle(users);
            let team1 = &users[..2];
            let team2 = &users[2..4];
            sender.channel.write(format!("⚽ We have a game! {:?} vs {:?}", team1, team2)).unwrap();
        }
    }
}
<commit_msg>Add 1v1 game style<commit_after>use std::cell::RefCell;
use std::collections::HashSet;
use std::rc::Rc;

use rand::{self, Rng};

use slackbot::{CommandHandler,Sender};

pub struct RegisterCommandHandler {
    registered_users: Rc<RefCell<HashSet<String>>>
}

impl RegisterCommandHandler {
    pub fn new(user_store: Rc<RefCell<HashSet<String>>>) -> Self {
        RegisterCommandHandler {
            registered_users: user_store
        }
    }
}

impl CommandHandler for RegisterCommandHandler {
    fn handle(&mut self, sender: &mut Sender, args: &Vec<String>) {
        let username = if args.len() > 0 { args[0].clone() } else { sender.user.name.clone() };
        if self.registered_users.borrow_mut().insert(username.clone()) {
            sender.channel.write(format!("Added {0} to the daily foosball pool!", username)).unwrap();
        } else {
            sender.channel.write(format!("{0} is already in the daily foosball pool.", username)).unwrap();
        }
    }
}

pub struct UnregisterCommandHandler {
    registered_users: Rc<RefCell<HashSet<String>>>
}

impl UnregisterCommandHandler {
    pub fn new(user_store: Rc<RefCell<HashSet<String>>>) -> Self {
        UnregisterCommandHandler {
            registered_users: user_store
        }
    }
}

impl CommandHandler for UnregisterCommandHandler {
    fn handle(&mut self, sender: &mut Sender, _: &Vec<String>) {
        if self.registered_users.borrow_mut().remove(&sender.user.name[..]) {
            sender.channel.write(format!("Removed {0} from the daily foosball pool!", sender.user.name)).unwrap();
        } else {
            sender.channel.write(format!("{0} was not in the daily foosball pool.", sender.user.name)).unwrap();
        }
    }
}

pub struct InfoCommandHandler {
    registered_users: Rc<RefCell<HashSet<String>>>
}

impl InfoCommandHandler {
    pub fn new(user_store: Rc<RefCell<HashSet<String>>>) -> Self {
        InfoCommandHandler {
            registered_users: user_store
        }
    }
}

impl CommandHandler for InfoCommandHandler {
    fn handle(&mut self, sender: &mut Sender, _: &Vec<String>) {
        let users = self.registered_users.borrow();
        sender.channel.write(format!("Users in the pool: {:?}", users)).unwrap();
    }
}

pub struct GameCommandHandler {
    registered_users: Rc<RefCell<HashSet<String>>>
}

impl GameCommandHandler {
    pub fn new(user_store: Rc<RefCell<HashSet<String>>>) -> Self {
        GameCommandHandler {
            registered_users: user_store
        }
    }
}

impl CommandHandler for GameCommandHandler {
    fn handle(&mut self, sender: &mut Sender, args: &Vec<String>) {
        let team_size = if args.len() > 0 && args[0] == "1v1" { 1 } else { 2 };
        let users = self.registered_users.borrow();
        if users.len() < team_size * 2 {
            sender.channel.write(format!("Not enough players! Need {0} players to be registered to start a game.", team_size * 2)).unwrap();
        } else {
            let mut users = &mut users.iter().collect::<Vec<_>>()[..];
            let mut rng = rand::thread_rng();
            rng.shuffle(users);
            let team1 = &users[..team_size];
            let team2 = &users[team_size..team_size * 2];
            sender.channel.write(format!("⚽ We have a game! {:?} vs {:?}", team1, team2)).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use parking_lot::{RwLock, RwLockWriteGuard};
use serde;
use std;
use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::thread;

use bifrost_hasher::{hash_bytes, hash_str};
use conshash::weights::client::SMClient as WeightSMClient;
use conshash::weights::DEFAULT_SERVICE_ID;
use membership::client::{Member, ObserverClient as MembershipClient};
use raft::client::{RaftClient, SubscriptionError, SubscriptionReceipt};
use raft::state_machine::master::ExecError;
use rand;
use utils::bincode::serialize;

use futures::prelude::*;
use std::collections::BTreeMap;
use std::collections::BTreeSet;

pub mod weights;

#[derive(Debug)]
pub enum Action {
    Joined,
    Left,
}

#[derive(Debug)]
pub enum InitTableError {
    GroupNotExisted,
    NoWeightService(ExecError),
    NoWeightGroup,
    NoWeightInfo,
    Unknown,
}

#[derive(Debug)]
pub enum CHError {
    WatchError(Result<Result<SubscriptionReceipt, SubscriptionError>, ExecError>),
    InitTableError(InitTableError),
}

struct LookupTables {
    nodes: Vec<u64>,
    addrs: HashMap<u64, String>,
}

pub struct ConsistentHashing {
    tables: RwLock<LookupTables>,
    membership: Arc<MembershipClient>,
    weight_sm_client: WeightSMClient,
    group_name: String,
    watchers: RwLock<Vec<Box<Fn(&Member, &Action, &LookupTables, &Vec<u64>) + Send + Sync>>>,
    version: AtomicU64,
}

impl ConsistentHashing {
    pub fn new_with_id(
        id: u64,
        group: &str,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<ConsistentHashing>, CHError> {
        let membership = Arc::new(MembershipClient::new(raft_client));
        let ch = Arc::new(ConsistentHashing {
            tables: RwLock::new(LookupTables {
                nodes: Vec::new(),
                addrs: HashMap::new(),
            }),
            membership: membership.clone(),
            weight_sm_client: WeightSMClient::new(id, &raft_client),
            group_name: group.to_string(),
            watchers: RwLock::new(Vec::new()),
            version: AtomicU64::new(0),
        });
        {
            let ch = ch.clone();
            let res = membership
                .on_group_member_joined(
                    move |r| {
                        if let Ok((member, version)) = r {
                            server_joined(&ch, member, version);
                        }
                    },
                    group,
                )
                .wait();
            if let Ok(Ok(_)) = res {
            } else {
                return Err(CHError::WatchError(res));
            }
        }
        {
            let ch = ch.clone();
            let res = membership
                .on_group_member_online(
                    move |r| {
                        if let Ok((member, version)) = r {
                            server_joined(&ch, member, version);
                        }
                    },
                    group,
                )
                .wait();
            if let Ok(Ok(_)) = res {
            } else {
                return Err(CHError::WatchError(res));
            }
        }
        {
            let ch = ch.clone();
            let res = membership
                .on_group_member_left(
                    move |r| {
                        if let Ok((member, version)) = r {
                            server_left(&ch, member, version);
                        }
                    },
                    group,
                )
                .wait();
            if let Ok(Ok(_)) = res {
            } else {
                return Err(CHError::WatchError(res));
            }
        }
        {
            let ch = ch.clone();
            let res = membership
                .on_group_member_offline(
                    move |r| {
                        if let Ok((member, version)) = r {
                            server_left(&ch, member, version);
                        }
                    },
                    group,
                )
                .wait();
            if let Ok(Ok(_)) = res {
            } else {
                return Err(CHError::WatchError(res));
            }
        }
        Ok(ch)
    }
    pub fn new(
        group: &str,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<ConsistentHashing>, CHError> {
        Self::new_with_id(DEFAULT_SERVICE_ID, group, raft_client)
    }
    pub fn new_client(
        group: &str,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<ConsistentHashing>, CHError> {
        Self::new_client_with_id(DEFAULT_SERVICE_ID, group, raft_client)
    }
    pub fn new_client_with_id(
        id: u64,
        group: &str,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<ConsistentHashing>, CHError> {
        match ConsistentHashing::new_with_id(id, group, raft_client) {
            Err(e) => Err(e),
            Ok(ch) => match ch.init_table() {
                Err(e) => Err(CHError::InitTableError(e)),
                Ok(_) => Ok(ch.clone()),
            },
        }
    }
    pub fn init_table(&self) -> Result<(), InitTableError> {
        let mut table = &mut self.tables.write();
        self.init_table_(&mut table)
    }
    pub fn to_server_name(&self, server_id: u64) -> String {
        let lookup_table = self.tables.read();
        lookup_table.addrs.get(&server_id).unwrap().clone()
    }
    pub fn to_server_name_option(&self, server_id: Option<u64>) -> Option<String> {
        server_id.map(|id| {
            let lookup_table = self.tables.read();
            lookup_table.addrs.get(&id).unwrap().clone()
        })
    }
    pub fn get_server_id(&self, hash: u64) -> Option<u64> {
        let lookup_table = self.tables.read();
        let nodes = &lookup_table.nodes;
        let slot_count = nodes.len();
        if slot_count == 0 {
            return None;
        }
        let result = nodes.get(self.jump_hash(slot_count, hash));
        debug!("Hash {} have been point to {:?}", hash, result);
        result.cloned()
    }
    pub fn jump_hash(&self, slot_count: usize, hash: u64) -> usize {
        let mut b: i64 = -1;
        let mut j: i64 = 0;
        let mut h = hash;
        while j < (slot_count as i64) {
            b = j;
            h = h.wrapping_mul(2862933555777941757).wrapping_add(1);
            j = (((b.wrapping_add(1)) as f64) * ((1i64 << 31) as f64)
                / (((h >> 33).wrapping_add(1)) as f64)) as i64;
        }
        debug!(
            "Jump hash point to index {} for {}, with slots {}",
            b, hash, slot_count
        );
        b as usize
    }
    pub fn get_server(&self, hash: u64) -> Option<String> {
        self.to_server_name_option(self.get_server_id(hash))
    }
    pub fn get_server_by_string(&self, string: &String) -> Option<String> {
        self.get_server(hash_str(string))
    }
    pub fn get_server_by<T>(&self, obj: &T) -> Option<String>
    where
        T: serde::Serialize,
    {
        self.get_server(hash_bytes(serialize(obj).as_slice()))
    }
    pub fn get_server_id_by_string(&self, string: &String) -> Option<u64> {
        self.get_server_id(hash_str(string))
    }
    pub fn get_server_id_by<T>(&self, obj: &T) -> Option<u64>
    where
        T: serde::Serialize,
    {
        self.get_server_id(hash_bytes(serialize(obj).as_slice()))
    }
    pub fn rand_server(&self) -> Option<String> {
        let rand = rand::random::<u64>();
        self.get_server(rand)
    }
    pub fn nodes_count(&self) -> usize {
        let lookup_table = self.tables.read();
        return lookup_table.nodes.len();
    }
    pub fn set_weight(
        &self,
        server_name: &String,
        weight: u64,
    ) -> impl Future<Item = bool, Error = ExecError> {
        let group_id = hash_str(&self.group_name);
        let server_id = hash_str(server_name);
        self.weight_sm_client
            .set_weight(&group_id, &server_id, &weight)
            .map(|res| if let Ok(_) = res { true } else { false })
    }
    pub fn watch_all_actions<F>(&self, f: F)
    where
        F: Fn(&Member, &Action, &LookupTables, &Vec<u64>) + 'static + Send + Sync,
    {
        let mut watchers = self.watchers.write();
        watchers.push(Box::new(f));
    }
    pub fn watch_server_nodes_range_changed<F>(&self, server: &String, f: F)
    // return ranges [...,...)
    where
        F: Fn((usize, u32)) + 'static + Send + Sync,
    {
        let server_id = hash_str(server);
        let wrapper = move |_: &Member, _: &Action, lookup_table: &LookupTables, _: &Vec<u64>| {
            let nodes = &lookup_table.nodes;
            let node_len = nodes.len();
            let mut weight = 0;
            let mut start = None;
            for ni in 0..node_len {
                let node = nodes[ni];
                if node == server_id {
                    weight += 1;
                    if start.is_none() {
                        start = Some(ni)
                    }
                }
            }
            if start.is_some() {
                f((start.unwrap(), weight));
            } else {
                warn!("No node exists for watch");
            }
        };
        self.watch_all_actions(wrapper);
    }

    fn init_table_(
        &self,
        lookup_table: &mut RwLockWriteGuard<LookupTables>,
    ) -> Result<(), InitTableError> {
        if let Ok(Ok((mut members, version))) =
            self.membership.group_members(&self.group_name, true).wait()
        {
            let group_id = hash_str(&self.group_name);
            match self.weight_sm_client.get_weights(&group_id).wait() {
                Ok(Ok(Some(weights))) => {
                    if let Some(min_weight) = weights.values().min() {
                        let mut factors: BTreeMap<u64, u32> = BTreeMap::new();
                        let min_weight = *min_weight as f64;
                        for member in members.iter() {
                            let k = member.id;
                            let w = match weights.get(&k) {
                                Some(w) => *w as f64,
                                None => min_weight,
                            };
                            factors.insert(k, (w / min_weight) as u32);
                        }
                        let factor_sum: u32 = factors.values().sum();
                        lookup_table.nodes = Vec::with_capacity(factor_sum as usize);
                        for member in members.iter() {
                            lookup_table.addrs.insert(member.id, member.address.clone());
                        }
                        for (server_id, weight) in factors.into_iter() {
                            for i in 0..weight {
                                lookup_table.nodes.push(server_id);
                            }
                        }
                        self.version.store(version, Ordering::Relaxed);
                        Ok(())
                    } else {
                        Err(InitTableError::NoWeightInfo)
                    }
                }
                Err(e) => Err(InitTableError::NoWeightService(e)),
                Ok(Ok(None)) => Err(InitTableError::NoWeightGroup),
                _ => Err(InitTableError::Unknown),
            }
        } else {
            Err(InitTableError::GroupNotExisted)
        }
    }
}

fn server_joined(ch: &Arc<ConsistentHashing>, member: Member, version: u64) {
    server_changed(ch, member, Action::Joined, version);
}
fn server_left(ch: &Arc<ConsistentHashing>, member: Member, version: u64) {
    server_changed(ch, member, Action::Left, version);
}
fn server_changed(ch: &Arc<ConsistentHashing>, member: Member, action: Action, version: u64) {
    let ch_version = ch.version.load(Ordering::Relaxed);
    if ch_version < version {
        let ch = ch.clone();
        thread::Builder::new()
            .name(format!(
                "Conshash member changes update - {}",
                member.address
            ))
            .spawn(move || {
                let mut lookup_table = ch.tables.write();
                let watchers = ch.watchers.read();
                let ch_version = ch.version.load(Ordering::Relaxed);
                if ch_version >= version {
                    return;
                }
                let old_nodes = lookup_table.nodes.clone();
                ch.init_table_(&mut lookup_table);
                for watch in watchers.iter() {
                    watch(&member, &action, &*lookup_table, &old_nodes);
                }
            });
    }
}
<commit_msg>run future on core<commit_after>use parking_lot::{RwLock, RwLockWriteGuard};
use serde;
use std;
use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::thread;

use bifrost_hasher::{hash_bytes, hash_str};
use conshash::weights::client::SMClient as WeightSMClient;
use conshash::weights::DEFAULT_SERVICE_ID;
use membership::client::{Member, ObserverClient as MembershipClient};
use raft::client::{RaftClient, SubscriptionError, SubscriptionReceipt};
use raft::state_machine::master::ExecError;
use rand;
use utils::bincode::serialize;

use futures::prelude::*;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use tokio_core::reactor::Core;

pub mod weights;

#[derive(Debug)]
pub enum Action {
    Joined,
    Left,
}

#[derive(Debug)]
pub enum InitTableError {
    GroupNotExisted,
    NoWeightService(ExecError),
    NoWeightGroup,
    NoWeightInfo,
    Unknown,
}

#[derive(Debug)]
pub enum CHError {
    WatchError(Result<Result<SubscriptionReceipt, SubscriptionError>, ExecError>),
    InitTableError(InitTableError),
}

struct LookupTables {
    nodes: Vec<u64>,
    addrs: HashMap<u64, String>,
}

pub struct ConsistentHashing {
    tables: RwLock<LookupTables>,
    membership: Arc<MembershipClient>,
    weight_sm_client: WeightSMClient,
    group_name: String,
    watchers: RwLock<Vec<Box<Fn(&Member, &Action, &LookupTables, &Vec<u64>) + Send + Sync>>>,
    version: AtomicU64,
}

impl ConsistentHashing {
    pub fn new_with_id(
        id: u64,
        group: &str,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<ConsistentHashing>, CHError> {
        let membership = Arc::new(MembershipClient::new(raft_client));
        let ch = Arc::new(ConsistentHashing {
            tables: RwLock::new(LookupTables {
                nodes: Vec::new(),
                addrs: HashMap::new(),
            }),
            membership: membership.clone(),
            weight_sm_client: WeightSMClient::new(id, &raft_client),
            group_name: group.to_string(),
            watchers: RwLock::new(Vec::new()),
            version: AtomicU64::new(0),
        });
        let mut core = Core::new().unwrap();
        {
            let ch = ch.clone();
            let res_fut = membership
                .on_group_member_joined(
                    move |r| {
                        if let Ok((member, version)) = r {
                            server_joined(&ch, member, version);
                        }
                    },
                    group,
                );
            let res = core.run(res_fut);
            if let Ok(Ok(_)) = res {
            } else {
                return Err(CHError::WatchError(res));
            }
        }
        {
            let ch = ch.clone();
            let res_fut = membership
                .on_group_member_online(
                    move |r| {
                        if let Ok((member, version)) = r {
                            server_joined(&ch, member, version);
                        }
                    },
                    group,
                );
            let res = core.run(res_fut);
            if let Ok(Ok(_)) = res {
            } else {
                return Err(CHError::WatchError(res));
            }
        }
        {
            let ch = ch.clone();
            let res_fut = membership
                .on_group_member_left(
                    move |r| {
                        if let Ok((member, version)) = r {
                            server_left(&ch, member, version);
                        }
                    },
                    group,
                );
            let res = core.run(res_fut);
            if let Ok(Ok(_)) = res {
            } else {
                return Err(CHError::WatchError(res));
            }
        }
        {
            let ch = ch.clone();
            let res_fut = membership
                .on_group_member_offline(
                    move |r| {
                        if let Ok((member, version)) = r {
                            server_left(&ch, member, version);
                        }
                    },
                    group,
                );
            let res = core.run(res_fut);
            if let Ok(Ok(_)) = res {
            } else {
                return Err(CHError::WatchError(res));
            }
        }
        Ok(ch)
    }
    pub fn new(
        group: &str,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<ConsistentHashing>, CHError> {
        Self::new_with_id(DEFAULT_SERVICE_ID, group, raft_client)
    }
    pub fn new_client(
        group: &str,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<ConsistentHashing>, CHError> {
        Self::new_client_with_id(DEFAULT_SERVICE_ID, group, raft_client)
    }
    pub fn new_client_with_id(
        id: u64,
        group: &str,
        raft_client: &Arc<RaftClient>,
    ) -> Result<Arc<ConsistentHashing>, CHError> {
        match ConsistentHashing::new_with_id(id, group, raft_client) {
            Err(e) => Err(e),
            Ok(ch) => match ch.init_table() {
                Err(e) => Err(CHError::InitTableError(e)),
                Ok(_) => Ok(ch.clone()),
            },
        }
    }
    pub fn init_table(&self) -> Result<(), InitTableError> {
        let mut table = &mut self.tables.write();
        self.init_table_(&mut table)
    }
    pub fn to_server_name(&self, server_id: u64) -> String {
        let lookup_table = self.tables.read();
        lookup_table.addrs.get(&server_id).unwrap().clone()
    }
    pub fn to_server_name_option(&self, server_id: Option<u64>) -> Option<String> {
        server_id.map(|id| {
            let lookup_table = self.tables.read();
            lookup_table.addrs.get(&id).unwrap().clone()
        })
    }
    pub fn get_server_id(&self, hash: u64) -> Option<u64> {
        let lookup_table = self.tables.read();
        let nodes = &lookup_table.nodes;
        let slot_count = nodes.len();
        if slot_count == 0 {
            return None;
        }
        let result = nodes.get(self.jump_hash(slot_count, hash));
        debug!("Hash {} have been point to {:?}", hash, result);
        result.cloned()
    }
    pub fn jump_hash(&self, slot_count: usize, hash: u64) -> usize {
        let mut b: i64 = -1;
        let mut j: i64 = 0;
        let mut h = hash;
        while j < (slot_count as i64) {
            b = j;
            h = h.wrapping_mul(2862933555777941757).wrapping_add(1);
            j = (((b.wrapping_add(1)) as f64) * ((1i64 << 31) as f64)
                / (((h >> 33).wrapping_add(1)) as f64)) as i64;
        }
        debug!(
            "Jump hash point to index {} for {}, with slots {}",
            b, hash, slot_count
        );
        b as usize
    }
    pub fn get_server(&self, hash: u64) -> Option<String> {
        self.to_server_name_option(self.get_server_id(hash))
    }
    pub fn get_server_by_string(&self, string: &String) -> Option<String> {
        self.get_server(hash_str(string))
    }
    pub fn get_server_by<T>(&self, obj: &T) -> Option<String>
    where
        T: serde::Serialize,
    {
        self.get_server(hash_bytes(serialize(obj).as_slice()))
    }
    pub fn get_server_id_by_string(&self, string: &String) -> Option<u64> {
        self.get_server_id(hash_str(string))
    }
    pub fn get_server_id_by<T>(&self, obj: &T) -> Option<u64>
    where
        T: serde::Serialize,
    {
        self.get_server_id(hash_bytes(serialize(obj).as_slice()))
    }
    pub fn rand_server(&self) -> Option<String> {
        let rand = rand::random::<u64>();
        self.get_server(rand)
    }
    pub fn nodes_count(&self) -> usize {
        let lookup_table = self.tables.read();
        return lookup_table.nodes.len();
    }
    pub fn set_weight(
        &self,
        server_name: &String,
        weight: u64,
    ) -> impl Future<Item = bool, Error = ExecError> {
        let group_id = hash_str(&self.group_name);
        let server_id = hash_str(server_name);
        self.weight_sm_client
            .set_weight(&group_id, &server_id, &weight)
            .map(|res| if let Ok(_) = res { true } else { false })
    }
    pub fn watch_all_actions<F>(&self, f: F)
    where
        F: Fn(&Member, &Action, &LookupTables, &Vec<u64>) + 'static + Send + Sync,
    {
        let mut watchers = self.watchers.write();
        watchers.push(Box::new(f));
    }
    pub fn watch_server_nodes_range_changed<F>(&self, server: &String, f: F)
    // return ranges [...,...)
    where
        F: Fn((usize, u32)) + 'static + Send + Sync,
    {
        let server_id = hash_str(server);
        let wrapper = move |_: &Member, _: &Action, lookup_table: &LookupTables, _: &Vec<u64>| {
            let nodes = &lookup_table.nodes;
            let node_len = nodes.len();
            let mut weight = 0;
            let mut start = None;
            for ni in 0..node_len {
                let node = nodes[ni];
                if node == server_id {
                    weight += 1;
                    if start.is_none() {
                        start = Some(ni)
                    }
                }
            }
            if start.is_some() {
                f((start.unwrap(), weight));
            } else {
                warn!("No node exists for watch");
            }
        };
        self.watch_all_actions(wrapper);
    }

    fn init_table_(
        &self,
        lookup_table: &mut RwLockWriteGuard<LookupTables>,
    ) -> Result<(), InitTableError> {
        if let Ok(Ok((mut members, version))) =
            self.membership.group_members(&self.group_name, true).wait()
        {
            let group_id = hash_str(&self.group_name);
            match self.weight_sm_client.get_weights(&group_id).wait() {
                Ok(Ok(Some(weights))) => {
                    if let Some(min_weight) = weights.values().min() {
                        let mut factors: BTreeMap<u64, u32> = BTreeMap::new();
                        let min_weight = *min_weight as f64;
                        for member in members.iter() {
                            let k = member.id;
                            let w = match weights.get(&k) {
                                Some(w) => *w as f64,
                                None => min_weight,
                            };
                            factors.insert(k, (w / min_weight) as u32);
                        }
                        let factor_sum: u32 = factors.values().sum();
                        lookup_table.nodes = Vec::with_capacity(factor_sum as usize);
                        for member in members.iter() {
                            lookup_table.addrs.insert(member.id, member.address.clone());
                        }
                        for (server_id, weight) in factors.into_iter() {
                            for i in 0..weight {
                                lookup_table.nodes.push(server_id);
                            }
                        }
                        self.version.store(version, Ordering::Relaxed);
                        Ok(())
                    } else {
                        Err(InitTableError::NoWeightInfo)
                    }
                }
                Err(e) => Err(InitTableError::NoWeightService(e)),
                Ok(Ok(None)) => Err(InitTableError::NoWeightGroup),
                _ => Err(InitTableError::Unknown),
            }
        } else {
            Err(InitTableError::GroupNotExisted)
        }
    }
}

fn server_joined(ch: &Arc<ConsistentHashing>, member: Member, version: u64) {
    server_changed(ch, member, Action::Joined, version);
}
fn server_left(ch: &Arc<ConsistentHashing>, member: Member, version: u64) {
    server_changed(ch, member, Action::Left, version);
}
fn server_changed(ch: &Arc<ConsistentHashing>, member: Member, action: Action, version: u64) {
    let ch_version = ch.version.load(Ordering::Relaxed);
    if ch_version < version {
        let ch = ch.clone();
        thread::Builder::new()
            .name(format!(
                "Conshash member changes update - {}",
                member.address
            ))
            .spawn(move || {
                let mut lookup_table = ch.tables.write();
                let watchers = ch.watchers.read();
                let ch_version = ch.version.load(Ordering::Relaxed);
                if ch_version >= version {
                    return;
                }
                let old_nodes = lookup_table.nodes.clone();
                ch.init_table_(&mut lookup_table);
                for watch in watchers.iter() {
                    watch(&member, &action, &*lookup_table, &old_nodes);
                }
            });
    }
}
<|endoftext|>


<commit_before>use crate::core::compiler::CompileKind;
use crate::util::interning::InternedString;
use crate::util::{CargoResult, Config, RustfixDiagnosticServer};
use anyhow::bail;
use cargo_util::ProcessBuilder;
use serde::ser;
use std::cell::RefCell;
use std::path::PathBuf;

/// Configuration information for a rustc build.
#[derive(Debug)]
pub struct BuildConfig {
    /// The requested kind of compilation for this session
    pub requested_kinds: Vec<CompileKind>,
    /// Number of rustc jobs to run in parallel.
    pub jobs: u32,
    /// Do not abort the build as soon as there is an error.
    pub keep_going: bool,
    /// Build profile
    pub requested_profile: InternedString,
    /// The mode we are compiling in.
    pub mode: CompileMode,
    /// `true` to print stdout in JSON format (for machine reading).
    pub message_format: MessageFormat,
    /// Force Cargo to do a full rebuild and treat each target as changed.
    pub force_rebuild: bool,
    /// Output a build plan to stdout instead of actually compiling.
    pub build_plan: bool,
    /// Output the unit graph to stdout instead of actually compiling.
    pub unit_graph: bool,
    /// An optional override of the rustc process for primary units
    pub primary_unit_rustc: Option<ProcessBuilder>,
    /// A thread used by `cargo fix` to receive messages on a socket regarding
    /// the success/failure of applying fixes.
    pub rustfix_diagnostic_server: RefCell<Option<RustfixDiagnosticServer>>,
    /// The directory to copy final artifacts to. Note that even if `out_dir` is
    /// set, a copy of artifacts still could be found a `target/(debug\release)`
    /// as usual.
    // Note that, although the cmd-line flag name is `out-dir`, in code we use
    // `export_dir`, to avoid confusion with out dir at `target/debug/deps`.
    pub export_dir: Option<PathBuf>,
    /// `true` to output a future incompatibility report at the end of the build
    pub future_incompat_report: bool,
    /// Which kinds of build timings to output (empty if none).
    pub timing_outputs: Vec<TimingOutput>,
}

impl BuildConfig {
    /// Parses all config files to learn about build configuration. Currently
    /// configured options are:
    ///
    /// * `build.jobs`
    /// * `build.target`
    /// * `target.$target.ar`
    /// * `target.$target.linker`
    /// * `target.$target.libfoo.metadata`
    pub fn new(
        config: &Config,
        jobs: Option<i32>,
        keep_going: bool,
        requested_targets: &[String],
        mode: CompileMode,
    ) -> CargoResult<BuildConfig> {
        let cfg = config.build_config()?;
        let requested_kinds = CompileKind::from_requested_targets(config, requested_targets)?;
        if jobs == Some(0) {
            anyhow::bail!("jobs may not be 0")
        }
        if jobs.is_some() && config.jobserver_from_env().is_some() {
            config.shell().warn(
                "a `-j` argument was passed to Cargo but Cargo is \
                 also configured with an external jobserver in \
                 its environment, ignoring the `-j` parameter",
            )?;
        }
        let jobs = match jobs.or(cfg.jobs) {
            None => ::num_cpus::get() as u32,
            Some(0) => anyhow::bail!("jobs may not be 0"),
            Some(j) if j < 0 => (::num_cpus::get() as i32 + j).max(1) as u32,
            Some(j) => j as u32,
        };

        if config.cli_unstable().build_std.is_some() && requested_kinds[0].is_host() {
            // TODO: This should eventually be fixed.
            anyhow::bail!("-Zbuild-std requires --target");
        }

        Ok(BuildConfig {
            requested_kinds,
            jobs,
            keep_going,
            requested_profile: InternedString::new("dev"),
            mode,
            message_format: MessageFormat::Human,
            force_rebuild: false,
            build_plan: false,
            unit_graph: false,
            primary_unit_rustc: None,
            rustfix_diagnostic_server: RefCell::new(None),
            export_dir: None,
            future_incompat_report: false,
            timing_outputs: Vec::new(),
        })
    }

    /// Whether or not the *user* wants JSON output. Whether or not rustc
    /// actually uses JSON is decided in `add_error_format`.
    pub fn emit_json(&self) -> bool {
        matches!(self.message_format, MessageFormat::Json { .. })
    }

    pub fn test(&self) -> bool {
        self.mode == CompileMode::Test || self.mode == CompileMode::Bench
    }

    pub fn single_requested_kind(&self) -> CargoResult<CompileKind> {
        match self.requested_kinds.len() {
            1 => Ok(self.requested_kinds[0]),
            _ => bail!("only one `--target` argument is supported"),
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MessageFormat {
    Human,
    Json {
        /// Whether rustc diagnostics are rendered by cargo or included into the
        /// output stream.
        render_diagnostics: bool,
        /// Whether the `rendered` field of rustc diagnostics are using the
        /// "short" rendering.
        short: bool,
        /// Whether the `rendered` field of rustc diagnostics embed ansi color
        /// codes.
        ansi: bool,
    },
    Short,
}

/// The general "mode" for what to do.
/// This is used for two purposes. The commands themselves pass this in to
/// `compile_ws` to tell it the general execution strategy. This influences
/// the default targets selected. The other use is in the `Unit` struct
/// to indicate what is being done with a specific target.
#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
pub enum CompileMode {
    /// A target being built for a test.
    Test,
    /// Building a target with `rustc` (lib or bin).
    Build,
    /// Building a target with `rustc` to emit `rmeta` metadata only. If
    /// `test` is true, then it is also compiled with `--test` to check it like
    /// a test.
    Check { test: bool },
    /// Used to indicate benchmarks should be built. This is not used in
    /// `Unit`, because it is essentially the same as `Test` (indicating
    /// `--test` should be passed to rustc) and by using `Test` instead it
    /// allows some de-duping of Units to occur.
    Bench,
    /// A target that will be documented with `rustdoc`.
    /// If `deps` is true, then it will also document all dependencies.
    Doc { deps: bool },
    /// A target that will be tested with `rustdoc`.
    Doctest,
    /// An example or library that will be scraped for function calls by `rustdoc`.
    Docscrape,
    /// A marker for Units that represent the execution of a `build.rs` script.
    RunCustomBuild,
}

impl ser::Serialize for CompileMode {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        use self::CompileMode::*;
        match *self {
            Test => "test".serialize(s),
            Build => "build".serialize(s),
            Check { .. } => "check".serialize(s),
            Bench => "bench".serialize(s),
            Doc { .. } => "doc".serialize(s),
            Doctest => "doctest".serialize(s),
            Docscrape => "docscrape".serialize(s),
            RunCustomBuild => "run-custom-build".serialize(s),
        }
    }
}

impl CompileMode {
    /// Returns `true` if the unit is being checked.
    pub fn is_check(self) -> bool {
        matches!(self, CompileMode::Check { .. })
    }

    /// Returns `true` if this is generating documentation.
    pub fn is_doc(self) -> bool {
        matches!(self, CompileMode::Doc { .. })
    }

    /// Returns `true` if this a doc test.
    pub fn is_doc_test(self) -> bool {
        self == CompileMode::Doctest
    }

    /// Returns `true` if this is scraping examples for documentation.
    pub fn is_doc_scrape(self) -> bool {
        self == CompileMode::Docscrape
    }

    /// Returns `true` if this is any type of test (test, benchmark, doc test, or
    /// check test).
    pub fn is_any_test(self) -> bool {
        matches!(
            self,
            CompileMode::Test
                | CompileMode::Bench
                | CompileMode::Check { test: true }
                | CompileMode::Doctest
        )
    }

    /// Returns `true` if this is something that passes `--test` to rustc.
    pub fn is_rustc_test(self) -> bool {
        matches!(
            self,
            CompileMode::Test | CompileMode::Bench | CompileMode::Check { test: true }
        )
    }

    /// Returns `true` if this is the *execution* of a `build.rs` script.
    pub fn is_run_custom_build(self) -> bool {
        self == CompileMode::RunCustomBuild
    }

    /// Returns `true` if this mode may generate an executable.
    ///
    /// Note that this also returns `true` for building libraries, so you also
    /// have to check the target.
    pub fn generates_executable(self) -> bool {
        matches!(
            self,
            CompileMode::Test | CompileMode::Bench | CompileMode::Build
        )
    }
}

/// Kinds of build timings we can output.
#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
pub enum TimingOutput {
    /// Human-readable HTML report
    Html,
    /// Machine-readable JSON (unstable)
    Json,
}
<commit_msg>remove duplicate check<commit_after>use crate::core::compiler::CompileKind;
use crate::util::interning::InternedString;
use crate::util::{CargoResult, Config, RustfixDiagnosticServer};
use anyhow::bail;
use cargo_util::ProcessBuilder;
use serde::ser;
use std::cell::RefCell;
use std::path::PathBuf;

/// Configuration information for a rustc build.
#[derive(Debug)]
pub struct BuildConfig {
    /// The requested kind of compilation for this session
    pub requested_kinds: Vec<CompileKind>,
    /// Number of rustc jobs to run in parallel.
    pub jobs: u32,
    /// Do not abort the build as soon as there is an error.
    pub keep_going: bool,
    /// Build profile
    pub requested_profile: InternedString,
    /// The mode we are compiling in.
    pub mode: CompileMode,
    /// `true` to print stdout in JSON format (for machine reading).
    pub message_format: MessageFormat,
    /// Force Cargo to do a full rebuild and treat each target as changed.
    pub force_rebuild: bool,
    /// Output a build plan to stdout instead of actually compiling.
    pub build_plan: bool,
    /// Output the unit graph to stdout instead of actually compiling.
    pub unit_graph: bool,
    /// An optional override of the rustc process for primary units
    pub primary_unit_rustc: Option<ProcessBuilder>,
    /// A thread used by `cargo fix` to receive messages on a socket regarding
    /// the success/failure of applying fixes.
    pub rustfix_diagnostic_server: RefCell<Option<RustfixDiagnosticServer>>,
    /// The directory to copy final artifacts to. Note that even if `out_dir` is
    /// set, a copy of artifacts still could be found a `target/(debug\release)`
    /// as usual.
    // Note that, although the cmd-line flag name is `out-dir`, in code we use
    // `export_dir`, to avoid confusion with out dir at `target/debug/deps`.
    pub export_dir: Option<PathBuf>,
    /// `true` to output a future incompatibility report at the end of the build
    pub future_incompat_report: bool,
    /// Which kinds of build timings to output (empty if none).
    pub timing_outputs: Vec<TimingOutput>,
}

impl BuildConfig {
    /// Parses all config files to learn about build configuration. Currently
    /// configured options are:
    ///
    /// * `build.jobs`
    /// * `build.target`
    /// * `target.$target.ar`
    /// * `target.$target.linker`
    /// * `target.$target.libfoo.metadata`
    pub fn new(
        config: &Config,
        jobs: Option<i32>,
        keep_going: bool,
        requested_targets: &[String],
        mode: CompileMode,
    ) -> CargoResult<BuildConfig> {
        let cfg = config.build_config()?;
        let requested_kinds = CompileKind::from_requested_targets(config, requested_targets)?;
        if jobs.is_some() && config.jobserver_from_env().is_some() {
            config.shell().warn(
                "a `-j` argument was passed to Cargo but Cargo is \
                 also configured with an external jobserver in \
                 its environment, ignoring the `-j` parameter",
            )?;
        }
        let jobs = match jobs.or(cfg.jobs) {
            None => ::num_cpus::get() as u32,
            Some(0) => anyhow::bail!("jobs may not be 0"),
            Some(j) if j < 0 => (::num_cpus::get() as i32 + j).max(1) as u32,
            Some(j) => j as u32,
        };

        if config.cli_unstable().build_std.is_some() && requested_kinds[0].is_host() {
            // TODO: This should eventually be fixed.
            anyhow::bail!("-Zbuild-std requires --target");
        }

        Ok(BuildConfig {
            requested_kinds,
            jobs,
            keep_going,
            requested_profile: InternedString::new("dev"),
            mode,
            message_format: MessageFormat::Human,
            force_rebuild: false,
            build_plan: false,
            unit_graph: false,
            primary_unit_rustc: None,
            rustfix_diagnostic_server: RefCell::new(None),
            export_dir: None,
            future_incompat_report: false,
            timing_outputs: Vec::new(),
        })
    }

    /// Whether or not the *user* wants JSON output. Whether or not rustc
    /// actually uses JSON is decided in `add_error_format`.
    pub fn emit_json(&self) -> bool {
        matches!(self.message_format, MessageFormat::Json { .. })
    }

    pub fn test(&self) -> bool {
        self.mode == CompileMode::Test || self.mode == CompileMode::Bench
    }

    pub fn single_requested_kind(&self) -> CargoResult<CompileKind> {
        match self.requested_kinds.len() {
            1 => Ok(self.requested_kinds[0]),
            _ => bail!("only one `--target` argument is supported"),
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MessageFormat {
    Human,
    Json {
        /// Whether rustc diagnostics are rendered by cargo or included into the
        /// output stream.
        render_diagnostics: bool,
        /// Whether the `rendered` field of rustc diagnostics are using the
        /// "short" rendering.
        short: bool,
        /// Whether the `rendered` field of rustc diagnostics embed ansi color
        /// codes.
        ansi: bool,
    },
    Short,
}

/// The general "mode" for what to do.
/// This is used for two purposes. The commands themselves pass this in to
/// `compile_ws` to tell it the general execution strategy. This influences
/// the default targets selected. The other use is in the `Unit` struct
/// to indicate what is being done with a specific target.
#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
pub enum CompileMode {
    /// A target being built for a test.
    Test,
    /// Building a target with `rustc` (lib or bin).
    Build,
    /// Building a target with `rustc` to emit `rmeta` metadata only. If
    /// `test` is true, then it is also compiled with `--test` to check it like
    /// a test.
    Check { test: bool },
    /// Used to indicate benchmarks should be built. This is not used in
    /// `Unit`, because it is essentially the same as `Test` (indicating
    /// `--test` should be passed to rustc) and by using `Test` instead it
    /// allows some de-duping of Units to occur.
    Bench,
    /// A target that will be documented with `rustdoc`.
    /// If `deps` is true, then it will also document all dependencies.
    Doc { deps: bool },
    /// A target that will be tested with `rustdoc`.
    Doctest,
    /// An example or library that will be scraped for function calls by `rustdoc`.
    Docscrape,
    /// A marker for Units that represent the execution of a `build.rs` script.
    RunCustomBuild,
}

impl ser::Serialize for CompileMode {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        use self::CompileMode::*;
        match *self {
            Test => "test".serialize(s),
            Build => "build".serialize(s),
            Check { .. } => "check".serialize(s),
            Bench => "bench".serialize(s),
            Doc { .. } => "doc".serialize(s),
            Doctest => "doctest".serialize(s),
            Docscrape => "docscrape".serialize(s),
            RunCustomBuild => "run-custom-build".serialize(s),
        }
    }
}

impl CompileMode {
    /// Returns `true` if the unit is being checked.
    pub fn is_check(self) -> bool {
        matches!(self, CompileMode::Check { .. })
    }

    /// Returns `true` if this is generating documentation.
    pub fn is_doc(self) -> bool {
        matches!(self, CompileMode::Doc { .. })
    }

    /// Returns `true` if this a doc test.
    pub fn is_doc_test(self) -> bool {
        self == CompileMode::Doctest
    }

    /// Returns `true` if this is scraping examples for documentation.
    pub fn is_doc_scrape(self) -> bool {
        self == CompileMode::Docscrape
    }

    /// Returns `true` if this is any type of test (test, benchmark, doc test, or
    /// check test).
    pub fn is_any_test(self) -> bool {
        matches!(
            self,
            CompileMode::Test
                | CompileMode::Bench
                | CompileMode::Check { test: true }
                | CompileMode::Doctest
        )
    }

    /// Returns `true` if this is something that passes `--test` to rustc.
    pub fn is_rustc_test(self) -> bool {
        matches!(
            self,
            CompileMode::Test | CompileMode::Bench | CompileMode::Check { test: true }
        )
    }

    /// Returns `true` if this is the *execution* of a `build.rs` script.
    pub fn is_run_custom_build(self) -> bool {
        self == CompileMode::RunCustomBuild
    }

    /// Returns `true` if this mode may generate an executable.
    ///
    /// Note that this also returns `true` for building libraries, so you also
    /// have to check the target.
    pub fn generates_executable(self) -> bool {
        matches!(
            self,
            CompileMode::Test | CompileMode::Bench | CompileMode::Build
        )
    }
}

/// Kinds of build timings we can output.
#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
pub enum TimingOutput {
    /// Human-readable HTML report
    Html,
    /// Machine-readable JSON (unstable)
    Json,
}
<|endoftext|>


<commit_before>use std::cmp::min;

use widgets::{Widget, Block};
use buffer::Buffer;
use layout::Rect;
use style::Color;

pub struct Text<'a> {
    block: Option<Block<'a>>,
    fg: Color,
    bg: Color,
    text: &'a str,
    colors: &'a [(u16, u16, u16, Color, Color)],
}

impl<'a> Default for Text<'a> {
    fn default() -> Text<'a> {
        Text {
            block: None,
            fg: Color::Reset,
            bg: Color::Reset,
            text: "",
            colors: &[],
        }
    }
}

impl<'a> Text<'a> {
    pub fn block(&'a mut self, block: Block<'a>) -> &mut Text<'a> {
        self.block = Some(block);
        self
    }

    pub fn text(&mut self, text: &'a str) -> &mut Text<'a> {
        self.text = text;
        self
    }

    pub fn bg(&mut self, bg: Color) -> &mut Text<'a> {
        self.bg = bg;
        self
    }

    pub fn fg(&mut self, fg: Color) -> &mut Text<'a> {
        self.fg = fg;
        self
    }

    pub fn colors(&mut self, colors: &'a [(u16, u16, u16, Color, Color)]) -> &mut Text<'a> {
        self.colors = colors;
        self
    }
}

impl<'a> Widget<'a> for Text<'a> {
    fn buffer(&'a self, area: &Rect) -> Buffer<'a> {
        let (mut buf, text_area) = match self.block {
            Some(ref b) => (b.buffer(area), b.inner(*area)),
            None => (Buffer::empty(*area), *area),
        };
        let mut lines = self.text.lines().collect::<Vec<&str>>();
        let margin_x = text_area.x - area.x;
        let margin_y = text_area.y - area.y;
        let height = min(lines.len(), text_area.height as usize);
        for line in lines.iter_mut().take(height) {
            buf.set_string(margin_x, margin_y, line, self.fg, self.bg);
        }
        for &(x, y, width, fg, bg) in self.colors {
            for i in 0..width {
                buf.set_fg(x + i, y + margin_y, fg);
                buf.set_bg(x + i, y + margin_y, fg);
            }
        }
        buf
    }
}
<commit_msg>Update text widget (templating and wrapping)<commit_after>use unicode_segmentation::UnicodeSegmentation;

use widgets::{Widget, Block};
use buffer::Buffer;
use layout::Rect;
use style::Color;

pub struct Text<'a> {
    block: Option<Block<'a>>,
    fg: Color,
    bg: Color,
    wrapping: bool,
    text: &'a str,
    colors: &'a [(u16, u16, u16, Color, Color)],
}

impl<'a> Default for Text<'a> {
    fn default() -> Text<'a> {
        Text {
            block: None,
            fg: Color::Reset,
            bg: Color::Reset,
            wrapping: false,
            text: "",
            colors: &[],
        }
    }
}

impl<'a> Text<'a> {
    pub fn block(&'a mut self, block: Block<'a>) -> &mut Text<'a> {
        self.block = Some(block);
        self
    }

    pub fn text(&mut self, text: &'a str) -> &mut Text<'a> {
        self.text = text;
        self
    }

    pub fn bg(&mut self, bg: Color) -> &mut Text<'a> {
        self.bg = bg;
        self
    }

    pub fn fg(&mut self, fg: Color) -> &mut Text<'a> {
        self.fg = fg;
        self
    }

    pub fn colors(&mut self, colors: &'a [(u16, u16, u16, Color, Color)]) -> &mut Text<'a> {
        self.colors = colors;
        self
    }

    pub fn wrap(&mut self, flag: bool) -> &mut Text<'a> {
        self.wrapping = flag;
        self
    }
}

struct Parser<'a> {
    text: Vec<&'a str>,
    mark: bool,
    color_string: String,
    color: Color,
    escaping: bool,
    coloring: bool,
}

impl<'a> Parser<'a> {
    fn new(text: &'a str) -> Parser<'a> {
        Parser {
            text: UnicodeSegmentation::graphemes(text, true).rev().collect::<Vec<&str>>(),
            mark: false,
            color_string: String::from(""),
            color: Color::Reset,
            escaping: false,
            coloring: false,
        }
    }

    fn update_color(&mut self) {
        self.color = match &*self.color_string {
            "black" => Color::Black,
            "red" => Color::Red,
            "green" => Color::Green,
            "yellow" => Color::Yellow,
            "magenta" => Color::Magenta,
            "cyan" => Color::Cyan,
            "gray" => Color::Gray,
            "dark_gray" => Color::DarkGray,
            "light_red" => Color::LightRed,
            "light_green" => Color::LightGreen,
            "light_yellow" => Color::LightYellow,
            "light_magenta" => Color::LightMagenta,
            "light_cyan" => Color::LightCyan,
            "white" => Color::White,
            _ => Color::Reset,
        }
    }

    fn reset(&mut self) {
        self.coloring = false;
        self.mark = false;
        self.color = Color::Reset;
        self.color_string = String::from("");
    }
}

impl<'a> Iterator for Parser<'a> {
    type Item = (&'a str, Color);
    fn next(&mut self) -> Option<(&'a str, Color)> {
        match self.text.pop() {
            Some(s) => {
                if s == "\\" {
                    if self.escaping {
                        Some((s, self.color))
                    } else {
                        self.escaping = true;
                        self.next()
                    }
                } else if s == "{" {
                    if self.escaping {
                        self.escaping = false;
                        Some((s, self.color))
                    } else {
                        self.color = Color::Reset;
                        self.mark = true;
                        self.next()
                    }
                } else if s == "}" && self.mark {
                    self.reset();
                    self.next()
                } else if s == " " && self.mark {
                    self.coloring = true;
                    self.update_color();
                    self.next()
                } else if self.mark && !self.coloring {
                    self.color_string.push_str(s);
                    self.next()
                } else {
                    Some((s, self.color))
                }
            }
            None => None,
        }
    }
}

impl<'a> Widget<'a> for Text<'a> {
    fn buffer(&'a self, area: &Rect) -> Buffer<'a> {
        let (mut buf, text_area) = match self.block {
            Some(ref b) => (b.buffer(area), b.inner(*area)),
            None => (Buffer::empty(*area), *area),
        };

        if text_area.height < 1 {
            return buf;
        }

        let margin_x = text_area.x - area.x;
        let margin_y = text_area.y - area.y;
        let mut x = 0;
        let mut y = 0;
        for (s, c) in Parser::new(self.text) {
            if s == "\n" {
                x = 0;
                y += 1;
                continue;
            }
            if x >= text_area.width {
                if self.wrapping {
                    x = 0;
                    y += 1;
                }
                continue;
            }

            if y > text_area.height - 1 {
                break;
            }

            buf.update_cell(margin_x + x, margin_y + y, s, c, self.bg);
            x += 1;
        }

        for &(x, y, width, fg, bg) in self.colors {
            for i in 0..width {
                buf.set_fg(x + i, y + margin_y, fg);
                buf.set_bg(x + i, y + margin_y, bg);
            }
        }
        buf
    }
}
<|endoftext|>


<commit_before>extern mod std;

use libc::c_char;
use libc::c_int;
use libc::size_t;
use libc::c_ulong;
use libc::c_void;
use ptr::null;
use ptr::addr_of;
use ptr::mut_addr_of;
use str::as_c_str;

struct mpz_struct {
  _mp_alloc: c_int,
  _mp_size: c_int,
  _mp_d: *c_void
}

type mpz_srcptr = *const mpz_struct;
type mpz_ptr = *mut mpz_struct;

extern mod gmp {
  fn __gmpz_init(x: mpz_ptr);
  fn __gmpz_init_set_str(rop: mpz_ptr, str: *c_char, base: c_int) -> c_int;
  fn __gmpz_clear(x: mpz_ptr);
  fn __gmpz_set_str(rop: mpz_ptr, str: *c_char, base: c_int) -> c_int;
  fn __gmpz_get_str(str: *c_char, base: c_int, op: mpz_srcptr) -> *c_char;
  pure fn __gmpz_sizeinbase(op: mpz_srcptr, base: c_int) -> size_t;
  pure fn __gmpz_cmp(op: mpz_srcptr, op2: mpz_srcptr) -> c_int;
  pure fn __gmpz_cmp_ui(op1: mpz_srcptr, op2: c_ulong) -> c_int;
  fn __gmpz_add(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
  fn __gmpz_sub(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
  fn __gmpz_mul(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
  fn __gmpz_neg(rop: mpz_ptr, op: mpz_srcptr);
  fn __gmpz_tdiv_q(r: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
  fn __gmpz_mod(r: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
}

use gmp::*;

pub struct Mpz {
  priv mpz: mpz_struct,

  drop {
    __gmpz_clear(mut_addr_of(&self.mpz));
  }
}

impl Mpz {
  fn set_str(&self, s: &str, base: int) -> bool {
    let mpz = mut_addr_of(&self.mpz);
    let r = as_c_str(s, { |s| __gmpz_set_str(mpz, s, base as c_int) });
    r == 0
  }

  pure fn size_in_base(&self, base: int) -> uint {
    __gmpz_sizeinbase(addr_of(&self.mpz), base as c_int) as uint
  }
}

impl Mpz: cmp::Eq {
  pure fn eq(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) == 0
  }
  pure fn ne(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) != 0
  }
}

impl Mpz: cmp::Ord {
  pure fn lt(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) < 0
  }
  pure fn le(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) <= 0
  }
  pure fn gt(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) > 0
  }
  pure fn ge(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) >= 0
  }
}

impl Mpz: num::Num {
  pure fn add(other: &Mpz) -> Mpz unsafe {
    let res = init();
    __gmpz_add(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn sub(other: &Mpz) -> Mpz unsafe {
    let res = init();
    __gmpz_sub(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn mul(other: &Mpz) -> Mpz unsafe {
    let res = init();
    __gmpz_mul(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn div(other: &Mpz) -> Mpz unsafe {
    if __gmpz_cmp_ui(addr_of(&self.mpz), 0) == 0 {
      fail ~"divide by zero";
    }

    let res = init();
    __gmpz_tdiv_q(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn modulo(other: &Mpz) -> Mpz unsafe {
    if __gmpz_cmp_ui(addr_of(&self.mpz), 0) == 0 {
      fail ~"divide by zero";
    }

    let res = init();
    __gmpz_mod(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn neg() -> Mpz unsafe {
    let res = init();
    __gmpz_neg(mut_addr_of(&res.mpz), addr_of(&self.mpz));
    res
  }
  pure fn to_int() -> int {
    fail ~"not implemented";
  }
  static pure fn from_int(other: int) -> Mpz unsafe {
    let res = init();
    // the gmp functions dealing with longs aren't usable here - long is only
    // guaranteed to be at least 32-bit
    assert(res.set_str(other.to_str(), 10));
    res
  }
}

impl Mpz : from_str::FromStr {
  static fn from_str(s: &str) -> Option<Mpz> {
    let mpz = mpz_struct { _mp_alloc: 0, _mp_size: 0, _mp_d: null() };
    if as_c_str(s, { |s| __gmpz_init_set_str(mut_addr_of(&mpz), s, 10) }) == 0 {
      Some(Mpz { mpz: mpz })
    } else {
      __gmpz_clear(mut_addr_of(&mpz));
      None
    }
  }
}

impl Mpz : to_str::ToStr {
  pure fn to_str() -> ~str unsafe {
    let length = self.size_in_base(10) + 2;
    let dst = vec::to_mut(vec::from_elem(length, '0'));
    let pdst = vec::raw::to_ptr(dst);

    str::raw::from_c_str(__gmpz_get_str(pdst as *c_char, 10, addr_of(&self.mpz)))
  }
}

pub fn init() -> Mpz {
  let mpz = mpz_struct { _mp_alloc: 0, _mp_size: 0, _mp_d: null() };
  __gmpz_init(mut_addr_of(&mpz));
  Mpz { mpz: mpz }
}

#[cfg(test)]
mod tests {
  #[test]
  fn size_in_base() {
    let x = init();
    x.set_str("150000", 10);
    assert(x.size_in_base(10) == 6);
  }

  #[test]
  fn eq() {
    let x = init();
    x.set_str("4242142195", 10);
    let y = init();
    y.set_str("4242142195", 10);
    let z = init();
    z.set_str("4242142196", 10);

    assert(x == y);
    assert(x != z);
    assert(y != z);
  }

  #[test]
  fn ord() {
    let x = init();
    x.set_str("40000000000000000000000", 10);
    let y = init();
    y.set_str("45000000000000000000000", 10);
    let z = init();
    z.set_str("50000000000000000000000", 10);

    assert(x < y && x < z && y < z);
    assert(x <= x && x <= y && x <= z && y <= z);
    assert(z > y && z > x && y > x);
    assert(z >= z && z >= y && z >= x && y >= x);
  }

  #[test]
  #[should_fail]
  fn div_zero() {
    let x = init();
    x / x;
  }

  #[test]
  #[should_fail]
  fn modulo_zero() {
    let x = init();
    x % x;
  }

  #[test]
  fn test_div_round() {
    let x = init();
    let y = init();
    let mut z: Mpz;

    x.set_str("2", 10);
    y.set_str("3", 10);
    z = x / y;
    assert(__gmpz_cmp_ui(addr_of(&z.mpz), 2 / 3) == 0);

    x.set_str("2", 10);
    y.set_str("-3", 10);
    z = x / y;
    assert(__gmpz_cmp_ui(addr_of(&z.mpz), 2 / -3) == 0);
  }

  #[test]
  fn to_str() {
    let x = init();
    x.set_str("1234567890", 10);
    assert(x.to_str() == ~"1234567890");
  }
}
<commit_msg>add init_set_str(s, base) and use it in from_str<commit_after>extern mod std;

use libc::c_char;
use libc::c_int;
use libc::size_t;
use libc::c_ulong;
use libc::c_void;
use ptr::null;
use ptr::addr_of;
use ptr::mut_addr_of;
use str::as_c_str;

struct mpz_struct {
  _mp_alloc: c_int,
  _mp_size: c_int,
  _mp_d: *c_void
}

type mpz_srcptr = *const mpz_struct;
type mpz_ptr = *mut mpz_struct;

extern mod gmp {
  fn __gmpz_init(x: mpz_ptr);
  fn __gmpz_init_set_str(rop: mpz_ptr, str: *c_char, base: c_int) -> c_int;
  fn __gmpz_clear(x: mpz_ptr);
  fn __gmpz_set_str(rop: mpz_ptr, str: *c_char, base: c_int) -> c_int;
  fn __gmpz_get_str(str: *c_char, base: c_int, op: mpz_srcptr) -> *c_char;
  pure fn __gmpz_sizeinbase(op: mpz_srcptr, base: c_int) -> size_t;
  pure fn __gmpz_cmp(op: mpz_srcptr, op2: mpz_srcptr) -> c_int;
  pure fn __gmpz_cmp_ui(op1: mpz_srcptr, op2: c_ulong) -> c_int;
  fn __gmpz_add(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
  fn __gmpz_sub(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
  fn __gmpz_mul(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
  fn __gmpz_neg(rop: mpz_ptr, op: mpz_srcptr);
  fn __gmpz_tdiv_q(r: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
  fn __gmpz_mod(r: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
}

use gmp::*;

pub struct Mpz {
  priv mpz: mpz_struct,

  drop {
    __gmpz_clear(mut_addr_of(&self.mpz));
  }
}

impl Mpz {
  fn set_str(&self, s: &str, base: int) -> bool {
    let mpz = mut_addr_of(&self.mpz);
    let r = as_c_str(s, { |s| __gmpz_set_str(mpz, s, base as c_int) });
    r == 0
  }

  pure fn size_in_base(&self, base: int) -> uint {
    __gmpz_sizeinbase(addr_of(&self.mpz), base as c_int) as uint
  }
}

impl Mpz: cmp::Eq {
  pure fn eq(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) == 0
  }
  pure fn ne(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) != 0
  }
}

impl Mpz: cmp::Ord {
  pure fn lt(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) < 0
  }
  pure fn le(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) <= 0
  }
  pure fn gt(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) > 0
  }
  pure fn ge(other: &Mpz) -> bool {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) >= 0
  }
}

impl Mpz: num::Num {
  pure fn add(other: &Mpz) -> Mpz unsafe {
    let res = init();
    __gmpz_add(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn sub(other: &Mpz) -> Mpz unsafe {
    let res = init();
    __gmpz_sub(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn mul(other: &Mpz) -> Mpz unsafe {
    let res = init();
    __gmpz_mul(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn div(other: &Mpz) -> Mpz unsafe {
    if __gmpz_cmp_ui(addr_of(&self.mpz), 0) == 0 {
      fail ~"divide by zero";
    }

    let res = init();
    __gmpz_tdiv_q(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn modulo(other: &Mpz) -> Mpz unsafe {
    if __gmpz_cmp_ui(addr_of(&self.mpz), 0) == 0 {
      fail ~"divide by zero";
    }

    let res = init();
    __gmpz_mod(mut_addr_of(&res.mpz), addr_of(&self.mpz), addr_of(&other.mpz));
    res
  }
  pure fn neg() -> Mpz unsafe {
    let res = init();
    __gmpz_neg(mut_addr_of(&res.mpz), addr_of(&self.mpz));
    res
  }
  pure fn to_int() -> int {
    fail ~"not implemented";
  }
  static pure fn from_int(other: int) -> Mpz unsafe {
    let res = init();
    // the gmp functions dealing with longs aren't usable here - long is only
    // guaranteed to be at least 32-bit
    assert(res.set_str(other.to_str(), 10));
    res
  }
}

impl Mpz : from_str::FromStr {
  static fn from_str(s: &str) -> Option<Mpz> {
    init_set_str(s, 10)
  }
}

impl Mpz : to_str::ToStr {
  pure fn to_str() -> ~str unsafe {
    let length = self.size_in_base(10) + 2;
    let dst = vec::to_mut(vec::from_elem(length, '0'));
    let pdst = vec::raw::to_ptr(dst);

    str::raw::from_c_str(__gmpz_get_str(pdst as *c_char, 10, addr_of(&self.mpz)))
  }
}

pub fn init() -> Mpz {
  let mpz = mpz_struct { _mp_alloc: 0, _mp_size: 0, _mp_d: null() };
  __gmpz_init(mut_addr_of(&mpz));
  Mpz { mpz: mpz }
}

pub fn init_set_str(s: &str, base: int) -> Option<Mpz> {
  let mpz = mpz_struct { _mp_alloc: 0, _mp_size: 0, _mp_d: null() };
  let mpz_ptr = mut_addr_of(&mpz);
  let r = as_c_str(s, { |s| __gmpz_init_set_str(mpz_ptr, s, base as c_int) });
  if r == 0 {
    Some(Mpz { mpz: mpz })
  } else {
    __gmpz_clear(mpz_ptr);
    None
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn size_in_base() {
    let x = init();
    x.set_str("150000", 10);
    assert(x.size_in_base(10) == 6);
  }

  #[test]
  fn eq() {
    let x = init();
    x.set_str("4242142195", 10);
    let y = init();
    y.set_str("4242142195", 10);
    let z = init();
    z.set_str("4242142196", 10);

    assert(x == y);
    assert(x != z);
    assert(y != z);
  }

  #[test]
  fn ord() {
    let x = init();
    x.set_str("40000000000000000000000", 10);
    let y = init();
    y.set_str("45000000000000000000000", 10);
    let z = init();
    z.set_str("50000000000000000000000", 10);

    assert(x < y && x < z && y < z);
    assert(x <= x && x <= y && x <= z && y <= z);
    assert(z > y && z > x && y > x);
    assert(z >= z && z >= y && z >= x && y >= x);
  }

  #[test]
  #[should_fail]
  fn div_zero() {
    let x = init();
    x / x;
  }

  #[test]
  #[should_fail]
  fn modulo_zero() {
    let x = init();
    x % x;
  }

  #[test]
  fn test_div_round() {
    let x = init();
    let y = init();
    let mut z: Mpz;

    x.set_str("2", 10);
    y.set_str("3", 10);
    z = x / y;
    assert(__gmpz_cmp_ui(addr_of(&z.mpz), 2 / 3) == 0);

    x.set_str("2", 10);
    y.set_str("-3", 10);
    z = x / y;
    assert(__gmpz_cmp_ui(addr_of(&z.mpz), 2 / -3) == 0);
  }

  #[test]
  fn to_str() {
    let x = init();
    x.set_str("1234567890", 10);
    assert(x.to_str() == ~"1234567890");
  }

  #[test]
  fn invalid_str() {
    assert(init_set_str("foobar", 10).is_none());
  }
}
<|endoftext|>


<commit_before>extern mod std;

use libc::c_char;
use libc::c_int;
use libc::size_t;
use libc::c_void;
use ptr::null;
use str::as_c_str;
use ptr::addr_of;

struct mpz_struct {
  _mp_alloc: c_int,
  _mp_size: c_int,
  _mp_d: *c_void
}

type mpz_t = *mpz_struct;

extern mod gmp {
  fn __gmpz_init(x: mpz_t);
  fn __gmpz_clear(x: mpz_t);
  fn __gmpz_set_str(rop: mpz_t, str: *c_char, base: c_int) -> c_int;
  fn __gmpz_get_str(str: *c_char, base: c_int, op: mpz_t) -> *c_char;
  fn __gmpz_sizeinbase(op: mpz_t, base: c_int) -> size_t;
  fn __gmpz_cmp(op: mpz_t, op2: mpz_t) -> c_int;
}

use gmp::*;

pub struct Mpz {
  priv mpz: mpz_struct,

  drop {
    __gmpz_clear(addr_of(&self.mpz));
  }
}

impl Mpz {
  fn set_str(&self, s: &str, base: int) -> bool {
    let mpz = addr_of(&self.mpz);
    let r = as_c_str(s, { |s| __gmpz_set_str(mpz, s, base as c_int) });
    r == 0
  }

  fn size_in_base(&self, base: int) -> uint {
    __gmpz_sizeinbase(addr_of(&self.mpz), base as c_int) as uint
  }
}

impl Mpz: cmp::Eq {
  pure fn eq(other: &Mpz) -> bool unsafe {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) == 0
  }
  pure fn ne(other: &Mpz) -> bool unsafe {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) != 0
  }
}

fn init() -> Mpz {
  let mpz = mpz_struct { _mp_alloc: 0, _mp_size: 0, _mp_d: null() };
  __gmpz_init(addr_of(&mpz));
  Mpz { mpz: mpz }
}

#[cfg(test)]
mod tests {
  #[test]
  fn size_in_base() {
    let x = init();
    x.set_str("150000", 10);
    assert(x.size_in_base(10) == 6);
  }
  #[test]
  fn eq() {
    let x = init();
    x.set_str("4242142195", 10);
    let y = init();
    y.set_str("4242142195", 10);
    let z = init();
    z.set_str("4242142196", 10);

    assert(x == y);
    assert(x != z);
    assert(y != z);
  }
}
<commit_msg>implement Ord trait<commit_after>extern mod std;

use libc::c_char;
use libc::c_int;
use libc::size_t;
use libc::c_void;
use ptr::null;
use str::as_c_str;
use ptr::addr_of;

struct mpz_struct {
  _mp_alloc: c_int,
  _mp_size: c_int,
  _mp_d: *c_void
}

type mpz_t = *mpz_struct;

extern mod gmp {
  fn __gmpz_init(x: mpz_t);
  fn __gmpz_clear(x: mpz_t);
  fn __gmpz_set_str(rop: mpz_t, str: *c_char, base: c_int) -> c_int;
  fn __gmpz_get_str(str: *c_char, base: c_int, op: mpz_t) -> *c_char;
  fn __gmpz_sizeinbase(op: mpz_t, base: c_int) -> size_t;
  fn __gmpz_cmp(op: mpz_t, op2: mpz_t) -> c_int;
}

use gmp::*;

pub struct Mpz {
  priv mpz: mpz_struct,

  drop {
    __gmpz_clear(addr_of(&self.mpz));
  }
}

impl Mpz {
  fn set_str(&self, s: &str, base: int) -> bool {
    let mpz = addr_of(&self.mpz);
    let r = as_c_str(s, { |s| __gmpz_set_str(mpz, s, base as c_int) });
    r == 0
  }

  fn size_in_base(&self, base: int) -> uint {
    __gmpz_sizeinbase(addr_of(&self.mpz), base as c_int) as uint
  }
}

impl Mpz: cmp::Eq {
  pure fn eq(other: &Mpz) -> bool unsafe {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) == 0
  }
  pure fn ne(other: &Mpz) -> bool unsafe {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) != 0
  }
}

impl Mpz: cmp::Ord {
  pure fn lt(other: &Mpz) -> bool unsafe {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) < 0
  }
  pure fn le(other: &Mpz) -> bool unsafe {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) <= 0
  }
  pure fn gt(other: &Mpz) -> bool unsafe {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) > 0
  }
  pure fn ge(other: &Mpz) -> bool unsafe {
    __gmpz_cmp(addr_of(&self.mpz), addr_of(&other.mpz)) >= 0
  }
}

fn init() -> Mpz {
  let mpz = mpz_struct { _mp_alloc: 0, _mp_size: 0, _mp_d: null() };
  __gmpz_init(addr_of(&mpz));
  Mpz { mpz: mpz }
}

#[cfg(test)]
mod tests {
  #[test]
  fn size_in_base() {
    let x = init();
    x.set_str("150000", 10);
    assert(x.size_in_base(10) == 6);
  }
  #[test]
  fn eq() {
    let x = init();
    x.set_str("4242142195", 10);
    let y = init();
    y.set_str("4242142195", 10);
    let z = init();
    z.set_str("4242142196", 10);

    assert(x == y);
    assert(x != z);
    assert(y != z);
  }
  #[test]
  fn ord() {
    let x = init();
    x.set_str("40000000000000000000000", 10);
    let y = init();
    y.set_str("45000000000000000000000", 10);
    let z = init();
    z.set_str("50000000000000000000000", 10);

    assert(x < y && x < z && y < z);
    assert(x <= x && x <= y && x <= z && y <= z);
    assert(z > y && z > x && y > x);
    assert(z >= z && z >= y && z >= x && y >= x);
  }
}
<|endoftext|>


<commit_before>#![no_main]

use libfuzzer_sys::{
    arbitrary::{self, Arbitrary},
    fuzz_target,
};
use ropey::Rope;

const SMALL_TEXT: &str = include_str!("small.txt");
const MEDIUM_TEXT: &str = include_str!("medium.txt");

#[derive(Arbitrary, Copy, Clone, Debug)]
enum Op<'a> {
    Insert(usize, &'a str),
    InsertChar(usize, char),
    Remove(usize, usize),
    SplitOff(usize, bool),
    Append(&'a str),
}

#[derive(Arbitrary, Copy, Clone, Debug)]
enum StartingText<'a> {
    Small,
    Medium,
    Custom(&'a str),
}

fuzz_target!(|data: (StartingText, Vec<Op>)| {
    let mut r = Rope::from_str(match data.0 {
        StartingText::Small => SMALL_TEXT,
        StartingText::Medium => MEDIUM_TEXT,
        StartingText::Custom(s) => s,
    });

    for op in data.1 {
        match op {
            Op::Insert(idx, s) => {
                let _ = r.try_insert(idx, s);
            }
            Op::InsertChar(idx, c) => {
                let _ = r.try_insert_char(idx, c);
            }
            Op::Remove(idx_1, idx_2) => {
                let _ = r.try_remove(idx_1..idx_2);
            }
            Op::SplitOff(idx, keep_right) => match r.try_split_off(idx) {
                Ok(right) => {
                    if keep_right {
                        r = right;
                    }
                }
                Err(_) => {}
            },
            Op::Append(s) => {
                r.append(Rope::from_str(s));
            }
        }
    }
});
<commit_msg>Add tree validity checks to the fuzzing target.<commit_after>#![no_main]

use libfuzzer_sys::{
    arbitrary::{self, Arbitrary},
    fuzz_target,
};
use ropey::Rope;

const SMALL_TEXT: &str = include_str!("small.txt");
const MEDIUM_TEXT: &str = include_str!("medium.txt");

#[derive(Arbitrary, Copy, Clone, Debug)]
enum Op<'a> {
    Insert(usize, &'a str),
    InsertChar(usize, char),
    Remove(usize, usize),
    SplitOff(usize, bool),
    Append(&'a str),
}

#[derive(Arbitrary, Copy, Clone, Debug)]
enum StartingText<'a> {
    Small,
    Medium,
    Custom(&'a str),
}

fuzz_target!(|data: (StartingText, Vec<Op>)| {
    let mut r = Rope::from_str(match data.0 {
        StartingText::Small => SMALL_TEXT,
        StartingText::Medium => MEDIUM_TEXT,
        StartingText::Custom(s) => s,
    });

    for op in data.1 {
        match op {
            Op::Insert(idx, s) => {
                let _ = r.try_insert(idx, s);
            }
            Op::InsertChar(idx, c) => {
                let _ = r.try_insert_char(idx, c);
            }
            Op::Remove(idx_1, idx_2) => {
                let _ = r.try_remove(idx_1..idx_2);
            }
            Op::SplitOff(idx, keep_right) => match r.try_split_off(idx) {
                Ok(right) => {
                    if keep_right {
                        r = right;
                    }
                }
                Err(_) => {}
            },
            Op::Append(s) => {
                r.append(Rope::from_str(s));
            }
        }
    }

    r.assert_integrity();
    r.assert_invariants();
});
<|endoftext|>