<commit_before>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                if let Ok(message) = decode(encoded_msg) {
                    let message: PeerMessage = message;

                    debug!(target: LIB_NAME, "I am using {:?}.", self.ws.token());

                    if let Some(demo_client) = self.demo_client.clone() {
                        if message.sender.as_str() == demo_client.as_str() {
                            info!(target: LIB_NAME, "Faking delay for messages from {}!", demo_client);
                            self.message_queue.push_back(message);
                            return self.ws.timeout(4000, DELAYED_MESSAGE);
                        }
                    }

                    self.message_handler(message);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Failed to serialize the binary message."))
                }
            }
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to client list", string);
                if let Ok(mut clocks) = self.clocks.lock() {
                    clocks.insert(string, 0u32);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Failed to serialize the string message."))
                }
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                if let Some(msg) = self.message_queue.pop_front() {
                    self.message_handler(msg);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Invalid timeout token encountered!"))
                }
            }
            _ => Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        // TODO: Remove disconnected client's clock from our vclock copy.
        info!(target: LIB_NAME, "Received an on_close call");
        if reason.is_empty() {
            // This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} d/c with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                if vclocks.get(&key.clone()).is_some() {
                    let lval = vclocks.get(&key.clone()).unwrap().clone();
                    let max_val = cmp::max(val, &lval);
                    vclocks.insert(key.clone(), *max_val);
                }
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        // Finishes the lifetime of the mutex holds so buffer_check can use it without blocking
        {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
            info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            for (key, val) in message.clocks.iter() {
                vclocks.insert(key.clone(), *val);
            }
        }
        self.buffer_check();
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}", e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}", e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}
<commit_msg>Cargo fmt<commit_after>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                if let Ok(message) = decode(encoded_msg) {
                    let message: PeerMessage = message;

                    debug!(target: LIB_NAME, "I am using {:?}.", self.ws.token());

                    if let Some(demo_client) = self.demo_client.clone() {
                        if message.sender.as_str() == demo_client.as_str() {
                            info!(target: LIB_NAME,
                                  "Faking delay for messages from {}!", demo_client);
                            self.message_queue.push_back(message);
                            return self.ws.timeout(4000, DELAYED_MESSAGE);
                        }
                    }

                    self.message_handler(message);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Failed to serialize the binary message."))
                }
            }
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to client list", string);
                if let Ok(mut clocks) = self.clocks.lock() {
                    clocks.insert(string, 0u32);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Failed to serialize the string message."))
                }
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                if let Some(msg) = self.message_queue.pop_front() {
                    self.message_handler(msg);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Invalid timeout token encountered!"))
                }
            }
            _ => Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        // TODO: Remove disconnected client's clock from our vclock copy.
        info!(target: LIB_NAME, "Received an on_close call");
        if reason.is_empty() {
            // This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} d/c with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                if vclocks.get(&key.clone()).is_some() {
                    let lval = vclocks.get(&key.clone()).unwrap().clone();
                    let max_val = cmp::max(val, &lval);
                    vclocks.insert(key.clone(), *max_val);
                }
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        // Finishes the lifetime of the mutex holds so buffer_check can use it without
        // blocking
        {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
            info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            for (key, val) in message.clocks.iter() {
                vclocks.insert(key.clone(), *val);
            }
        }
        self.buffer_check();
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}",
                   e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}",
                   e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}
<|endoftext|>


<commit_before>//! This is a basic example of leveraging `UdpCodec` to create a simple UDP
//! client and server which speak a custom protocol.
//!
//! Here we're using the a custom codec to convert a UDP socket to a stream of
//! client messages. These messages are then processed and returned back as a
//! new message with a new destination. Overall, we then use this to construct a
//! "ping pong" pair where two sockets are sending messages back and forth.

extern crate tokio_core;
extern crate env_logger;
extern crate futures;

use std::io;
use std::net::SocketAddr;
use std::str;
use std::thread;

use futures::{Future, Stream, Sink};
use tokio_core::net::{UdpSocket, UdpCodec};
use tokio_core::reactor::Core;

pub struct PacketCodec;

pub struct UdpManager {
        //reader: Stream,
        //writer: Sink,
}

impl UdpCodec for PacketCodec {
    type In = (SocketAddr, Vec<u8>);
    type Out = (SocketAddr, Vec<u8>);

    fn decode(&mut self, addr: &SocketAddr, buf: &[u8]) -> io::Result<Self::In> {
        Ok((*addr, buf.to_vec()))
    }

    fn encode(&mut self, (addr, buf): Self::Out, into: &mut Vec<u8>) -> SocketAddr {
        into.extend(buf);
        addr
    }
}

fn udp_listen() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let addr: SocketAddr = "0.0.0.0:12345".parse().unwrap();

    // Bind both our sockets and then figure out what ports we got.
    let socket = UdpSocket::bind(&addr, &handle).unwrap();

    // We're parsing each socket with the `PacketCodec` defined above, and then we
    // `split` each codec into the sink/stream halves.
    let (writer, reader) = socket.framed(PacketCodec).split();

    // Listen for new messages and then send back a modified responses
    let reader = reader.and_then(|(socket, data)| {
        let stringy = String::from_utf8(data);
        println!("socket: {:?}, data: {:?}", socket, stringy);

        Ok(())
    });

    let writer = writer.send((addr, "I am a packet sent from within.".to_string().into_bytes())).then(|_| {
        println!("Sent message");
        Ok(())
    });

    let reader = reader.for_each(|_| {
        Ok(())
    });

    handle.spawn( writer);

    core.run(reader).unwrap();
}

fn main() {
    drop(env_logger::init());

    thread::spawn(|| udp_listen());

    loop {
        thread::sleep(std::time::Duration::from_secs(1));
    }
}
<commit_msg>Trying to incorporate channels<commit_after>//! This is a basic example of leveraging `UdpCodec` to create a simple UDP
//! client and server which speak a custom protocol.
//!
//! Here we're using the a custom codec to convert a UDP socket to a stream of
//! client messages. These messages are then processed and returned back as a
//! new message with a new destination. Overall, we then use this to construct a
//! "ping pong" pair where two sockets are sending messages back and forth.

extern crate tokio_core;
extern crate env_logger;
extern crate futures;

use std::io;
use std::net::SocketAddr;
use std::str;
use std::thread;

use futures::{Future, Stream, Sink};
use futures::sync::mpsc;

use tokio_core::net::{UdpSocket, UdpCodec};
use tokio_core::reactor::Core;

pub struct PacketCodec;

pub struct UdpManager {
        //reader: Stream,
        //writer: Sink,
}

impl UdpCodec for PacketCodec {
    type In = (SocketAddr, Vec<u8>);
    type Out = (SocketAddr, Vec<u8>);

    fn decode(&mut self, addr: &SocketAddr, buf: &[u8]) -> io::Result<Self::In> {
        Ok((*addr, buf.to_vec()))
    }

    fn encode(&mut self, (addr, buf): Self::Out, into: &mut Vec<u8>) -> SocketAddr {
        into.extend(buf);
        addr
    }
}

fn udp_listen(tx_1: mpsc::Sender<String>) {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let addr: SocketAddr = "0.0.0.0:12345".parse().unwrap();

    // Bind both our sockets and then figure out what ports we got.
    let socket = UdpSocket::bind(&addr, &handle).unwrap();

    // We're parsing each socket with the `PacketCodec` defined above, and then we
    // `split` each codec into the sink/stream halves.
    let (writer, reader) = socket.framed(PacketCodec).split();

    // Listen for new messages and then send back a modified responses
    let reader = reader.and_then(|(socket, data)| {
        let stringy = String::from_utf8(data);

        let message : String = format!("socket: {:?}, data: {:?}", socket, stringy);

        println!("Sending...");
        tx_1.send(message);
        Ok(())
    });

    let writer = writer.send((addr, "I am a packet sent from within.".to_string().into_bytes())).then(|_| {
        println!("Sent message");
        Ok(())
    });

    let reader = reader.for_each(|_| {
        Ok(())
    });

    handle.spawn( writer);

    core.run(reader).unwrap();
}

fn main() {
    drop(env_logger::init());

    let (tx_1, rx_1) = mpsc::channel::<String>(10); // backpressure of 10

    thread::spawn(|| udp_listen(tx_1));

    loop {
        rx_1.then(|msg| {
            println!("Received message:... {}", msg.unwrap());
            Ok(())
        });
        thread::sleep(std::time::Duration::from_secs(1));
    }
}
<|endoftext|>


<commit_before><commit_msg>ParseError: Remove the description field; only leave the display field<commit_after><|endoftext|>


<commit_before>use std::ops::Shl;
use traits::{One, Zero};

use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit};
use biguint::BigUint;

struct MontyReducer {
    n0inv: BigDigit,
}

// k0 = -m**-1 mod 2**BITS. Algorithm from: Dumas, J.G. "On Newton–Raphson
// Iteration for Multiplicative Inverses Modulo Prime Powers".
fn inv_mod_alt(b: BigDigit) -> BigDigit {
    assert_ne!(b & 1, 0);

    let mut k0 = 2 - b as SignedDoubleBigDigit;
    let mut t = (b - 1) as SignedDoubleBigDigit;
    let mut i = 1;
    while i < big_digit::BITS {
        t = t.wrapping_mul(t);
        k0 = k0.wrapping_mul(t + 1);

        i <<= 1;
    }
    -k0 as BigDigit
}

impl MontyReducer {
    fn new(n: &BigUint) -> Self {
        let n0inv = inv_mod_alt(n.data[0]);
        MontyReducer { n0inv }
    }
}

/// Computes z mod m = x * y * 2 ** (-n*_W) mod m
/// assuming k = -1/m mod 2**_W
/// See Gueron, "Efficient Software Implementations of Modular Exponentiation".
/// https://eprint.iacr.org/2011/239.pdf
/// In the terminology of that paper, this is an "Almost Montgomery Multiplication":
/// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result
/// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m.
fn montgomery(x: &BigUint, y: &BigUint, m: &BigUint, k: BigDigit, n: usize) -> BigUint {
    // This code assumes x, y, m are all the same length, n.
    // (required by addMulVVW and the for loop).
    // It also assumes that x, y are already reduced mod m,
    // or else the result will not be properly reduced.
    assert!(
        x.data.len() == n && y.data.len() == n && m.data.len() == n,
        "{:?} {:?} {:?} {}",
        x,
        y,
        m,
        n
    );

    let mut z = BigUint::zero();
    z.data.resize(n * 2, 0);

    let mut c: BigDigit = 0;
    for i in 0..n {
        let c2 = add_mul_vvw(&mut z.data[i..n + i], &x.data, y.data[i]);
        let t = z.data[i].wrapping_mul(k);
        let c3 = add_mul_vvw(&mut z.data[i..n + i], &m.data, t);
        let cx = c.wrapping_add(c2);
        let cy = cx.wrapping_add(c3);
        z.data[n + i] = cy;
        if cx < c2 || cy < c3 {
            c = 1;
        } else {
            c = 0;
        }
    }

    if c == 0 {
        z.data = z.data[n..].to_vec();
    } else {
        {
            let (mut first, second) = z.data.split_at_mut(n);
            sub_vv(&mut first, &second, &m.data);
        }
        z.data = z.data[..n].to_vec();
    }

    z
}

#[inline(always)]
fn add_mul_vvw(z: &mut [BigDigit], x: &[BigDigit], y: BigDigit) -> BigDigit {
    let mut c = 0;
    for (zi, xi) in z.iter_mut().zip(x.iter()) {
        let (z1, z0) = mul_add_www(*xi, y, *zi);
        let (c_, zi_) = add_ww(z0, c, 0);
        *zi = zi_;
        c = c_ + z1;
    }

    c
}

/// The resulting carry c is either 0 or 1.
#[inline(always)]
fn sub_vv(z: &mut [BigDigit], x: &[BigDigit], y: &[BigDigit]) -> BigDigit {
    let mut c = 0;
    for (i, (xi, yi)) in x.iter().zip(y.iter()).enumerate().take(z.len()) {
        let zi = xi.wrapping_sub(*yi).wrapping_sub(c);
        z[i] = zi;
        // see "Hacker's Delight", section 2-12 (overflow detection)
        c = ((yi & !xi) | ((yi | !xi) & zi)) >> (big_digit::BITS - 1)
    }

    c
}

/// z1<<_W + z0 = x+y+c, with c == 0 or 1
#[inline(always)]
fn add_ww(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) {
    let yc = y.wrapping_add(c);
    let z0 = x.wrapping_add(yc);
    let z1 = if z0 < x || yc < y { 1 } else { 0 };

    (z1, z0)
}

/// z1 << _W + z0 = x * y + c
#[inline(always)]
fn mul_add_www(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) {
    let z = x as DoubleBigDigit * y as DoubleBigDigit + c as DoubleBigDigit;
    ((z >> big_digit::BITS) as BigDigit, z as BigDigit)
}

/// Calculates x ** y mod m using a fixed, 4-bit window.
pub fn monty_modpow(x: &BigUint, y: &BigUint, m: &BigUint) -> BigUint {
    assert!(m.data[0] & 1 == 1);
    let mr = MontyReducer::new(m);
    let num_words = m.data.len();

    let mut x = x.clone();

    // We want the lengths of x and m to be equal.
    // It is OK if x >= m as long as len(x) == len(m).
    if x.data.len() > num_words {
        x %= m;
        // Note: now len(x) <= numWords, not guaranteed ==.
    }
    if x.data.len() < num_words {
        x.data.resize(num_words, 0);
    }

    // rr = 2**(2*_W*len(m)) mod m
    let mut rr = BigUint::one();
    rr = (rr.shl(2 * num_words * big_digit::BITS)) % m;
    if rr.data.len() < num_words {
        rr.data.resize(num_words, 0);
    }
    // one = 1, with equal length to that of m
    let mut one = BigUint::one();
    one.data.resize(num_words, 0);

    let n = 4;
    // powers[i] contains x^i
    let mut powers = Vec::with_capacity(1 << n);
    powers.push(montgomery(&one, &rr, m, mr.n0inv, num_words));
    powers.push(montgomery(&x, &rr, m, mr.n0inv, num_words));
    for i in 2..1 << n {
        let r = montgomery(&powers[i - 1], &powers[1], m, mr.n0inv, num_words);
        powers.push(r);
    }

    // initialize z = 1 (Montgomery 1)
    let mut z = powers[0].clone();
    z.data.resize(num_words, 0);
    let mut zz = BigUint::zero();
    zz.data.resize(num_words, 0);

    // same windowed exponent, but with Montgomery multiplications
    for i in (0..y.data.len()).rev() {
        let mut yi = y.data[i];
        let mut j = 0;
        while j < big_digit::BITS {
            if i != y.data.len() - 1 || j != 0 {
                zz = montgomery(&z, &z, m, mr.n0inv, num_words);
                z = montgomery(&zz, &zz, m, mr.n0inv, num_words);
                zz = montgomery(&z, &z, m, mr.n0inv, num_words);
                z = montgomery(&zz, &zz, m, mr.n0inv, num_words);
            }
            zz = montgomery(
                &z,
                &powers[(yi >> (big_digit::BITS - n)) as usize],
                m,
                mr.n0inv,
                num_words,
            );
            ::std::mem::swap(&mut z, &mut zz);
            yi <<= n;
            j += n;
        }
    }

    // convert to regular number
    zz = montgomery(&z, &one, m, mr.n0inv, num_words);

    zz.normalize();
    // One last reduction, just in case.
    // See golang.org/issue/13907.
    if &zz >= m {
        // Common case is m has high bit set; in that case,
        // since zz is the same length as m, there can be just
        // one multiple of m to remove. Just subtract.
        // We think that the subtract should be sufficient in general,
        // so do that unconditionally, but double-check,
        // in case our beliefs are wrong.
        // The div is not expected to be reached.
        zz -= m;
        if &zz >= m {
            zz %= m;
        }
    }

    zz.normalize();
    zz
}
<commit_msg>Don't use field shorthands for older rustc<commit_after>use std::ops::Shl;
use traits::{One, Zero};

use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit};
use biguint::BigUint;

struct MontyReducer {
    n0inv: BigDigit,
}

// k0 = -m**-1 mod 2**BITS. Algorithm from: Dumas, J.G. "On Newton–Raphson
// Iteration for Multiplicative Inverses Modulo Prime Powers".
fn inv_mod_alt(b: BigDigit) -> BigDigit {
    assert_ne!(b & 1, 0);

    let mut k0 = 2 - b as SignedDoubleBigDigit;
    let mut t = (b - 1) as SignedDoubleBigDigit;
    let mut i = 1;
    while i < big_digit::BITS {
        t = t.wrapping_mul(t);
        k0 = k0.wrapping_mul(t + 1);

        i <<= 1;
    }
    -k0 as BigDigit
}

impl MontyReducer {
    fn new(n: &BigUint) -> Self {
        let n0inv = inv_mod_alt(n.data[0]);
        MontyReducer { n0inv: n0inv }
    }
}

/// Computes z mod m = x * y * 2 ** (-n*_W) mod m
/// assuming k = -1/m mod 2**_W
/// See Gueron, "Efficient Software Implementations of Modular Exponentiation".
/// https://eprint.iacr.org/2011/239.pdf
/// In the terminology of that paper, this is an "Almost Montgomery Multiplication":
/// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result
/// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m.
fn montgomery(x: &BigUint, y: &BigUint, m: &BigUint, k: BigDigit, n: usize) -> BigUint {
    // This code assumes x, y, m are all the same length, n.
    // (required by addMulVVW and the for loop).
    // It also assumes that x, y are already reduced mod m,
    // or else the result will not be properly reduced.
    assert!(
        x.data.len() == n && y.data.len() == n && m.data.len() == n,
        "{:?} {:?} {:?} {}",
        x,
        y,
        m,
        n
    );

    let mut z = BigUint::zero();
    z.data.resize(n * 2, 0);

    let mut c: BigDigit = 0;
    for i in 0..n {
        let c2 = add_mul_vvw(&mut z.data[i..n + i], &x.data, y.data[i]);
        let t = z.data[i].wrapping_mul(k);
        let c3 = add_mul_vvw(&mut z.data[i..n + i], &m.data, t);
        let cx = c.wrapping_add(c2);
        let cy = cx.wrapping_add(c3);
        z.data[n + i] = cy;
        if cx < c2 || cy < c3 {
            c = 1;
        } else {
            c = 0;
        }
    }

    if c == 0 {
        z.data = z.data[n..].to_vec();
    } else {
        {
            let (mut first, second) = z.data.split_at_mut(n);
            sub_vv(&mut first, &second, &m.data);
        }
        z.data = z.data[..n].to_vec();
    }

    z
}

#[inline(always)]
fn add_mul_vvw(z: &mut [BigDigit], x: &[BigDigit], y: BigDigit) -> BigDigit {
    let mut c = 0;
    for (zi, xi) in z.iter_mut().zip(x.iter()) {
        let (z1, z0) = mul_add_www(*xi, y, *zi);
        let (c_, zi_) = add_ww(z0, c, 0);
        *zi = zi_;
        c = c_ + z1;
    }

    c
}

/// The resulting carry c is either 0 or 1.
#[inline(always)]
fn sub_vv(z: &mut [BigDigit], x: &[BigDigit], y: &[BigDigit]) -> BigDigit {
    let mut c = 0;
    for (i, (xi, yi)) in x.iter().zip(y.iter()).enumerate().take(z.len()) {
        let zi = xi.wrapping_sub(*yi).wrapping_sub(c);
        z[i] = zi;
        // see "Hacker's Delight", section 2-12 (overflow detection)
        c = ((yi & !xi) | ((yi | !xi) & zi)) >> (big_digit::BITS - 1)
    }

    c
}

/// z1<<_W + z0 = x+y+c, with c == 0 or 1
#[inline(always)]
fn add_ww(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) {
    let yc = y.wrapping_add(c);
    let z0 = x.wrapping_add(yc);
    let z1 = if z0 < x || yc < y { 1 } else { 0 };

    (z1, z0)
}

/// z1 << _W + z0 = x * y + c
#[inline(always)]
fn mul_add_www(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) {
    let z = x as DoubleBigDigit * y as DoubleBigDigit + c as DoubleBigDigit;
    ((z >> big_digit::BITS) as BigDigit, z as BigDigit)
}

/// Calculates x ** y mod m using a fixed, 4-bit window.
pub fn monty_modpow(x: &BigUint, y: &BigUint, m: &BigUint) -> BigUint {
    assert!(m.data[0] & 1 == 1);
    let mr = MontyReducer::new(m);
    let num_words = m.data.len();

    let mut x = x.clone();

    // We want the lengths of x and m to be equal.
    // It is OK if x >= m as long as len(x) == len(m).
    if x.data.len() > num_words {
        x %= m;
        // Note: now len(x) <= numWords, not guaranteed ==.
    }
    if x.data.len() < num_words {
        x.data.resize(num_words, 0);
    }

    // rr = 2**(2*_W*len(m)) mod m
    let mut rr = BigUint::one();
    rr = (rr.shl(2 * num_words * big_digit::BITS)) % m;
    if rr.data.len() < num_words {
        rr.data.resize(num_words, 0);
    }
    // one = 1, with equal length to that of m
    let mut one = BigUint::one();
    one.data.resize(num_words, 0);

    let n = 4;
    // powers[i] contains x^i
    let mut powers = Vec::with_capacity(1 << n);
    powers.push(montgomery(&one, &rr, m, mr.n0inv, num_words));
    powers.push(montgomery(&x, &rr, m, mr.n0inv, num_words));
    for i in 2..1 << n {
        let r = montgomery(&powers[i - 1], &powers[1], m, mr.n0inv, num_words);
        powers.push(r);
    }

    // initialize z = 1 (Montgomery 1)
    let mut z = powers[0].clone();
    z.data.resize(num_words, 0);
    let mut zz = BigUint::zero();
    zz.data.resize(num_words, 0);

    // same windowed exponent, but with Montgomery multiplications
    for i in (0..y.data.len()).rev() {
        let mut yi = y.data[i];
        let mut j = 0;
        while j < big_digit::BITS {
            if i != y.data.len() - 1 || j != 0 {
                zz = montgomery(&z, &z, m, mr.n0inv, num_words);
                z = montgomery(&zz, &zz, m, mr.n0inv, num_words);
                zz = montgomery(&z, &z, m, mr.n0inv, num_words);
                z = montgomery(&zz, &zz, m, mr.n0inv, num_words);
            }
            zz = montgomery(
                &z,
                &powers[(yi >> (big_digit::BITS - n)) as usize],
                m,
                mr.n0inv,
                num_words,
            );
            ::std::mem::swap(&mut z, &mut zz);
            yi <<= n;
            j += n;
        }
    }

    // convert to regular number
    zz = montgomery(&z, &one, m, mr.n0inv, num_words);

    zz.normalize();
    // One last reduction, just in case.
    // See golang.org/issue/13907.
    if &zz >= m {
        // Common case is m has high bit set; in that case,
        // since zz is the same length as m, there can be just
        // one multiple of m to remove. Just subtract.
        // We think that the subtract should be sufficient in general,
        // so do that unconditionally, but double-check,
        // in case our beliefs are wrong.
        // The div is not expected to be reached.
        zz -= m;
        if &zz >= m {
            zz %= m;
        }
    }

    zz.normalize();
    zz
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Data needed by the layout task.

use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};

use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::OpaqueNode;
use gfx::font_context::{FontContext, FontContextInfo};
#[cfg(not(target_os="android"))]
use green::task::GreenTask;
use script::layout_interface::LayoutChan;
use servo_msg::constellation_msg::ConstellationChan;
use servo_net::local_image_cache::LocalImageCache;
use servo_util::geometry::Au;
use servo_util::opts::Opts;
use sync::{Arc, Mutex};
use std::mem;
#[cfg(not(target_os="android"))]
use std::ptr;
#[cfg(not(target_os="android"))]
use std::rt::local::Local;
#[cfg(not(target_os="android"))]
use std::rt::task::Task;
use style::Stylist;
use url::Url;

#[cfg(not(target_os="android"))]
#[thread_local]
static mut FONT_CONTEXT: *mut FontContext = 0 as *mut FontContext;

#[cfg(target_os="android")]
local_data_key!(font_context: *mut FontContext)

#[cfg(not(target_os="android"))]
#[thread_local]
static mut APPLICABLE_DECLARATIONS_CACHE: *mut ApplicableDeclarationsCache =
    0 as *mut ApplicableDeclarationsCache;

#[cfg(target_os="android")]
local_data_key!(applicable_declarations_cache: *mut ApplicableDeclarationsCache)

#[cfg(not(target_os="android"))]
#[thread_local]
static mut STYLE_SHARING_CANDIDATE_CACHE: *mut StyleSharingCandidateCache =
    0 as *mut StyleSharingCandidateCache;

#[cfg(target_os="android")]
local_data_key!(style_sharing_candidate_cache: *mut StyleSharingCandidateCache)

/// Data shared by all layout workers.
#[deriving(Clone)]
pub struct LayoutContext {
    /// The local image cache.
    pub image_cache: Arc<Mutex<LocalImageCache>>,

    /// The current screen size.
    pub screen_size: Size2D<Au>,

    /// A channel up to the constellation.
    pub constellation_chan: ConstellationChan,

    /// A channel up to the layout task.
    pub layout_chan: LayoutChan,

    /// Information needed to construct a font context.
    pub font_context_info: FontContextInfo,

    /// The CSS selector stylist.
    ///
    /// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s.
    pub stylist: *Stylist,

    /// The root node at which we're starting the layout.
    pub reflow_root: OpaqueNode,

    /// The URL.
    pub url: Url,

    /// The command line options.
    pub opts: Opts,

    /// The dirty rectangle, used during display list building.
    pub dirty: Rect<Au>,
}

#[cfg(not(target_os="android"))]
impl LayoutContext {
    pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
        // Sanity check.
        {
            let mut task = Local::borrow(None::<Task>);
            match task.maybe_take_runtime::<GreenTask>() {
                Some(green) => {
                    task.put_runtime(green);
                    fail!("can't call this on a green task!")
                }
                None => {}
            }
        }

        unsafe {
            if FONT_CONTEXT == ptr::mut_null() {
                let context = box FontContext::new(self.font_context_info.clone());
                FONT_CONTEXT = mem::transmute(context)
            }
            mem::transmute(FONT_CONTEXT)
        }
    }

    pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
        // Sanity check.
        {
            let mut task = Local::borrow(None::<Task>);
            match task.maybe_take_runtime::<GreenTask>() {
                Some(green) => {
                    task.put_runtime(green);
                    fail!("can't call this on a green task!")
                }
                None => {}
            }
        }

        unsafe {
            if APPLICABLE_DECLARATIONS_CACHE == ptr::mut_null() {
                let cache = box ApplicableDeclarationsCache::new();
                APPLICABLE_DECLARATIONS_CACHE = mem::transmute(cache)
            }
            mem::transmute(APPLICABLE_DECLARATIONS_CACHE)
        }
    }

    pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
        // Sanity check.
        {
            let mut task = Local::borrow(None::<Task>);
            match task.maybe_take_runtime::<GreenTask>() {
                Some(green) => {
                    task.put_runtime(green);
                    fail!("can't call this on a green task!")
                }
                None => {}
            }
        }

        unsafe {
            if STYLE_SHARING_CANDIDATE_CACHE == ptr::mut_null() {
                let cache = box StyleSharingCandidateCache::new();
                STYLE_SHARING_CANDIDATE_CACHE = mem::transmute(cache)
            }
            mem::transmute(STYLE_SHARING_CANDIDATE_CACHE)
        }
    }
}

// On Android, we don't have the __tls_* functions emitted by rustc, so we
// need to use the slower local_data functions.
// Making matters worse, the local_data functions are very particular about
// enforcing the lifetimes associated with objects that they hold onto,
// which causes us some trouble we work around as below.
#[cfg(target_os="android")]
impl LayoutContext {
    pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
        unsafe {
            let opt = font_context.replace(None);
            let mut context;
            match opt {
                Some(c) => context = mem::transmute(c),
                None => {
                    context = mem::transmute(box FontContext::new(self.font_context_info.clone()))
                }
            }
            font_context.replace(Some(context));
            mem::transmute(context)
        }
    }

    pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
        unsafe {
            let opt = applicable_declarations_cache.replace(None);
            let mut cache;
            match opt {
                Some(c) => cache = mem::transmute(c),
                None => {
                    cache = mem::transmute(box ApplicableDeclarationsCache::new());
                }
            }
            applicable_declarations_cache.replace(Some(cache));
            mem::transmute(cache)
        }
    }

    pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
        unsafe {
            let opt = style_sharing_candidate_cache.replace(None);
            let mut cache;
            match opt {
                Some(c) => cache = mem::transmute(c),
                None => {
                    cache = mem::transmute(box StyleSharingCandidateCache::new());
                }
            }
            style_sharing_candidate_cache.replace(Some(cache));
            mem::transmute(cache)
        }
    }
}

<commit_msg>Suppress the compiler warning about raw_pointer_deriving in layout/context.rs.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Data needed by the layout task.

use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};

use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::OpaqueNode;
use gfx::font_context::{FontContext, FontContextInfo};
#[cfg(not(target_os="android"))]
use green::task::GreenTask;
use script::layout_interface::LayoutChan;
use servo_msg::constellation_msg::ConstellationChan;
use servo_net::local_image_cache::LocalImageCache;
use servo_util::geometry::Au;
use servo_util::opts::Opts;
use sync::{Arc, Mutex};
use std::mem;
#[cfg(not(target_os="android"))]
use std::ptr;
#[cfg(not(target_os="android"))]
use std::rt::local::Local;
#[cfg(not(target_os="android"))]
use std::rt::task::Task;
use style::Stylist;
use url::Url;

#[cfg(not(target_os="android"))]
#[thread_local]
static mut FONT_CONTEXT: *mut FontContext = 0 as *mut FontContext;

#[cfg(target_os="android")]
local_data_key!(font_context: *mut FontContext)

#[cfg(not(target_os="android"))]
#[thread_local]
static mut APPLICABLE_DECLARATIONS_CACHE: *mut ApplicableDeclarationsCache =
    0 as *mut ApplicableDeclarationsCache;

#[cfg(target_os="android")]
local_data_key!(applicable_declarations_cache: *mut ApplicableDeclarationsCache)

#[cfg(not(target_os="android"))]
#[thread_local]
static mut STYLE_SHARING_CANDIDATE_CACHE: *mut StyleSharingCandidateCache =
    0 as *mut StyleSharingCandidateCache;

#[cfg(target_os="android")]
local_data_key!(style_sharing_candidate_cache: *mut StyleSharingCandidateCache)

/// Data shared by all layout workers.
#[allow(raw_pointer_deriving)]
#[deriving(Clone)]
pub struct LayoutContext {
    /// The local image cache.
    pub image_cache: Arc<Mutex<LocalImageCache>>,

    /// The current screen size.
    pub screen_size: Size2D<Au>,

    /// A channel up to the constellation.
    pub constellation_chan: ConstellationChan,

    /// A channel up to the layout task.
    pub layout_chan: LayoutChan,

    /// Information needed to construct a font context.
    pub font_context_info: FontContextInfo,

    /// The CSS selector stylist.
    ///
    /// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s.
    pub stylist: *Stylist,

    /// The root node at which we're starting the layout.
    pub reflow_root: OpaqueNode,

    /// The URL.
    pub url: Url,

    /// The command line options.
    pub opts: Opts,

    /// The dirty rectangle, used during display list building.
    pub dirty: Rect<Au>,
}

#[cfg(not(target_os="android"))]
impl LayoutContext {
    pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
        // Sanity check.
        {
            let mut task = Local::borrow(None::<Task>);
            match task.maybe_take_runtime::<GreenTask>() {
                Some(green) => {
                    task.put_runtime(green);
                    fail!("can't call this on a green task!")
                }
                None => {}
            }
        }

        unsafe {
            if FONT_CONTEXT == ptr::mut_null() {
                let context = box FontContext::new(self.font_context_info.clone());
                FONT_CONTEXT = mem::transmute(context)
            }
            mem::transmute(FONT_CONTEXT)
        }
    }

    pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
        // Sanity check.
        {
            let mut task = Local::borrow(None::<Task>);
            match task.maybe_take_runtime::<GreenTask>() {
                Some(green) => {
                    task.put_runtime(green);
                    fail!("can't call this on a green task!")
                }
                None => {}
            }
        }

        unsafe {
            if APPLICABLE_DECLARATIONS_CACHE == ptr::mut_null() {
                let cache = box ApplicableDeclarationsCache::new();
                APPLICABLE_DECLARATIONS_CACHE = mem::transmute(cache)
            }
            mem::transmute(APPLICABLE_DECLARATIONS_CACHE)
        }
    }

    pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
        // Sanity check.
        {
            let mut task = Local::borrow(None::<Task>);
            match task.maybe_take_runtime::<GreenTask>() {
                Some(green) => {
                    task.put_runtime(green);
                    fail!("can't call this on a green task!")
                }
                None => {}
            }
        }

        unsafe {
            if STYLE_SHARING_CANDIDATE_CACHE == ptr::mut_null() {
                let cache = box StyleSharingCandidateCache::new();
                STYLE_SHARING_CANDIDATE_CACHE = mem::transmute(cache)
            }
            mem::transmute(STYLE_SHARING_CANDIDATE_CACHE)
        }
    }
}

// On Android, we don't have the __tls_* functions emitted by rustc, so we
// need to use the slower local_data functions.
// Making matters worse, the local_data functions are very particular about
// enforcing the lifetimes associated with objects that they hold onto,
// which causes us some trouble we work around as below.
#[cfg(target_os="android")]
impl LayoutContext {
    pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
        unsafe {
            let opt = font_context.replace(None);
            let mut context;
            match opt {
                Some(c) => context = mem::transmute(c),
                None => {
                    context = mem::transmute(box FontContext::new(self.font_context_info.clone()))
                }
            }
            font_context.replace(Some(context));
            mem::transmute(context)
        }
    }

    pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
        unsafe {
            let opt = applicable_declarations_cache.replace(None);
            let mut cache;
            match opt {
                Some(c) => cache = mem::transmute(c),
                None => {
                    cache = mem::transmute(box ApplicableDeclarationsCache::new());
                }
            }
            applicable_declarations_cache.replace(Some(cache));
            mem::transmute(cache)
        }
    }

    pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
        unsafe {
            let opt = style_sharing_candidate_cache.replace(None);
            let mut cache;
            match opt {
                Some(c) => cache = mem::transmute(c),
                None => {
                    cache = mem::transmute(box StyleSharingCandidateCache::new());
                }
            }
            style_sharing_candidate_cache.replace(Some(cache));
            mem::transmute(cache)
        }
    }
}

<|endoftext|>


<commit_before>use super::ByteSize;

impl std::str::FromStr for ByteSize {
    type Err = String;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        match value.parse::<u64>() {
            Ok(v) => return Ok(Self(v)), // simple case, bytes
            Err(_) => {}
        };
        let number: String = value
            .chars()
            .take_while(|c| c.is_digit(10) || c == &'.')
            .collect();
        match number.parse::<f64>() {
            Ok(v) => {
                let suffix: String = value
                    .chars()
                    .skip_while(|c| c.is_whitespace() || c.is_digit(10) || c == &'.')
                    .collect();
                Ok(Self((v * match_suffix(&suffix) as f64) as u64))
            }
            Err(error) => Err(format!(
                "couldn't parse {:?} into a ByteSize, {}",
                value, error
            )),
        }
    }
}

fn match_suffix(unit: &str) -> u64 {
    match unit.to_lowercase().as_str() {
        "k" | "kb" => super::KB,
        "ki" | "kib" => super::KIB,
        "m" | "mb" => super::MB,
        "mi" | "mib" => super::MIB,
        "g" | "gb" => super::GB,
        "gi" | "gib" => super::GIB,
        "t" | "tb" => super::TB,
        "ti" | "tib" => super::TIB,
        "p" | "pb" => super::PB,
        "pi" | "pib" => super::PIB,
        _ => 1,
    }
}

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

    #[test]
    fn when_ok() {
        // shortcut for writing test cases
        fn parse(s: &str) -> u64 {
            s.parse::<ByteSize>().unwrap().0
        }

        assert_eq!("0".parse::<ByteSize>().unwrap().0, 0);
        assert_eq!(parse("0"), 0);
        assert_eq!(parse("500"), 500);
        assert_eq!(parse("1K"), 1 * KB);
        assert_eq!(parse("1Ki"), 1 * KIB);
        assert_eq!(parse("1.5Ki"), (1.5 * KIB as f64) as u64);
        assert_eq!(parse("1KiB"), 1 * KIB);
        assert_eq!(parse("1.5KiB"), (1.5 * KIB as f64) as u64);
        assert_eq!(parse("3 MB"), 3 * MB);
        assert_eq!(parse("4 MiB"), 4 * MIB);
        assert_eq!(parse("6 GB"), 6 * GB);
        assert_eq!(parse("4 GiB"), 4 * GIB);
        assert_eq!(parse("88TB"), 88 * TB);
        assert_eq!(parse("521TiB"), 521 * TIB);
        assert_eq!(parse("8 PB"), 8 * PB);
        assert_eq!(parse("12 PiB"), 12 * PIB);
    }
}
<commit_msg>comment and precise imports<commit_after>use super::ByteSize;

impl std::str::FromStr for ByteSize {
    type Err = String;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        match value.parse::<u64>() {
            Ok(v) => return Ok(Self(v)), // simple case, bytes
            Err(_) => {}
        };
        let number: String = value
            .chars()
            .take_while(|c| c.is_digit(10) || c == &'.')
            .collect();
        match number.parse::<f64>() {
            Ok(v) => {
                let suffix: String = value
                    .chars()
                    .skip_while(|c| c.is_whitespace() || c.is_digit(10) || c == &'.')
                    .collect();
                Ok(Self((v * match_suffix(&suffix) as f64) as u64))
            }
            Err(error) => Err(format!(
                "couldn't parse {:?} into a ByteSize, {}",
                value, error
            )),
        }
    }
}

/// todo: maybe a Unit type would be appropriate
fn match_suffix(unit: &str) -> u64 {
    match unit.to_lowercase().as_str() {
        "k" | "kb" => super::KB,
        "ki" | "kib" => super::KIB,
        "m" | "mb" => super::MB,
        "mi" | "mib" => super::MIB,
        "g" | "gb" => super::GB,
        "gi" | "gib" => super::GIB,
        "t" | "tb" => super::TB,
        "ti" | "tib" => super::TIB,
        "p" | "pb" => super::PB,
        "pi" | "pib" => super::PIB,
        _ => 1,
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::{KB, KIB, MB, MIB, GB, GIB, TB, TIB, PB, PIB};

    #[test]
    fn when_ok() {
        // shortcut for writing test cases
        fn parse(s: &str) -> u64 {
            s.parse::<ByteSize>().unwrap().0
        }

        assert_eq!("0".parse::<ByteSize>().unwrap().0, 0);
        assert_eq!(parse("0"), 0);
        assert_eq!(parse("500"), 500);
        assert_eq!(parse("1K"), 1 * KB);
        assert_eq!(parse("1Ki"), 1 * KIB);
        assert_eq!(parse("1.5Ki"), (1.5 * KIB as f64) as u64);
        assert_eq!(parse("1KiB"), 1 * KIB);
        assert_eq!(parse("1.5KiB"), (1.5 * KIB as f64) as u64);
        assert_eq!(parse("3 MB"), 3 * MB);
        assert_eq!(parse("4 MiB"), 4 * MIB);
        assert_eq!(parse("6 GB"), 6 * GB);
        assert_eq!(parse("4 GiB"), 4 * GIB);
        assert_eq!(parse("88TB"), 88 * TB);
        assert_eq!(parse("521TiB"), 521 * TIB);
        assert_eq!(parse("8 PB"), 8 * PB);
        assert_eq!(parse("12 PiB"), 12 * PIB);
    }

    #[test]
    fn when_err() {
        // shortcut for writing test cases
        fn parse(s: &str) -> Result<ByteSize, String> {
            s.parse::<ByteSize>()
        }

        assert!(parse("").is_err());
        assert!(parse("a124GB").is_err());
    }
}
<|endoftext|>


<commit_before>use std::str;

use nom::{alphanumeric, IResult};

use error::EdoError;

#[derive(Debug, PartialEq)]
pub enum Expression<'a> {
    Function {
        name: &'a str,
        arguments: Vec<&'a str>,
    },
    Literal(&'a str),
}

// Parse a list of arguments
// TODO: allow trailing commas, allow leading and trailing whitespace
named!(arguments<&[u8], Vec<&str> >, delimited!(
    char!('('),
    separated_list!(
        terminated!(
            char!(','),
            many0!(char!(' '))
        ),
        map_res!(
            alphanumeric,
            str::from_utf8
        )
    ),
    char!(')')
));

// Parse a function
named!(function<&[u8], Expression>, chain!(
    tag!("{") ~
    // Parse until the function ends or the arguments start
    name: map_res!(
        alt!(
            take_until!("(") |
            take_until!("}")
        ),
        str::from_utf8
    ) ~
    // Optionally parse a list of arguments
    args: arguments? ~
    tag!("}") ,
    || { Expression::Function {
        name: name,
        arguments: args.unwrap_or(vec![]),
    }}
));

// Parse a literal
named!(literal<&[u8], Expression>, map!(
    map_res!(
        is_not!("{"),
        str::from_utf8
    ),
    Expression::Literal
));

// Parse multiple functions and text literals
named!(pub expressions<&[u8], Vec<Expression> >, many0!(alt!(
    function |
    literal
)));

/// Parse a template into a vector of expressions
pub fn parse<'a>(input: &'a str) -> Result<Vec<Expression>, EdoError> {
    match expressions(input.as_bytes()) {
        IResult::Done(_, expressions) => Ok(expressions),
        IResult::Error(_) =>
            Err(EdoError::ParsingError),
        IResult::Incomplete(_) =>
            Err(EdoError::ParsingError),
    }
}

#[cfg(test)]
mod tests {
    use nom::IResult;

    use super::{
        Expression,
        arguments,
        function,
        literal,
        expressions,
        parse
    };

    #[test]
    fn parse_arguments() {
        assert_eq!(
            arguments(b"()"),
            IResult::Done(
                &b""[..],
                vec![]
            )
        );

        assert_eq!(
            arguments(b"(test)"),
            IResult::Done(
                &b""[..],
                vec!["test"]
            )
        );

        assert_eq!(
            arguments(b"(test,test2)"),
            IResult::Done(
                &b""[..],
                vec!["test", "test2"]
            )
        );

        assert_eq!(
            arguments(b"(test, test2)"),
            IResult::Done(
                &b""[..],
                vec!["test", "test2"]
            )
        );
    }

    #[test]
    fn parse_function() {
        assert_eq!(
            function(b"{test}"),
            IResult::Done(
                &b""[..],
                Expression::Function {
                    name: "test",
                    arguments: vec![],
                }
            )
        );

        assert_eq!(
            function(b"{test()}"),
            IResult::Done(
                &b""[..],
                Expression::Function {
                    name: "test",
                    arguments: vec![],
                }
            )
        );

        assert_eq!(
            function(b"{test(1, 2, 3)}"),
            IResult::Done(
                &b""[..],
                Expression::Function {
                    name: "test",
                    arguments: vec!["1", "2", "3"],
                }
            )
        );
    }

    #[test]
    fn parse_literal() {
        assert_eq!(
            literal(b"testing"),
            IResult::Done(
                &b""[..],
                Expression::Literal("testing")
            )
        );
    }

    #[test]
    fn parse_multiple_expressions() {
        assert_eq!(
            expressions(b"{test}literal{test2}haha"),
            IResult::Done(
                &b""[..],
                vec![
                    Expression::Function {
                        name: "test",
                        arguments: vec![],
                    },
                    Expression::Literal("literal"),
                    Expression::Function {
                        name: "test2",
                        arguments: vec![],
                    },
                    Expression::Literal("haha"),
                ]
            )
        );

        assert_eq!(
            expressions(b"haha{test}"),
            IResult::Done(
                &b""[..],
                vec![
                    Expression::Literal("haha"),
                    Expression::Function {
                        name: "test",
                        arguments: vec![],
                    },
                ]
            )
        );
    }

    #[test]
    fn parse_method() {
        assert_eq!(
            parse("haha{test(a, b, c)}"),
            Ok(vec![
                Expression::Literal("haha"),
                Expression::Function {
                    name: "test",
                    arguments: vec!["a", "b", "c"],
                },
            ])
        );
    }
}
<commit_msg>Add TODO to argument parsing<commit_after>use std::str;

use nom::{alphanumeric, IResult};

use error::EdoError;

#[derive(Debug, PartialEq)]
pub enum Expression<'a> {
    Function {
        name: &'a str,
        arguments: Vec<&'a str>,
    },
    Literal(&'a str),
}

// Parse a list of arguments
// TODO: allow non alphanumeric values inside arguments
// TODO: allow trailing commas, allow leading and trailing whitespace
named!(arguments<&[u8], Vec<&str> >, delimited!(
    char!('('),
    separated_list!(
        terminated!(
            char!(','),
            many0!(char!(' '))
        ),
        map_res!(
            alphanumeric,
            str::from_utf8
        )
    ),
    char!(')')
));

// Parse a function
named!(function<&[u8], Expression>, chain!(
    tag!("{") ~
    // Parse until the function ends or the arguments start
    name: map_res!(
        alt!(
            take_until!("(") |
            take_until!("}")
        ),
        str::from_utf8
    ) ~
    // Optionally parse a list of arguments
    args: arguments? ~
    tag!("}") ,
    || { Expression::Function {
        name: name,
        arguments: args.unwrap_or(vec![]),
    }}
));

// Parse a literal
named!(literal<&[u8], Expression>, map!(
    map_res!(
        is_not!("{"),
        str::from_utf8
    ),
    Expression::Literal
));

// Parse multiple functions and text literals
named!(pub expressions<&[u8], Vec<Expression> >, many0!(alt!(
    function |
    literal
)));

/// Parse a template into a vector of expressions
pub fn parse<'a>(input: &'a str) -> Result<Vec<Expression>, EdoError> {
    match expressions(input.as_bytes()) {
        IResult::Done(_, expressions) => Ok(expressions),
        IResult::Error(_) =>
            Err(EdoError::ParsingError),
        IResult::Incomplete(_) =>
            Err(EdoError::ParsingError),
    }
}

#[cfg(test)]
mod tests {
    use nom::IResult;

    use super::{
        Expression,
        arguments,
        function,
        literal,
        expressions,
        parse
    };

    #[test]
    fn parse_arguments() {
        assert_eq!(
            arguments(b"()"),
            IResult::Done(
                &b""[..],
                vec![]
            )
        );

        assert_eq!(
            arguments(b"(test)"),
            IResult::Done(
                &b""[..],
                vec!["test"]
            )
        );

        assert_eq!(
            arguments(b"(test,test2)"),
            IResult::Done(
                &b""[..],
                vec!["test", "test2"]
            )
        );

        assert_eq!(
            arguments(b"(test, test2)"),
            IResult::Done(
                &b""[..],
                vec!["test", "test2"]
            )
        );
    }

    #[test]
    fn parse_function() {
        assert_eq!(
            function(b"{test}"),
            IResult::Done(
                &b""[..],
                Expression::Function {
                    name: "test",
                    arguments: vec![],
                }
            )
        );

        assert_eq!(
            function(b"{test()}"),
            IResult::Done(
                &b""[..],
                Expression::Function {
                    name: "test",
                    arguments: vec![],
                }
            )
        );

        assert_eq!(
            function(b"{test(1, 2, 3)}"),
            IResult::Done(
                &b""[..],
                Expression::Function {
                    name: "test",
                    arguments: vec!["1", "2", "3"],
                }
            )
        );
    }

    #[test]
    fn parse_literal() {
        assert_eq!(
            literal(b"testing"),
            IResult::Done(
                &b""[..],
                Expression::Literal("testing")
            )
        );
    }

    #[test]
    fn parse_multiple_expressions() {
        assert_eq!(
            expressions(b"{test}literal{test2}haha"),
            IResult::Done(
                &b""[..],
                vec![
                    Expression::Function {
                        name: "test",
                        arguments: vec![],
                    },
                    Expression::Literal("literal"),
                    Expression::Function {
                        name: "test2",
                        arguments: vec![],
                    },
                    Expression::Literal("haha"),
                ]
            )
        );

        assert_eq!(
            expressions(b"haha{test}"),
            IResult::Done(
                &b""[..],
                vec![
                    Expression::Literal("haha"),
                    Expression::Function {
                        name: "test",
                        arguments: vec![],
                    },
                ]
            )
        );
    }

    #[test]
    fn parse_method() {
        assert_eq!(
            parse("haha{test(a, b, c)}"),
            Ok(vec![
                Expression::Literal("haha"),
                Expression::Function {
                    name: "test",
                    arguments: vec!["a", "b", "c"],
                },
            ])
        );
    }
}
<|endoftext|>


<commit_before>use std::ops::{Sub, Div};

#[derive(Copy, Clone)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Self {
        Point { x: x, y: y }
    }

    pub fn cross(self, other: Point) -> f64 {
        return self.x * other.y - other.x * self.y;
    }

    pub fn dot(self, other: Point) -> f64 {
        return self.x * other.x + self.y * other.y;
    }
}

impl Sub<Point> for Point {
    type Output = Point;

    fn sub(self, other: Point) -> Self::Output {
        return Point {
            x: self.x - other.x,
            y: self.y - other.y,
        };
    }
}

impl Div<f64> for Point {
    type Output = Point;

    fn div(self, other: f64) -> Self::Output {
        return Point {
            x: self.x / other,
            y: self.y / other,
        };
    }
}
<commit_msg>Add test case for Point::new<commit_after>use std::ops::{Sub, Div};

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Self {
        Point { x: x, y: y }
    }

    pub fn cross(self, other: Point) -> f64 {
        return self.x * other.y - other.x * self.y;
    }

    pub fn dot(self, other: Point) -> f64 {
        return self.x * other.x + self.y * other.y;
    }
}

impl Sub<Point> for Point {
    type Output = Point;

    fn sub(self, other: Point) -> Self::Output {
        return Point {
            x: self.x - other.x,
            y: self.y - other.y,
        };
    }
}

impl Div<f64> for Point {
    type Output = Point;

    fn div(self, other: f64) -> Self::Output {
        return Point {
            x: self.x / other,
            y: self.y / other,
        };
    }
}

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

    #[test]
    fn test_new() {
        expect!(Point::new(1.0, 1.0)).to(be_equal_to(Point { x: 1.0, y: 1.0 }));
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;

type Result<T> = std::result::Result<T, String>;

// Setup to make this work. Create two files with some info. Ignore the
// return values because we don't care about them here.
fn setup() {
    File::create("a")
        .and_then(|mut file| file.write_all(b"grape"))
        .unwrap();

    File::create("b")
        .and_then(|mut file| file.write_all(b"fruit"))
        .unwrap();
}

// Get the data from each file with the data stored in a `Result`.
fn get_data(path: &str) -> Result<String> {
    File::open(path)
        .map_err(|err| err.to_string())
        .and_then(|mut file| {
            let mut contents = String::new();

            // Read the data into `contents`.
            file.read_to_string(&mut contents)
                .map_err(|err| err.to_string())
                // Ignore the output `read_to_string` returns and return `contents`.
                .map(|_| contents)
        })
}

// Concat the contents of the two files together into a new `Result`.
fn concat(filename_a: &str, filename_b: &str) -> Result<String> {
    let (data_a, data_b) = (get_data(filename_a), get_data(filename_b));

    data_a.and_then(|a|
        // Return `Ok` when both `a` and `b` are `Ok`. Otherwise return
        // whichever has the first `Err`.
        data_b.and_then(|b| Ok(a + &b))
    )
}

fn main() {
    setup();

    match concat("a", "b") {
        Ok(n)  => println!("{}", n),
        Err(e) => println!("Error: {}", e),
    }
}
<commit_msg>Reworked example as per minor discussion in #764<commit_after>// Use `String` as our error type
type Result<T> = std::result::Result<T, String>;

fn double_first(vec: Vec<&str>) -> Result<i32> {
   // Convert the `Option` to a `Result` if there is a value.
   // Otherwise, provide an `Err` containing this `String`.
    let first = match vec.first() {
        Some(first) => first,
        None => return Err("Please use a vector with at least one element.".to_owned())
    };

    // Double the number inside if `parse` works fine.
    // Otherwise, map any errors that `parse` yields to `String`.
    match first.parse::<i32>() {
        Ok(i) => Ok(2 * i),
        Err(e) => Err(e.to_string()),
    }
}

fn print(result: Result<i32>) {
    match result {
        Ok(n)  => println!("The first doubled is {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    let empty = vec![];
    let strings = vec!["tofu", "93", "18"];

    print(double_first(empty));
    print(double_first(strings));
}<|endoftext|>


<commit_before>use std::cmp;
use fnv::FnvHashMap;
use error::{Error, ErrorKind};
use result::Result;
use utf8::{DOLLAR, DOT};

const ROOT_QUERY_STR_OFFSET: usize = 2;

#[derive(Debug)]
pub struct Query<'a> {
    pub i: usize,
    pub ri: usize,
    pub target: bool,
    pub children: Option<FnvHashMap<&'a [u8], Query<'a>>>,
}

/// A pattern tree associated with the queries
pub struct QueryTree<'a> {
    pub root: FnvHashMap<&'a [u8], Query<'a>>,
    pub num_queries: usize,
    pub max_depth: usize,
    pub num_nodes: usize,
}

impl<'a> QueryTree<'a> {
    pub fn new<S: ?Sized + AsRef<[u8]>>(queries: &[&'a S]) -> Result<Self> {
        let mut root = FnvHashMap::default();
        let mut level = 0;
        let mut qi = 0;

        for (ri, s) in queries.into_iter().map(|s| (*s).as_ref()).enumerate() {
            if !is_valid_query_str(s) {
                return Err(Error::from(ErrorKind::InvalidQuery));
            }

            let l = set_queries(&mut root, &s[ROOT_QUERY_STR_OFFSET..], &mut qi, ri);
            level = cmp::max(level, l);
        }

        Ok(Self {
            root,
            num_queries: queries.len(),
            max_depth: level,
            num_nodes: qi,
        })
    }
}

#[inline]
fn is_valid_query_str(query_str: &[u8]) -> bool {
    if query_str.len() < ROOT_QUERY_STR_OFFSET + 1 || query_str[0] != DOLLAR || query_str[1] != DOT {
        return false;
    }
    let mut s = ROOT_QUERY_STR_OFFSET - 1;
    for i in s + 1..query_str.len() {
        if query_str[i] != DOT {
            continue;
        }
        if i == s + 1 || i == query_str.len() - 1 {
            return false;
        }
        s = i;
    }
    true
}

#[inline]
fn set_queries<'a>(queries: &mut FnvHashMap<&'a [u8], Query<'a>>, s: &'a [u8], qi: &mut usize, ri: usize) -> usize {
    for j in 0..s.len() {
        if s[j] == DOT {
            let (t, u) = s.split_at(j);
            let query = queries.entry(t).or_insert_with(|| {
                let query = Query {
                    i: *qi,
                    ri: ri,
                    target: false,
                    children: None,
                };
                *qi += 1;
                query
            });
            return set_queries(
                query.children.get_or_insert(FnvHashMap::default()),
                &u[1..],
                qi,
                ri,
            ) + 1;
        }
    }

    let query = queries.entry(s).or_insert_with(|| {
        let query = Query {
            i: *qi,
            ri: ri,
            target: false,
            children: None,
        };
        *qi += 1;
        query
    });
    query.target = true;
    1
}

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

    #[test]
    fn test_is_valid_query_str() {
        struct TestCase<'a> {
            query_str: &'a str,
            want: bool,
        }
        let test_cases = vec![
            TestCase {
                query_str: "",
                want: false,
            },
            TestCase {
                query_str: "$",
                want: false,
            },
            TestCase {
                query_str: "$.",
                want: false,
            },
            TestCase {
                query_str: "$..",
                want: false,
            },
            TestCase {
                query_str: "a.a",
                want: false,
            },
            TestCase {
                query_str: "$aa",
                want: false,
            },
            TestCase {
                query_str: "$.a",
                want: true,
            },
            TestCase {
                query_str: "$.aaaa",
                want: true,
            },
            TestCase {
                query_str: "$.aaaa.",
                want: false,
            },
            TestCase {
                query_str: "$.aaaa.b",
                want: true,
            },
            TestCase {
                query_str: "$.aaaa.bbbb",
                want: true,
            },
            TestCase {
                query_str: "$.aaaa.bbbb.",
                want: false,
            },
        ];
        for t in test_cases {
            let got = is_valid_query_str(t.query_str.as_bytes());
            assert_eq!(t.want, got);
        }
    }
}
<commit_msg>refactor(set_queries): avoid duplicate code<commit_after>use std::cmp;
use fnv::FnvHashMap;
use error::{Error, ErrorKind};
use result::Result;
use utf8::{DOLLAR, DOT};

const ROOT_QUERY_STR_OFFSET: usize = 2;

#[derive(Debug)]
pub struct Query<'a> {
    pub i: usize,
    pub ri: usize,
    pub target: bool,
    pub children: Option<FnvHashMap<&'a [u8], Query<'a>>>,
}

/// A pattern tree associated with the queries
pub struct QueryTree<'a> {
    pub root: FnvHashMap<&'a [u8], Query<'a>>,
    pub num_queries: usize,
    pub max_depth: usize,
    pub num_nodes: usize,
}

impl<'a> QueryTree<'a> {
    pub fn new<S: ?Sized + AsRef<[u8]>>(queries: &[&'a S]) -> Result<Self> {
        let mut root = FnvHashMap::default();
        let mut level = 0;
        let mut qi = 0;

        for (ri, s) in queries.into_iter().map(|s| (*s).as_ref()).enumerate() {
            if !is_valid_query_str(s) {
                return Err(Error::from(ErrorKind::InvalidQuery));
            }

            let l = set_queries(&mut root, &s[ROOT_QUERY_STR_OFFSET..], &mut qi, ri);
            level = cmp::max(level, l);
        }

        Ok(Self {
            root,
            num_queries: queries.len(),
            max_depth: level,
            num_nodes: qi,
        })
    }
}

#[inline]
fn is_valid_query_str(query_str: &[u8]) -> bool {
    if query_str.len() < ROOT_QUERY_STR_OFFSET + 1 || query_str[0] != DOLLAR || query_str[1] != DOT {
        return false;
    }
    let mut s = ROOT_QUERY_STR_OFFSET - 1;
    for i in s + 1..query_str.len() {
        if query_str[i] != DOT {
            continue;
        }
        if i == s + 1 || i == query_str.len() - 1 {
            return false;
        }
        s = i;
    }
    true
}

#[inline]
fn set_queries<'a>(queries: &mut FnvHashMap<&'a [u8], Query<'a>>, s: &'a [u8], qi: &mut usize, ri: usize) -> usize {
    let j = s.iter().position(|&c| c == DOT).unwrap_or(s.len());
    let (t, u) = s.split_at(j);

    let query = queries.entry(t).or_insert_with(|| {
        let query = Query {
            i: *qi,
            ri: ri,
            target: false,
            children: None,
        };
        *qi += 1;
        query
    });

    if u.len() > 1 {
        // The remaining segments are exist
        let children = query.children.get_or_insert(FnvHashMap::default());
        set_queries(children, &u[1..], qi, ri) + 1
    } else {
        query.target = true; // mark the node as a target node
        1
    }
}

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

    #[test]
    fn test_is_valid_query_str() {
        struct TestCase<'a> {
            query_str: &'a str,
            want: bool,
        }
        let test_cases = vec![
            TestCase {
                query_str: "",
                want: false,
            },
            TestCase {
                query_str: "$",
                want: false,
            },
            TestCase {
                query_str: "$.",
                want: false,
            },
            TestCase {
                query_str: "$..",
                want: false,
            },
            TestCase {
                query_str: "a.a",
                want: false,
            },
            TestCase {
                query_str: "$aa",
                want: false,
            },
            TestCase {
                query_str: "$.a",
                want: true,
            },
            TestCase {
                query_str: "$.aaaa",
                want: true,
            },
            TestCase {
                query_str: "$.aaaa.",
                want: false,
            },
            TestCase {
                query_str: "$.aaaa.b",
                want: true,
            },
            TestCase {
                query_str: "$.aaaa.bbbb",
                want: true,
            },
            TestCase {
                query_str: "$.aaaa.bbbb.",
                want: false,
            },
        ];
        for t in test_cases {
            let got = is_valid_query_str(t.query_str.as_bytes());
            assert_eq!(t.want, got);
        }
    }
}
<|endoftext|>


<commit_before>//! A queue-backed exclusive data lock.
//!
//
// * It is unclear how many of the unsafe methods within need actually remain
//   unsafe.

use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::cell::UnsafeCell;
use futures::{Future, Poll, Canceled};
use futures::sync::oneshot;
use crossbeam::sync::SegQueue;

 // Allows access to the data contained within a lock just like a mutex guard.
pub struct Guard<T> {
    lock: Qutex<T>,
}

impl<T> Deref for Guard<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.lock.inner.cell.get() }
    }
}

impl<T> DerefMut for Guard<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.lock.inner.cell.get() }
    }
}

impl<T> Drop for Guard<T> {
    fn drop(&mut self) {
        unsafe { self.lock.unlock().expect("Error dropping Guard") };
    }
}

pub struct FutureGuard<T> {
    lock: Option<Qutex<T>>,
    rx: oneshot::Receiver<()>,
}

impl<T> FutureGuard<T> {
    fn new(lock: Qutex<T>, rx: oneshot::Receiver<()>) -> FutureGuard<T> {
        FutureGuard {
            lock: Some(lock),
            rx: rx,
        }
    }

    pub fn wait(self) -> Result<Guard<T>, Canceled> {
        <Self as Future>::wait(self)
    }
}

impl<T> Future for FutureGuard<T> {
    type Item = Guard<T>;
    type Error = Canceled;

    #[inline]
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.lock.is_some() {
            unsafe { self.lock.as_ref().unwrap().process_queue()
                .expect("Error polling FutureGuard"); }

            match self.rx.poll() {
                Ok(status) => Ok(status.map(|_| {
                    Guard { lock: self.lock.take().unwrap() }
                })),
                Err(e) => Err(e.into()),
            }
        } else {
            ///// [KEEPME]:
            // Err("FutureGuard::poll: Task already completed.".into())
            panic!("FutureGuard::poll: Task already completed.");
        }
    }
}

pub struct Request {
    tx: oneshot::Sender<()>,
    // wait_event: Option<Event>,
}

impl Request {
    pub fn new(tx: oneshot::Sender<()>) -> Request {
        Request { tx: tx }
    }
}

struct Inner<T> {
    // TODO: Convert to `AtomicBool` if no additional states are needed:
    state: AtomicUsize,
    cell: UnsafeCell<T>,
    queue: SegQueue<Request>,
}

impl<T> From<T> for Inner<T> {
    #[inline]
    fn from(val: T) -> Inner<T> {
        Inner {
            state: AtomicUsize::new(0),
            cell: UnsafeCell::new(val),
            queue: SegQueue::new(),
        }
    }
}

unsafe impl<T: Send> Send for Inner<T> {}
unsafe impl<T: Send> Sync for Inner<T> {}

/// A queue-backed exclusive data lock.
pub struct Qutex<T> {
    inner: Arc<Inner<T>>,
}

impl<T> Qutex<T> {
    /// Creates and returns a new `Qutex`.
    #[inline]
    pub fn new(val: T) -> Qutex<T> {
        Qutex {
            inner: Arc::new(Inner::from(val)),
        }
    }

    /// Returns a new `FutureGuard` which can be used as a future and will
    /// resolve into a `Guard`.
    pub fn lock(&self) -> FutureGuard<T> {
        let (tx, rx) = oneshot::channel();
        // self.inner.queue.push(Request { tx: tx, wait_event: None });
        // self.inner.queue.push(Request { tx: tx });
        unsafe { self.push_request(Request::new(tx)); }
        // FutureGuard { lock: Some((*self).clone()), rx: rx }
        FutureGuard::new((*self).clone(), rx)
    }

    /// Pushes a lock request onto the queue.
    ///
    //
    // TODO: Evaluate unsafeness.
    //
    #[inline]
    pub unsafe fn push_request(&self, req: Request) {
        self.inner.queue.push(req);
    }

    /// Returns a mutable reference to the inner `Vec` if there are currently
    /// no other copies of this `Qutex`.
    ///
    /// Since this call borrows the inner lock mutably, no actual locking needs to
    /// take place---the mutable borrow statically guarantees no locks exist.
    ///
    #[inline]
    pub fn get_mut(&mut self) -> Option<&mut T> {
        Arc::get_mut(&mut self.inner).map(|inn| unsafe { &mut *inn.cell.get() })
    }

    /// Returns a reference to the inner value.
    ///
    /// This is frought with potential peril.
    ///
    #[inline]
    pub fn as_ptr(&self) -> *const T {
        self.inner.cell.get()
    }

    /// Returns a mutable reference to the inner value.
    ///
    /// Drinking water from the tap in 1850's London would be safer.
    ///
    #[inline]
    pub fn as_mut_ptr(&self) -> *mut T {
        self.inner.cell.get()
    }

    /// Pops the next lock request in the queue if this lock is unlocked.
    //
    // TODO:
    // * Determine if this needs to be unsafe.
    // * This is currently public/unsafe due to 'derivers' (aka. sub-types).
    // * Consider removing unsafe qualifier.
    //   - If this imposes a performance burden, create a 'safe' version with
    //      necessary runtime checks
    // * Return proper error type
    pub unsafe fn process_queue(&self) -> Result<(), &'static str> {
        match self.inner.state.compare_and_swap(0, 1, SeqCst) {
            // Unlocked:
            0 => {
                if let Some(req) = self.inner.queue.try_pop() {
                    req.tx.send(()).map_err(|_| "Qutex queue has been dropped")
                } else {
                    self.inner.state.store(0, SeqCst);
                    Ok(())
                }
            },
            // Already locked, leave it alone:
            1 => Ok(()),
            // Something else:
            n => panic!("Qutex::process_queue: inner.state: {}.", n),
        }
    }

    /// Unlocks this lock and wakes up the next task in the queue.
    //
    // TODO:
    // * Evaluate unsafeness.
    // * Return proper error type
    pub unsafe fn unlock(&self) -> Result<(), &'static str> {
        // TODO: Consider using `Ordering::Release`.
        self.inner.state.store(0, SeqCst);
        self.process_queue()
    }
}

impl<T> From<T> for Qutex<T> {
    #[inline]
    fn from(val: T) -> Qutex<T> {
        Qutex::new(val)
    }
}

impl<T> Clone for Qutex<T> {
    #[inline]
    fn clone(&self) -> Qutex<T> {
        Qutex {
            inner: self.inner.clone(),
        }
    }
}

#[cfg(test)]
// Woefully incomplete:
mod tests {
    #![allow(unused_variables, unused_imports, dead_code)]
    use super::*;

    #[test]
    fn simple() {
        let val = Qutex::from(999i32);

        println!("Reading val...");
        {
            let future_guard = val.lock();
            let guard = future_guard.wait().unwrap();
            println!("val: {}", *guard);
        }

        println!("Storing new val...");
        {
            let future_guard = val.lock();
            let mut guard = future_guard.wait().unwrap();
            *guard = 5;
        }

        println!("Reading val...");
        {
            let future_guard = val.lock();
            let guard = future_guard.wait().unwrap();
            println!("val: {}", *guard);
        }
    }

    #[test]
    // TODO: INCOMPLETE: Actually make this concurrent.
    fn concurrent() {
        let val = Qutex::from(10000i32);

        let fg0 = val.lock();
        let fg1 = val.lock();
        let fg2 = val.lock();

        println!("Reading val 0...");
        {
            let guard = fg0.wait().unwrap();
            println!("val: {}", *guard);
        }

        println!("Reading val 1...");
        {
            let guard = fg1.wait().unwrap();
            println!("val: {}", *guard);
        }

        println!("Reading val 2...");
        {
            let guard = fg2.wait().unwrap();
            println!("val: {}", *guard);
        }
    }
}<commit_msg>Locking now consumes qutex.<commit_after>//! A queue-backed exclusive data lock.
//!
//
// * It is unclear how many of the unsafe methods within need actually remain
//   unsafe.

use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::cell::UnsafeCell;
use futures::{Future, Poll, Canceled};
use futures::sync::oneshot;
use crossbeam::sync::SegQueue;

 // Allows access to the data contained within a lock just like a mutex guard.
pub struct Guard<T> {
    lock: Qutex<T>,
}

impl<T> Deref for Guard<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.lock.inner.cell.get() }
    }
}

impl<T> DerefMut for Guard<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.lock.inner.cell.get() }
    }
}

impl<T> Drop for Guard<T> {
    fn drop(&mut self) {
        unsafe { self.lock.unlock().expect("Error dropping Guard") };
    }
}

pub struct FutureGuard<T> {
    lock: Option<Qutex<T>>,
    rx: oneshot::Receiver<()>,
}

impl<T> FutureGuard<T> {
    fn new(lock: Qutex<T>, rx: oneshot::Receiver<()>) -> FutureGuard<T> {
        FutureGuard {
            lock: Some(lock),
            rx: rx,
        }
    }

    pub fn wait(self) -> Result<Guard<T>, Canceled> {
        <Self as Future>::wait(self)
    }
}

impl<T> Future for FutureGuard<T> {
    type Item = Guard<T>;
    type Error = Canceled;

    #[inline]
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.lock.is_some() {
            unsafe { self.lock.as_ref().unwrap().process_queue()
                .expect("Error polling FutureGuard"); }

            match self.rx.poll() {
                Ok(status) => Ok(status.map(|_| {
                    Guard { lock: self.lock.take().unwrap() }
                })),
                Err(e) => Err(e.into()),
            }
        } else {
            ///// [KEEPME]:
            // Err("FutureGuard::poll: Task already completed.".into())
            panic!("FutureGuard::poll: Task already completed.");
        }
    }
}

pub struct Request {
    tx: oneshot::Sender<()>,
    // wait_event: Option<Event>,
}

impl Request {
    pub fn new(tx: oneshot::Sender<()>) -> Request {
        Request { tx: tx }
    }
}

struct Inner<T> {
    // TODO: Convert to `AtomicBool` if no additional states are needed:
    state: AtomicUsize,
    cell: UnsafeCell<T>,
    queue: SegQueue<Request>,
}

impl<T> From<T> for Inner<T> {
    #[inline]
    fn from(val: T) -> Inner<T> {
        Inner {
            state: AtomicUsize::new(0),
            cell: UnsafeCell::new(val),
            queue: SegQueue::new(),
        }
    }
}

unsafe impl<T: Send> Send for Inner<T> {}
unsafe impl<T: Send> Sync for Inner<T> {}

/// A queue-backed exclusive data lock.
pub struct Qutex<T> {
    inner: Arc<Inner<T>>,
}

impl<T> Qutex<T> {
    /// Creates and returns a new `Qutex`.
    #[inline]
    pub fn new(val: T) -> Qutex<T> {
        Qutex {
            inner: Arc::new(Inner::from(val)),
        }
    }

    /// Returns a new `FutureGuard` which can be used as a future and will
    /// resolve into a `Guard`.
    pub fn lock(self) -> FutureGuard<T> {
        let (tx, rx) = oneshot::channel();
        // self.inner.queue.push(Request { tx: tx, wait_event: None });
        // self.inner.queue.push(Request { tx: tx });
        unsafe { self.push_request(Request::new(tx)); }
        // FutureGuard { lock: Some((*self).clone()), rx: rx }
        FutureGuard::new(self, rx)
    }

    /// Pushes a lock request onto the queue.
    ///
    //
    // TODO: Evaluate unsafe-ness.
    //
    #[inline]
    pub unsafe fn push_request(&self, req: Request) {
        self.inner.queue.push(req);
    }

    /// Returns a mutable reference to the inner `Vec` if there are currently
    /// no other copies of this `Qutex`.
    ///
    /// Since this call borrows the inner lock mutably, no actual locking needs to
    /// take place---the mutable borrow statically guarantees no locks exist.
    ///
    #[inline]
    pub fn get_mut(&mut self) -> Option<&mut T> {
        Arc::get_mut(&mut self.inner).map(|inn| unsafe { &mut *inn.cell.get() })
    }

    /// Returns a reference to the inner value.
    ///
    /// This is frought with potential peril.
    ///
    #[inline]
    pub fn as_ptr(&self) -> *const T {
        self.inner.cell.get()
    }

    /// Returns a mutable reference to the inner value.
    ///
    /// Drinking water from the tap in 1850's London would be safer.
    ///
    #[inline]
    pub fn as_mut_ptr(&self) -> *mut T {
        self.inner.cell.get()
    }

    /// Pops the next lock request in the queue if this lock is unlocked.
    //
    // TODO:
    // * Determine if this needs to be unsafe.
    // * This is currently public/unsafe due to 'derivers' (aka. sub-types).
    // * Consider removing unsafe qualifier.
    // * Return proper error type.
    pub unsafe fn process_queue(&self) -> Result<(), &'static str> {
        match self.inner.state.compare_and_swap(0, 1, SeqCst) {
            // Unlocked:
            0 => {
                if let Some(req) = self.inner.queue.try_pop() {
                    req.tx.send(()).map_err(|_| "Qutex queue has been dropped")
                } else {
                    self.inner.state.store(0, SeqCst);
                    Ok(())
                }
            },
            // Already locked, leave it alone:
            1 => Ok(()),
            // Something else:
            n => panic!("Qutex::process_queue: inner.state: {}.", n),
        }
    }

    /// Unlocks this lock and wakes up the next task in the queue.
    //
    // TODO:
    // * Evaluate unsafe-ness.
    // * Return proper error type
    pub unsafe fn unlock(&self) -> Result<(), &'static str> {
        // TODO: Consider using `Ordering::Release`.
        self.inner.state.store(0, SeqCst);
        self.process_queue()
    }
}

impl<T> From<T> for Qutex<T> {
    #[inline]
    fn from(val: T) -> Qutex<T> {
        Qutex::new(val)
    }
}

impl<T> Clone for Qutex<T> {
    #[inline]
    fn clone(&self) -> Qutex<T> {
        Qutex {
            inner: self.inner.clone(),
        }
    }
}

#[cfg(test)]
// Woefully incomplete:
mod tests {
    #![allow(unused_variables, unused_imports, dead_code)]
    use super::*;

    #[test]
    fn simple() {
        let val = Qutex::from(999i32);

        println!("Reading val...");
        {
            let future_guard = val.clone().lock();
            let guard = future_guard.wait().unwrap();
            println!("val: {}", *guard);
        }

        println!("Storing new val...");
        {
            let future_guard = val.clone().lock();
            let mut guard = future_guard.wait().unwrap();
            *guard = 5;
        }

        println!("Reading val...");
        {
            let future_guard = val.clone().lock();
            let guard = future_guard.wait().unwrap();
            println!("val: {}", *guard);
        }
    }

    #[test]
    // TODO: INCOMPLETE: Actually make this concurrent.
    fn concurrent() {
        let val = Qutex::from(10000i32);

        let fg0 = val.clone().lock();
        let fg1 = val.clone().lock();
        let fg2 = val.clone().lock();

        println!("Reading val 0...");
        {
            let guard = fg0.wait().unwrap();
            println!("val: {}", *guard);
        }

        println!("Reading val 1...");
        {
            let guard = fg1.wait().unwrap();
            println!("val: {}", *guard);
        }

        println!("Reading val 2...");
        {
            let guard = fg2.wait().unwrap();
            println!("val: {}", *guard);
        }
    }
}<|endoftext|>