<commit_before>use super::rpc::codec::RpcCodec;

use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::io::{Error, ErrorKind};
use std::net::SocketAddr;

use tokio::net::TcpListener;
use tokio_codec::Framed;
use tokio::prelude::*;

use blockchain::Blockchain;
use producer::Producer;
use net::peer::*;
use net::rpc::*;
use fut_util::*;

pub fn start(addr: SocketAddr, blockchain: Arc<Blockchain>, producer: Arc<Option<Producer>>) {
    let listener = TcpListener::bind(&addr).unwrap();
    info!("Server binded to {:?}", &addr);
    let server = listener.incoming().for_each(move |socket| {
        let addr = socket.peer_addr().unwrap();
        info!("[{}] Accepted connection", addr);

        let frame = Framed::new(socket, RpcCodec::new());
        let hs = frame.into_future()
                        .map_err(|(e, _)| e)
                        .and_then(|(data, frame)| {
                            if let Some(data) = data { return Ok((data, frame)) }
                            Err(Error::from(ErrorKind::UnexpectedEof))
                        });
        let hs = hs.and_then(|(data, frame)| {
            if data.id != 0 {
                return Err(Error::new(ErrorKind::InvalidData, "id must be 0"))
            }
            if let Some(msg) = data.msg {
                let peer_type = match msg {
                    RpcMsg::Handshake(peer_type) => peer_type,
                    _ => return Err(Error::new(ErrorKind::InvalidData, "expected handshake msg"))
                };
                Ok((peer_type, frame))
            } else {
                Err(Error::new(ErrorKind::InvalidData, "expected handshake msg"))
            }
        });

        let blockchain = Arc::clone(&blockchain);
        let producer = Arc::clone(&producer);
        let client = hs.and_then(move |(peer_type, frame)| {
            let peer = Peer::new(peer_type, addr, frame);
            debug!("Handshake from client completed: {:?}", peer);
            peer.get_sender().send_untracked(RpcPayload {
                id: 0,
                msg: None
            });
            handle_peer(peer, blockchain, producer);
            Ok(())
        });

        ::tokio::spawn(client.map_err(move |e| {
            debug!("[{}] Handshake error: {:?}", addr, e);
        }));
        Ok(())
    }).map_err(|err| {
        error!("Server accept error: {:?}", err);
    });
    ::tokio::spawn(server);
}

fn handle_peer(peer: Peer, blockchain: Arc<Blockchain>, producer: Arc<Option<Producer>>) {
    macro_rules! quick_send {
        ($sender:expr, $rpc:expr, $msg:expr) => {
            $sender.send_untracked(RpcPayload { id: $rpc.id, msg: Some($msg) });
        };
        ($sender:expr, $rpc:expr) => {
            $sender.send_untracked(RpcPayload { id: $rpc.id, msg: None });
        };
    }

    let (tx, rx) = {
        let (tx, rx) = channel::unbounded();
        (tx, rx.map_err(|_| {
            Error::new(ErrorKind::Other, "rx error")
        }))
    };

    let addr = peer.addr;
    let force_close = Arc::new(AtomicBool::new(false));
    let sender = peer.get_sender();
    ::tokio::spawn(ZipEither::new(peer, rx).take_while({
        let force_close = Arc::clone(&force_close);
        move |_| {
            Ok(!force_close.load(Ordering::Acquire))
        }
    }).for_each(move |(rpc, _)| {
        if let Some(rpc) = rpc {
            if let Some(msg) = rpc.msg {
                match msg {
                    RpcMsg::Event(evt) => {
                        if let Some(producer) = &*producer {
                            match evt {
                                RpcEvent::Block(block) => {
                                    let _ = producer.add_block(block);
                                },
                                RpcEvent::Tx(tx) => {
                                    let _ = producer.add_tx(tx);
                                }
                            }
                        }
                    },
                    RpcMsg::Broadcast(tx) => {
                        if let Some(producer) = &*producer {
                            match producer.add_tx(tx) {
                                Ok(_) => {
                                    quick_send!(sender, rpc);
                                },
                                Err(s) => {
                                    quick_send!(sender, rpc, RpcMsg::Error(s));
                                }
                            }
                        }
                    },
                    RpcMsg::Properties(var) => {
                        match var.request() {
                            Some(_) => {
                                let props = blockchain.get_properties();
                                quick_send!(sender, rpc, RpcMsg::Properties(RpcVariant::Res(props)));
                            },
                            None => {
                                warn!("[{}] Property responses not supported", addr);
                            }
                        }
                    },
                    RpcMsg::Block(var) => {
                        match var.request() {
                            Some(height) => {
                                let block = match blockchain.get_block(*height) {
                                    Some(block) => Some((&*block).clone()),
                                    None => None
                                };
                                quick_send!(sender, rpc, RpcMsg::Block(RpcVariant::Res(block)));
                            },
                            None => {
                                warn!("[{}] Block responses not supported", addr);
                            }
                        }
                    },
                    RpcMsg::Balance(var) => {
                        match var.request() {
                            Some(addr) => {
                                let bal = blockchain.get_balance(addr);
                                quick_send!(sender, rpc, RpcMsg::Balance(RpcVariant::Res(bal)));
                            },
                            None => {
                                warn!("[{}] Balance responses not supported", addr);
                            }
                        }
                    },
                    RpcMsg::TotalFee(var) => {
                        match var.request() {
                            Some(addr) => {
                                let fee = blockchain.get_total_fee(addr);
                                match fee {
                                    Some(fee) => {
                                        quick_send!(sender, rpc, RpcMsg::TotalFee(RpcVariant::Res(fee)));
                                    },
                                    None => {
                                        let err = "failed to retrieve total fee".to_string();
                                        quick_send!(sender, rpc, RpcMsg::Error(err));
                                    }
                                }
                            },
                            None => {
                                warn!("[{}] Total fee responses not supported", addr);
                            }
                        }
                    },
                    _ => {
                        warn!("[{}] Invalid rpc message sent from peer", addr);
                        force_close.store(true, Ordering::Release);
                        tx.send(())
                    }
                }
            }
        }
        Ok(())
    }).and_then(move |_| {
        warn!("[{}] Client disconnected", addr);
        Ok(())
    }).map_err(move |e| {
        debug!("[{}] Error handling frame from client: {:?}", addr, e);
    }));
}
<commit_msg>Remove warnings when receiving response messages<commit_after>use super::rpc::codec::RpcCodec;

use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::io::{Error, ErrorKind};
use std::net::SocketAddr;

use tokio::net::TcpListener;
use tokio_codec::Framed;
use tokio::prelude::*;

use blockchain::Blockchain;
use producer::Producer;
use net::peer::*;
use net::rpc::*;
use fut_util::*;

pub fn start(addr: SocketAddr, blockchain: Arc<Blockchain>, producer: Arc<Option<Producer>>) {
    let listener = TcpListener::bind(&addr).unwrap();
    info!("Server binded to {:?}", &addr);
    let server = listener.incoming().for_each(move |socket| {
        let addr = socket.peer_addr().unwrap();
        info!("[{}] Accepted connection", addr);

        let frame = Framed::new(socket, RpcCodec::new());
        let hs = frame.into_future()
                        .map_err(|(e, _)| e)
                        .and_then(|(data, frame)| {
                            if let Some(data) = data { return Ok((data, frame)) }
                            Err(Error::from(ErrorKind::UnexpectedEof))
                        });
        let hs = hs.and_then(|(data, frame)| {
            if data.id != 0 {
                return Err(Error::new(ErrorKind::InvalidData, "id must be 0"))
            }
            if let Some(msg) = data.msg {
                let peer_type = match msg {
                    RpcMsg::Handshake(peer_type) => peer_type,
                    _ => return Err(Error::new(ErrorKind::InvalidData, "expected handshake msg"))
                };
                Ok((peer_type, frame))
            } else {
                Err(Error::new(ErrorKind::InvalidData, "expected handshake msg"))
            }
        });

        let blockchain = Arc::clone(&blockchain);
        let producer = Arc::clone(&producer);
        let client = hs.and_then(move |(peer_type, frame)| {
            let peer = Peer::new(peer_type, addr, frame);
            debug!("Handshake from client completed: {:?}", peer);
            peer.get_sender().send_untracked(RpcPayload {
                id: 0,
                msg: None
            });
            handle_peer(peer, blockchain, producer);
            Ok(())
        });

        ::tokio::spawn(client.map_err(move |e| {
            debug!("[{}] Handshake error: {:?}", addr, e);
        }));
        Ok(())
    }).map_err(|err| {
        error!("Server accept error: {:?}", err);
    });
    ::tokio::spawn(server);
}

fn handle_peer(peer: Peer, blockchain: Arc<Blockchain>, producer: Arc<Option<Producer>>) {
    macro_rules! quick_send {
        ($sender:expr, $rpc:expr, $msg:expr) => {
            $sender.send_untracked(RpcPayload { id: $rpc.id, msg: Some($msg) });
        };
        ($sender:expr, $rpc:expr) => {
            $sender.send_untracked(RpcPayload { id: $rpc.id, msg: None });
        };
    }

    let (tx, rx) = {
        let (tx, rx) = channel::unbounded();
        (tx, rx.map_err(|_| {
            Error::new(ErrorKind::Other, "rx error")
        }))
    };

    let addr = peer.addr;
    let force_close = Arc::new(AtomicBool::new(false));
    let sender = peer.get_sender();
    ::tokio::spawn(ZipEither::new(peer, rx).take_while({
        let force_close = Arc::clone(&force_close);
        move |_| {
            Ok(!force_close.load(Ordering::Acquire))
        }
    }).for_each(move |(rpc, _)| {
        if let Some(rpc) = rpc {
            if let Some(msg) = rpc.msg {
                match msg {
                    RpcMsg::Event(evt) => {
                        if let Some(producer) = &*producer {
                            match evt {
                                RpcEvent::Block(block) => {
                                    let _ = producer.add_block(block);
                                },
                                RpcEvent::Tx(tx) => {
                                    let _ = producer.add_tx(tx);
                                }
                            }
                        }
                    },
                    RpcMsg::Broadcast(tx) => {
                        if let Some(producer) = &*producer {
                            match producer.add_tx(tx) {
                                Ok(_) => {
                                    quick_send!(sender, rpc);
                                },
                                Err(s) => {
                                    quick_send!(sender, rpc, RpcMsg::Error(s));
                                }
                            }
                        }
                    },
                    RpcMsg::Properties(var) => {
                        if let Some(_) = var.request() {
                            let props = blockchain.get_properties();
                            quick_send!(sender, rpc, RpcMsg::Properties(RpcVariant::Res(props)));
                        }
                    },
                    RpcMsg::Block(var) => {
                        if let Some(height) = var.request() {
                            let block = match blockchain.get_block(*height) {
                                Some(block) => Some((&*block).clone()),
                                None => None
                            };
                            quick_send!(sender, rpc, RpcMsg::Block(RpcVariant::Res(block)));
                        }
                    },
                    RpcMsg::Balance(var) => {
                        if let Some(addr) = var.request() {
                            let bal = blockchain.get_balance(addr);
                            quick_send!(sender, rpc, RpcMsg::Balance(RpcVariant::Res(bal)));
                        }
                    },
                    RpcMsg::TotalFee(var) => {
                        if let Some(addr) = var.request() {
                            let fee = blockchain.get_total_fee(addr);
                            match fee {
                                Some(fee) => {
                                    quick_send!(sender, rpc, RpcMsg::TotalFee(RpcVariant::Res(fee)));
                                },
                                None => {
                                    let err = "failed to retrieve total fee".to_string();
                                    quick_send!(sender, rpc, RpcMsg::Error(err));
                                }
                            }
                        }
                    },
                    _ => {
                        warn!("[{}] Invalid rpc message sent from peer", addr);
                        force_close.store(true, Ordering::Release);
                        tx.send(())
                    }
                }
            }
        }
        Ok(())
    }).and_then(move |_| {
        warn!("[{}] Client disconnected", addr);
        Ok(())
    }).map_err(move |e| {
        debug!("[{}] Error handling frame from client: {:?}", addr, e);
    }));
}
<|endoftext|>


<commit_before>#![cfg(feature = "std")]
use futures::io::Window;

#[test]
fn set() {
    let mut buffer = Window::new(&[1, 2, 3]);
    buffer.set(..3);
    buffer.set(3..3);
    buffer.set(3..=2); // == 3..3
    buffer.set(0..2);

    assert_eq!(buffer.as_ref(), &[1, 2]);
}

#[test]
#[should_panic]
fn set_panic_out_of_bounds() {
    let mut buffer = Window::new(&[1, 2, 3]);
    buffer.set(2..4);
}

#[test]
#[should_panic]
fn set_panic_start_is_greater_than_end() {
    let mut buffer = Window::new(&[1, 2, 3]);
    buffer.set(3..2);
}
<commit_msg>Fix clippy warnings<commit_after>#![cfg(feature = "std")]
#![allow(clippy::reversed_empty_ranges)] // This is intentional.

use futures::io::Window;

#[test]
fn set() {
    let mut buffer = Window::new(&[1, 2, 3]);
    buffer.set(..3);
    assert_eq!(buffer.as_ref(), &[1, 2, 3]);
    buffer.set(3..3);
    assert_eq!(buffer.as_ref(), &[]);
    buffer.set(3..=2); // == 3..3
    assert_eq!(buffer.as_ref(), &[]);
    buffer.set(0..2);
    assert_eq!(buffer.as_ref(), &[1, 2]);
}

#[test]
#[should_panic]
fn set_panic_out_of_bounds() {
    let mut buffer = Window::new(&[1, 2, 3]);
    buffer.set(2..4);
}

#[test]
#[should_panic]
fn set_panic_start_is_greater_than_end() {
    let mut buffer = Window::new(&[1, 2, 3]);
    buffer.set(3..2);
}
<|endoftext|>


<commit_before>use bls::Keypair;
use clap::{App, Arg, SubCommand};
use slog::{debug, info, o, Drain};
use std::path::PathBuf;
use validator_client::Config as ValidatorClientConfig;
use types::test_utils::generate_deterministic_keypair;

fn main() {
    // Logging
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::CompactFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();
    let log = slog::Logger::root(drain, o!());

    // CLI
    let matches = App::new("Lighthouse Accounts Manager")
        .version("0.0.1")
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Eth 2.0 Accounts Manager")
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .value_name("DIR")
                .help("Data directory for keys and databases.")
                .takes_value(true),
        )
        .subcommand(
            SubCommand::with_name("generate")
                .about("Generates a new validator private key")
                .version("0.0.1")
                .author("Sigma Prime <contact@sigmaprime.io>"),
        )
        .subcommand(
            SubCommand::with_name("generate_deterministic")
                .about("Generates a deterministic validator private key FOR TESTING")
                .version("0.0.1")
                .author("Sigma Prime <contact@sigmaprime.io>")
                .arg(
                    Arg::with_name("validator index")
                        .long("index")
                        .short("i")
                        .value_name("index")
                        .help("The index of the validator, for which the test key is generated")
                        .takes_value(true)
                        .required(true)
                )
        )
        .get_matches();

    let config = ValidatorClientConfig::parse_args(&matches, &log)
        .expect("Unable to build a configuration for the account manager.");

    // Log configuration
    info!(log, "";
          "data_dir" => &config.data_dir.to_str());

    match matches.subcommand() {
        ("generate", Some(_gen_m)) => {
            let keypair = Keypair::random();
            let key_path: PathBuf = config
                .save_key(&keypair)
                .expect("Unable to save newly generated private key.");
            debug!(
                log,
                "Keypair generated {:?}, saved to: {:?}",
                keypair.identifier(),
                key_path.to_string_lossy()
            );
        },
        ("generate_deterministic", Some(gen_d_matches)) => {
            let validator_index = gen_d_matches
                .value_of("validator index")
                .expect("Validator index required.")
                .parse::<u64>()
                .expect("Invalid validator index.") as usize;
            let keypair = generate_deterministic_keypair(validator_index);
            let key_path: PathBuf = config
                .save_key(&keypair)
                .expect("Unable to save newly generated deterministic private key.");
            debug!(
                log,
                "Deterministic Keypair generated {:?}, saved to: {:?}",
                keypair.identifier(),
                key_path.to_string_lossy()
            );
        },
        _ => panic!(
            "The account manager must be run with a subcommand. See help for more information."
        ),
    }
}
<commit_msg>Fixed cargo fmt.<commit_after>use bls::Keypair;
use clap::{App, Arg, SubCommand};
use slog::{debug, info, o, Drain};
use std::path::PathBuf;
use types::test_utils::generate_deterministic_keypair;
use validator_client::Config as ValidatorClientConfig;

fn main() {
    // Logging
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::CompactFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();
    let log = slog::Logger::root(drain, o!());

    // CLI
    let matches = App::new("Lighthouse Accounts Manager")
        .version("0.0.1")
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Eth 2.0 Accounts Manager")
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .value_name("DIR")
                .help("Data directory for keys and databases.")
                .takes_value(true),
        )
        .subcommand(
            SubCommand::with_name("generate")
                .about("Generates a new validator private key")
                .version("0.0.1")
                .author("Sigma Prime <contact@sigmaprime.io>"),
        )
        .subcommand(
            SubCommand::with_name("generate_deterministic")
                .about("Generates a deterministic validator private key FOR TESTING")
                .version("0.0.1")
                .author("Sigma Prime <contact@sigmaprime.io>")
                .arg(
                    Arg::with_name("validator index")
                        .long("index")
                        .short("i")
                        .value_name("index")
                        .help("The index of the validator, for which the test key is generated")
                        .takes_value(true)
                        .required(true),
                ),
        )
        .get_matches();

    let config = ValidatorClientConfig::parse_args(&matches, &log)
        .expect("Unable to build a configuration for the account manager.");

    // Log configuration
    info!(log, "";
          "data_dir" => &config.data_dir.to_str());

    match matches.subcommand() {
        ("generate", Some(_gen_m)) => {
            let keypair = Keypair::random();
            let key_path: PathBuf = config
                .save_key(&keypair)
                .expect("Unable to save newly generated private key.");
            debug!(
                log,
                "Keypair generated {:?}, saved to: {:?}",
                keypair.identifier(),
                key_path.to_string_lossy()
            );
        }
        ("generate_deterministic", Some(gen_d_matches)) => {
            let validator_index = gen_d_matches
                .value_of("validator index")
                .expect("Validator index required.")
                .parse::<u64>()
                .expect("Invalid validator index.") as usize;
            let keypair = generate_deterministic_keypair(validator_index);
            let key_path: PathBuf = config
                .save_key(&keypair)
                .expect("Unable to save newly generated deterministic private key.");
            debug!(
                log,
                "Deterministic Keypair generated {:?}, saved to: {:?}",
                keypair.identifier(),
                key_path.to_string_lossy()
            );
        }
        _ => panic!(
            "The account manager must be run with a subcommand. See help for more information."
        ),
    }
}
<|endoftext|>


<commit_before>
extern crate ndarray;
extern crate ndarray_odeint;

use ndarray::*;
use ndarray_odeint::*;

fn main() {
    let dt = 0.01;
    let eom = model::Lorenz63::default();
    let teo = explicit::rk4(eom, dt);
    let mut buf = explicit::RK4Buffer::new_buffer(&teo);
    let mut x: Array1<f64> = arr1(&[1.0, 0.0, 0.0]);
    for _ in 0..100_000_000 {
        teo.iterate_buf(&mut x, &mut buf);
    }
}
<commit_msg>Fix examples/bench<commit_after>
extern crate ndarray;
extern crate ndarray_odeint;

use ndarray::*;
use ndarray_odeint::*;

fn main() {
    let dt = 0.01;
    let eom = model::Lorenz63::default();
    let teo = explicit::rk4(eom, dt);
    let mut buf = teo.new_buffer();
    let mut x: Array1<f64> = arr1(&[1.0, 0.0, 0.0]);
    for _ in 0..100_000_000 {
        teo.iterate(&mut x, &mut buf);
    }
}
<|endoftext|>


<commit_before>//! Action types.
//!
//! Applications should not access the `action` module directly. Instead, they
//! should use the appropriate `Client` method to construct an action. For
//! example, the method `post_to_database` constructs a `PostToDatabase`
//! action.

macro_rules! impl_action_public_methods {
    ($action_output:ty) => {
        /// Sends the action request and waits for the response.
        pub fn run(self) -> Result<$action_output, Error> {
            action::run_action(self)
        }
    }
}

macro_rules! make_couchdb_error {
    ($error_variant:ident, $response:expr) => {
        Error::$error_variant(Some(try!($response.decode_json::<ErrorResponse>())))
    }
}

#[macro_use]
mod test_macro;

mod delete_database;
mod delete_document;
mod get_all_databases;
mod get_database;
mod get_document;
mod get_view;
mod head_database;
mod head_document;
mod post_to_database;
mod put_database;
mod put_document;

pub use self::delete_database::DeleteDatabase;
pub use self::delete_document::DeleteDocument;
pub use self::get_all_databases::GetAllDatabases;
pub use self::get_database::GetDatabase;
pub use self::get_document::GetDocument;
pub use self::get_view::GetView;
pub use self::head_database::HeadDatabase;
pub use self::head_document::HeadDocument;
pub use self::post_to_database::PostToDatabase;
pub use self::put_database::PutDatabase;
pub use self::put_document::PutDocument;

use hyper;
use serde;
use serde_json;

use Error;
use Revision;
use error::{DecodeErrorKind, TransportKind};

// The Action trait abstracts the machinery for executing CouchDB actions. Types
// implementing the Action trait define only how they construct requests and
// process responses. This separates the action logic from the responsibility of
// sending the request and receiving its response.
trait Action: Sized {
    type Output;
    fn make_request(self) -> Result<Request, Error>;
    fn take_response<R: Response>(response: R) -> Result<Self::Output, Error>;
}

fn run_action<A>(action: A) -> Result<A::Output, Error>
    where A: Action
{
    let action_request = try!(action.make_request());

    let action_response = {
        use std::io::Write;
        let mut hyper_request = try!(hyper::client::Request::new(action_request.method,
                                                                 action_request.uri)
                                         .map_err(|e| Error::Transport(TransportKind::Hyper(e))));
        *hyper_request.headers_mut() = action_request.headers;
        let mut request_stream = try!(hyper_request.start()
                                                   .map_err(|e| {
                                                       Error::Transport(TransportKind::Hyper(e))
                                                   }));
        try!(request_stream.write_all(&action_request.body)
                           .map_err(|e| Error::Transport(TransportKind::Io(e))));
        let hyper_response = try!(request_stream.send().map_err(|e| {
            Error::Transport(TransportKind::Hyper(e))
        }));
        HyperResponse::new(hyper_response)
    };

    A::take_response(action_response)
}

struct Request {
    method: hyper::method::Method,
    uri: hyper::Url,
    headers: hyper::header::Headers,
    body: Vec<u8>,
}

impl Request {
    pub fn new(method: hyper::method::Method, uri: hyper::Url) -> Self {
        Request {
            method: method,
            uri: uri,
            headers: hyper::header::Headers::new(),
            body: Vec::new(),
        }
    }

    #[cfg(test)]
    pub fn method(&self) -> &hyper::method::Method {
        &self.method
    }

    #[cfg(test)]
    pub fn uri(&self) -> &hyper::Url {
        &self.uri
    }

    #[cfg(test)]
    pub fn headers(&self) -> &hyper::header::Headers {
        &self.headers
    }

    pub fn set_body(mut self, body: Vec<u8>) -> Self {
        self.body = body;
        self
    }

    pub fn set_accept_application_json(mut self) -> Self {
        let qitems = {
            use hyper::mime::{Mime, TopLevel, SubLevel};
            vec![hyper::header::qitem(Mime(TopLevel::Application, SubLevel::Json, vec![]))]
        };
        self.headers.set(hyper::header::Accept(qitems));
        self
    }

    pub fn set_content_type_application_json(mut self) -> Self {
        let qitems = {
            use hyper::mime::{Mime, TopLevel, SubLevel};
            Mime(TopLevel::Application, SubLevel::Json, vec![])
        };
        self.headers.set(hyper::header::ContentType(qitems));
        self
    }

    pub fn set_if_match_revision(mut self, rev: Option<&Revision>) -> Self {
        match rev {
            None => self,
            Some(rev) => {
                let etags = new_revision_etags(rev);
                self.headers.set(hyper::header::IfMatch::Items(etags));
                self
            }
        }
    }

    pub fn set_if_none_match_revision(mut self, rev: Option<&Revision>) -> Self {
        match rev {
            None => self,
            Some(rev) => {
                let etags = new_revision_etags(rev);
                self.headers.set(hyper::header::IfNoneMatch::Items(etags));
                self
            }
        }
    }
}

trait Response {

    fn status(&self) -> hyper::status::StatusCode {
        hyper::status::StatusCode::InternalServerError
    }

    fn content_type_must_be_application_json(&self) -> Result<(), Error> {
        Err(Error::NoContentTypeHeader { expected: "application/json" })
    }

    fn decode_json<T: serde::Deserialize>(&mut self) -> Result<T, Error> {
        serde_json::from_str("").map_err(|e| Error::Decode(DecodeErrorKind::Serde { cause: e }))
    }
}

struct HyperResponse {
    hyper_response: hyper::client::Response,
}

impl HyperResponse {
    fn new(hyper_response: hyper::client::Response) -> Self {
        HyperResponse { hyper_response: hyper_response }
    }
}

impl Response for HyperResponse {
    fn status(&self) -> hyper::status::StatusCode {
        self.hyper_response.status
    }

    // Returns an error if the HTTP response doesn't have a Content-Type of
    // `application/json`.
    fn content_type_must_be_application_json(&self) -> Result<(), Error> {
        // FIXME: Test this.
        match self.hyper_response.headers.get::<hyper::header::ContentType>() {
            None => Err(Error::NoContentTypeHeader { expected: "application/json" }),
            Some(content_type) => {
                use hyper::mime::*;
                let exp = hyper::mime::Mime(TopLevel::Application, SubLevel::Json, vec![]);
                let &hyper::header::ContentType(ref got) = content_type;
                if *got != exp {
                    Err(Error::UnexpectedContentTypeHeader {
                        expected: "application/json",
                        got: format!("{}", got),
                    })
                } else {
                    Ok(())
                }
            }
        }
    }

    fn decode_json<T: serde::Deserialize>(&mut self) -> Result<T, Error> {
        serde_json::from_reader::<_, T>(&mut self.hyper_response).map_err(|e| {
            match e {
                serde_json::Error::IoError(e) => Error::Transport(TransportKind::Io(e)),
                _ => Error::Decode(DecodeErrorKind::Serde { cause: e }),
            }
        })
    }
}

// Mock response encapsulating a typical application/json response.
#[cfg(test)]
struct JsonResponse {
    status_code: hyper::status::StatusCode,
    body: String,
}

#[cfg(test)]
impl JsonResponse {
    fn new<T: serde::Serialize>(status_code: hyper::status::StatusCode, body: &T) -> Self {
        JsonResponse {
            status_code: status_code,
            body: serde_json::to_string(&body).unwrap(),
        }
    }
}

#[cfg(test)]
impl Response for JsonResponse {
    fn status(&self) -> hyper::status::StatusCode {
        self.status_code
    }

    fn content_type_must_be_application_json(&self) -> Result<(), Error> {
        Ok(())
    }

    fn decode_json<T: serde::Deserialize>(&mut self) -> Result<T, Error> {
        serde_json::from_str(&self.body)
            .map_err(|e| Error::Decode(DecodeErrorKind::Serde { cause: e }))
    }
}

// Mock response encapsulating a response with no body.
#[cfg(test)]
struct NoContentResponse {
    status_code: hyper::status::StatusCode,
}

#[cfg(test)]
impl NoContentResponse {
    fn new(status_code: hyper::status::StatusCode) -> Self {
        NoContentResponse { status_code: status_code }
    }
}

#[cfg(test)]
impl Response for NoContentResponse {
    fn status(&self) -> hyper::status::StatusCode {
        self.status_code
    }
}

fn new_revision_etags(rev: &Revision) -> Vec<hyper::header::EntityTag> {
    // FIXME: Test this.
    vec![hyper::header::EntityTag::new(false, rev.to_string())]
}
<commit_msg>Resolve all FIXME comments<commit_after>//! Action types.
//!
//! Applications should not access the `action` module directly. Instead, they
//! should use the appropriate `Client` method to construct an action. For
//! example, the method `post_to_database` constructs a `PostToDatabase`
//! action.

macro_rules! impl_action_public_methods {
    ($action_output:ty) => {
        /// Sends the action request and waits for the response.
        pub fn run(self) -> Result<$action_output, Error> {
            action::run_action(self)
        }
    }
}

macro_rules! make_couchdb_error {
    ($error_variant:ident, $response:expr) => {
        Error::$error_variant(Some(try!($response.decode_json::<ErrorResponse>())))
    }
}

#[macro_use]
mod test_macro;

mod delete_database;
mod delete_document;
mod get_all_databases;
mod get_database;
mod get_document;
mod get_view;
mod head_database;
mod head_document;
mod post_to_database;
mod put_database;
mod put_document;

pub use self::delete_database::DeleteDatabase;
pub use self::delete_document::DeleteDocument;
pub use self::get_all_databases::GetAllDatabases;
pub use self::get_database::GetDatabase;
pub use self::get_document::GetDocument;
pub use self::get_view::GetView;
pub use self::head_database::HeadDatabase;
pub use self::head_document::HeadDocument;
pub use self::post_to_database::PostToDatabase;
pub use self::put_database::PutDatabase;
pub use self::put_document::PutDocument;

use hyper;
use serde;
use serde_json;

use Error;
use Revision;
use error::{DecodeErrorKind, TransportKind};

// The Action trait abstracts the machinery for executing CouchDB actions. Types
// implementing the Action trait define only how they construct requests and
// process responses. This separates the action logic from the responsibility of
// sending the request and receiving its response.
trait Action: Sized {
    type Output;
    fn make_request(self) -> Result<Request, Error>;
    fn take_response<R: Response>(response: R) -> Result<Self::Output, Error>;
}

fn run_action<A>(action: A) -> Result<A::Output, Error>
    where A: Action
{
    let action_request = try!(action.make_request());

    let action_response = {
        use std::io::Write;
        let mut hyper_request = try!(hyper::client::Request::new(action_request.method,
                                                                 action_request.uri)
                                         .map_err(|e| Error::Transport(TransportKind::Hyper(e))));
        *hyper_request.headers_mut() = action_request.headers;
        let mut request_stream = try!(hyper_request.start()
                                                   .map_err(|e| {
                                                       Error::Transport(TransportKind::Hyper(e))
                                                   }));
        try!(request_stream.write_all(&action_request.body)
                           .map_err(|e| Error::Transport(TransportKind::Io(e))));
        let hyper_response = try!(request_stream.send().map_err(|e| {
            Error::Transport(TransportKind::Hyper(e))
        }));
        HyperResponse::new(hyper_response)
    };

    A::take_response(action_response)
}

struct Request {
    method: hyper::method::Method,
    uri: hyper::Url,
    headers: hyper::header::Headers,
    body: Vec<u8>,
}

impl Request {
    pub fn new(method: hyper::method::Method, uri: hyper::Url) -> Self {
        Request {
            method: method,
            uri: uri,
            headers: hyper::header::Headers::new(),
            body: Vec::new(),
        }
    }

    #[cfg(test)]
    pub fn method(&self) -> &hyper::method::Method {
        &self.method
    }

    #[cfg(test)]
    pub fn uri(&self) -> &hyper::Url {
        &self.uri
    }

    #[cfg(test)]
    pub fn headers(&self) -> &hyper::header::Headers {
        &self.headers
    }

    pub fn set_body(mut self, body: Vec<u8>) -> Self {
        self.body = body;
        self
    }

    pub fn set_accept_application_json(mut self) -> Self {
        let qitems = {
            use hyper::mime::{Mime, TopLevel, SubLevel};
            vec![hyper::header::qitem(Mime(TopLevel::Application, SubLevel::Json, vec![]))]
        };
        self.headers.set(hyper::header::Accept(qitems));
        self
    }

    pub fn set_content_type_application_json(mut self) -> Self {
        let qitems = {
            use hyper::mime::{Mime, TopLevel, SubLevel};
            Mime(TopLevel::Application, SubLevel::Json, vec![])
        };
        self.headers.set(hyper::header::ContentType(qitems));
        self
    }

    pub fn set_if_match_revision(mut self, rev: Option<&Revision>) -> Self {
        match rev {
            None => self,
            Some(rev) => {
                let etags = new_revision_etags(rev);
                self.headers.set(hyper::header::IfMatch::Items(etags));
                self
            }
        }
    }

    pub fn set_if_none_match_revision(mut self, rev: Option<&Revision>) -> Self {
        match rev {
            None => self,
            Some(rev) => {
                let etags = new_revision_etags(rev);
                self.headers.set(hyper::header::IfNoneMatch::Items(etags));
                self
            }
        }
    }
}

trait Response {

    fn status(&self) -> hyper::status::StatusCode {
        hyper::status::StatusCode::InternalServerError
    }

    fn content_type_must_be_application_json(&self) -> Result<(), Error> {
        Err(Error::NoContentTypeHeader { expected: "application/json" })
    }

    fn decode_json<T: serde::Deserialize>(&mut self) -> Result<T, Error> {
        serde_json::from_str("").map_err(|e| Error::Decode(DecodeErrorKind::Serde { cause: e }))
    }
}

struct HyperResponse {
    hyper_response: hyper::client::Response,
}

impl HyperResponse {
    fn new(hyper_response: hyper::client::Response) -> Self {
        HyperResponse { hyper_response: hyper_response }
    }
}

impl Response for HyperResponse {
    fn status(&self) -> hyper::status::StatusCode {
        self.hyper_response.status
    }

    // Returns an error if the HTTP response doesn't have a Content-Type of
    // `application/json`.
    fn content_type_must_be_application_json(&self) -> Result<(), Error> {
        headers_content_type_must_be_application_json(&self.hyper_response.headers)
    }

    fn decode_json<T: serde::Deserialize>(&mut self) -> Result<T, Error> {
        serde_json::from_reader::<_, T>(&mut self.hyper_response).map_err(|e| {
            match e {
                serde_json::Error::IoError(e) => Error::Transport(TransportKind::Io(e)),
                _ => Error::Decode(DecodeErrorKind::Serde { cause: e }),
            }
        })
    }
}

// Mock response encapsulating a typical application/json response.
#[cfg(test)]
struct JsonResponse {
    status_code: hyper::status::StatusCode,
    body: String,
}

#[cfg(test)]
impl JsonResponse {
    fn new<T: serde::Serialize>(status_code: hyper::status::StatusCode, body: &T) -> Self {
        JsonResponse {
            status_code: status_code,
            body: serde_json::to_string(&body).unwrap(),
        }
    }
}

#[cfg(test)]
impl Response for JsonResponse {
    fn status(&self) -> hyper::status::StatusCode {
        self.status_code
    }

    fn content_type_must_be_application_json(&self) -> Result<(), Error> {
        Ok(())
    }

    fn decode_json<T: serde::Deserialize>(&mut self) -> Result<T, Error> {
        serde_json::from_str(&self.body)
            .map_err(|e| Error::Decode(DecodeErrorKind::Serde { cause: e }))
    }
}

// Mock response encapsulating a response with no body.
#[cfg(test)]
struct NoContentResponse {
    status_code: hyper::status::StatusCode,
}

#[cfg(test)]
impl NoContentResponse {
    fn new(status_code: hyper::status::StatusCode) -> Self {
        NoContentResponse { status_code: status_code }
    }
}

#[cfg(test)]
impl Response for NoContentResponse {
    fn status(&self) -> hyper::status::StatusCode {
        self.status_code
    }
}

fn headers_content_type_must_be_application_json(headers: &hyper::header::Headers)
                                                 -> Result<(), Error> {
    use hyper::header::ContentType;
    use hyper::mime::{Mime, TopLevel, SubLevel};
    let c = "application/json";
    match headers.get::<ContentType>() {
        None => Err(Error::NoContentTypeHeader { expected: c }),
        Some(&ContentType(Mime(TopLevel::Application, SubLevel::Json, ref _param))) => Ok(()),
        Some(&ContentType(ref mime)) => {
            Err(Error::UnexpectedContentTypeHeader {
                expected: c,
                got: format!("{}", mime),
            })
        }
    }
}

fn new_revision_etags(rev: &Revision) -> Vec<hyper::header::EntityTag> {
    vec![hyper::header::EntityTag::new(false, rev.to_string())]
}

#[cfg(test)]
mod tests {

    #[test]
    fn headers_content_type_must_be_application_json_ok_with_charset() {
        use hyper::header::{ContentType, Headers};
        let mut headers = Headers::new();
        headers.set(ContentType("application/json; charset=utf-8".parse().unwrap()));
        super::headers_content_type_must_be_application_json(&headers).unwrap();
    }

    #[test]
    fn headers_content_type_must_be_application_json_ok_without_charset() {
        use hyper::header::{ContentType, Headers};
        let mut headers = Headers::new();
        headers.set(ContentType("application/json".parse().unwrap()));
        super::headers_content_type_must_be_application_json(&headers).unwrap();
    }

    #[test]
    fn headers_content_type_must_be_application_json_no_header() {
        use hyper::header::Headers;
        let headers = Headers::new();
        super::headers_content_type_must_be_application_json(&headers).unwrap_err();
    }

    #[test]
    fn headers_content_type_must_be_application_json_wrong_type() {
        use hyper::header::{ContentType, Headers};
        let mut headers = Headers::new();
        headers.set(ContentType("plain/text".parse().unwrap()));
        super::headers_content_type_must_be_application_json(&headers).unwrap_err();
    }
}
<|endoftext|>


<commit_before>use {Job, Result};

pub trait Schedule {
    fn push(&mut self, &Job) -> Result<Decision>;
    fn pass(&mut self, f64);
}

pub struct Decision {
    pub start: f64,
    pub finish: f64,
    pub mapping: Vec<(usize, usize)>,
}

mod compact;
mod queue;

pub use self::compact::Compact;

impl Decision {
    #[inline]
    pub fn new(start: f64, finish: f64, mapping: Vec<(usize, usize)>) -> Decision {
        Decision { start: start, finish: finish, mapping: mapping }
    }
}
<commit_msg>A cosmetic adjustment<commit_after>use {Job, Result};

mod compact;
mod queue;

pub use self::compact::Compact;

pub trait Schedule {
    fn push(&mut self, &Job) -> Result<Decision>;
    fn pass(&mut self, f64);
}

pub struct Decision {
    pub start: f64,
    pub finish: f64,
    pub mapping: Vec<(usize, usize)>,
}

impl Decision {
    #[inline]
    pub fn new(start: f64, finish: f64, mapping: Vec<(usize, usize)>) -> Decision {
        Decision { start: start, finish: finish, mapping: mapping }
    }
}
<|endoftext|>


<commit_before>use {osc_types, errors};

use std::{io, string, mem, error};
use std::io::BufRead;

use byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8], size: usize) -> Result<osc_types::OscPacket, errors::OscError> {
    match msg[0] as char {
        '/' => {
            decode_message(msg, size)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(errors::OscError::BadOscPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8], size: usize) -> Result<osc_types::OscPacket, errors::OscError> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);
    let mut pos: u64 = 0;

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            pos = pad_four(cursor.position());
            println!("{}, {}", addr, pos);
        }
        Err(e) => {
            println!("{}", e)
        }
    }

    Ok(osc_types::OscPacket::Message(osc_types::OscMessage))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> Result<String, errors::OscError> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => String::from_utf8(str_buf).map_err(|e| errors::OscError::StringError(e)),
        Err(e) => Err(errors::OscError::ReadError(e)),
    }
}

fn decode_bundle(msg: &[u8]) -> Result<osc_types::OscPacket, errors::OscError> {
    Err(errors::OscError::BadOscBundle)
}

fn pad_four(pos: u64) -> u64 {
    let d: u64 = pos % 4;
    match d {
        0 => pos,
        _ => pos + (4 - d),
    }
}
<commit_msg>Use `OscResult` type alias<commit_after>use {osc_types, errors};

use std::{io, string, mem, error};
use std::io::BufRead;

use byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg, size)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(errors::OscError::BadOscPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);
    let mut pos: u64 = 0;

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            pos = pad_four(cursor.position());
            println!("{}, {}", addr, pos);
        }
        Err(e) => {
            println!("{}", e)
        }
    }

    Ok(osc_types::OscPacket::Message(osc_types::OscMessage))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> osc_types::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => String::from_utf8(str_buf).map_err(|e| errors::OscError::StringError(e)),
        Err(e) => Err(errors::OscError::ReadError(e)),
    }
}

fn decode_bundle(msg: &[u8]) -> osc_types::OscResult<osc_types::OscPacket> {
    Err(errors::OscError::BadOscBundle)
}

fn pad_four(pos: u64) -> u64 {
    let d: u64 = pos % 4;
    match d {
        0 => pos,
        _ => pos + (4 - d),
    }
}
<|endoftext|>


<commit_before>use rustc_data_structures::fx::FxHashSet;
use std::fs;
use std::hash::{Hash, Hasher};
use std::path::Path;

use errors::Handler;

macro_rules! try_something {
    ($e:expr, $diag:expr, $out:expr) => ({
        match $e {
            Ok(c) => c,
            Err(e) => {
                $diag.struct_err(&e.to_string()).emit();
                return $out;
            }
        }
    })
}

#[derive(Debug, Clone, Eq)]
pub struct CssPath {
    pub name: String,
    pub children: FxHashSet<CssPath>,
}

// This PartialEq implementation IS NOT COMMUTATIVE!!!
//
// The order is very important: the second object must have all first's rules.
// However, the first doesn't require to have all second's rules.
impl PartialEq for CssPath {
    fn eq(&self, other: &CssPath) -> bool {
        if self.name != other.name {
            false
        } else {
            for child in &self.children {
                if !other.children.iter().any(|c| child == c) {
                    return false;
                }
            }
            true
        }
    }
}

impl Hash for CssPath {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.name.hash(state);
        for x in &self.children {
            x.hash(state);
        }
    }
}

impl CssPath {
    fn new(name: String) -> CssPath {
        CssPath {
            name,
            children: FxHashSet::default(),
        }
    }
}

/// All variants contain the position they occur.
#[derive(Debug, Clone, Copy)]
enum Events {
    StartLineComment(usize),
    StartComment(usize),
    EndComment(usize),
    InBlock(usize),
    OutBlock(usize),
}

impl Events {
    fn get_pos(&self) -> usize {
        match *self {
            Events::StartLineComment(p) |
            Events::StartComment(p) |
            Events::EndComment(p) |
            Events::InBlock(p) |
            Events::OutBlock(p) => p,
        }
    }

    fn is_comment(&self) -> bool {
        match *self {
            Events::StartLineComment(_) |
            Events::StartComment(_) |
            Events::EndComment(_) => true,
            _ => false,
        }
    }
}

fn previous_is_line_comment(events: &[Events]) -> bool {
    if let Some(&Events::StartLineComment(_)) = events.last() {
        true
    } else {
        false
    }
}

fn is_line_comment(pos: usize, v: &[u8], events: &[Events]) -> bool {
    if let Some(&Events::StartComment(_)) = events.last() {
        return false;
    }
    pos + 1 < v.len() && v[pos + 1] == b'/'
}

fn load_css_events(v: &[u8]) -> Vec<Events> {
    let mut pos = 0;
    let mut events = Vec::with_capacity(100);

    while pos < v.len() - 1 {
        match v[pos] {
            b'/' if pos + 1 < v.len() && v[pos + 1] == b'*' => {
                events.push(Events::StartComment(pos));
                pos += 1;
            }
            b'/' if is_line_comment(pos, v, &events) => {
                events.push(Events::StartLineComment(pos));
                pos += 1;
            }
            b'\n' if previous_is_line_comment(&events) => {
                events.push(Events::EndComment(pos));
            }
            b'*' if pos + 1 < v.len() && v[pos + 1] == b'/' => {
                events.push(Events::EndComment(pos + 2));
                pos += 1;
            }
            b'{' if !previous_is_line_comment(&events) => {
                if let Some(&Events::StartComment(_)) = events.last() {
                    pos += 1;
                    continue
                }
                events.push(Events::InBlock(pos + 1));
            }
            b'}' if !previous_is_line_comment(&events) => {
                if let Some(&Events::StartComment(_)) = events.last() {
                    pos += 1;
                    continue
                }
                events.push(Events::OutBlock(pos + 1));
            }
            _ => {}
        }
        pos += 1;
    }
    events
}

fn get_useful_next(events: &[Events], pos: &mut usize) -> Option<Events> {
    while *pos < events.len() {
        if !events[*pos].is_comment() {
            return Some(events[*pos]);
        }
        *pos += 1;
    }
    None
}

fn get_previous_positions(events: &[Events], mut pos: usize) -> Vec<usize> {
    let mut ret = Vec::with_capacity(3);

    ret.push(events[pos].get_pos());
    if pos > 0 {
        pos -= 1;
    }
    loop {
        if pos < 1 || !events[pos].is_comment() {
            let x = events[pos].get_pos();
            if *ret.last().unwrap() != x {
                ret.push(x);
            } else {
                ret.push(0);
            }
            break
        }
        ret.push(events[pos].get_pos());
        pos -= 1;
    }
    if ret.len() & 1 != 0 && events[pos].is_comment() {
        ret.push(0);
    }
    ret.iter().rev().cloned().collect()
}

fn build_rule(v: &[u8], positions: &[usize]) -> String {
    positions.chunks(2)
             .map(|x| ::std::str::from_utf8(&v[x[0]..x[1]]).unwrap_or(""))
             .collect::<String>()
             .trim()
             .replace("\n", " ")
             .replace("/", "")
             .replace("\t", " ")
             .replace("{", "")
             .replace("}", "")
             .split(' ')
             .filter(|s| s.len() > 0)
             .collect::<Vec<&str>>()
             .join(" ")
}

fn inner(v: &[u8], events: &[Events], pos: &mut usize) -> FxHashSet<CssPath> {
    let mut paths = Vec::with_capacity(50);

    while *pos < events.len() {
        if let Some(Events::OutBlock(_)) = get_useful_next(events, pos) {
            *pos += 1;
            break
        }
        if let Some(Events::InBlock(_)) = get_useful_next(events, pos) {
            paths.push(CssPath::new(build_rule(v, &get_previous_positions(events, *pos))));
            *pos += 1;
        }
        while let Some(Events::InBlock(_)) = get_useful_next(events, pos) {
            if let Some(ref mut path) = paths.last_mut() {
                for entry in inner(v, events, pos).iter() {
                    path.children.insert(entry.clone());
                }
            }
        }
        if let Some(Events::OutBlock(_)) = get_useful_next(events, pos) {
            *pos += 1;
        }
    }
    paths.iter().cloned().collect()
}

pub fn load_css_paths(v: &[u8]) -> CssPath {
    let events = load_css_events(v);
    let mut pos = 0;

    let mut parent = CssPath::new("parent".to_owned());
    parent.children = inner(v, &events, &mut pos);
    parent
}

pub fn get_differences(against: &CssPath, other: &CssPath, v: &mut Vec<String>) {
    if against.name != other.name {
        return
    } else {
        for child in &against.children {
            let mut found = false;
            let mut found_working = false;
            let mut tmp = Vec::new();

            for other_child in &other.children {
                if child.name == other_child.name {
                    if child != other_child {
                        get_differences(child, other_child, &mut tmp);
                    } else {
                        found_working = true;
                    }
                    found = true;
                    break
                }
            }
            if found == false {
                v.push(format!("  Missing \"{}\" rule", child.name));
            } else if found_working == false {
                v.extend(tmp.iter().cloned());
            }
        }
    }
}

pub fn test_theme_against<P: AsRef<Path>>(f: &P, against: &CssPath, diag: &Handler)
    -> (bool, Vec<String>)
{
    let data = try_something!(fs::read(f), diag, (false, vec![]));
    let paths = load_css_paths(&data);
    let mut ret = vec![];
    get_differences(against, &paths, &mut ret);
    (true, ret)
}

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

    #[test]
    fn test_comments_in_rules() {
        let text = r#"
rule a {}

rule b, c
// a line comment
{}

rule d
// another line comment
e {}

rule f/* a multine

comment*/{}

rule g/* another multine

comment*/h

i {}

rule j/*commeeeeent

you like things like "{}" in there? :)
*/
end {}"#;

        let against = r#"
rule a {}

rule b, c {}

rule d e {}

rule f {}

rule gh i {}

rule j end {}
"#;

        let mut ret = Vec::new();
        get_differences(&load_css_paths(against.as_bytes()),
                        &load_css_paths(text.as_bytes()),
                        &mut ret);
        assert!(ret.is_empty());
    }

    #[test]
    fn test_text() {
        let text = r#"
a
/* sdfs
*/ b
c // sdf
d {}
"#;
        let paths = load_css_paths(text.as_bytes());
        assert!(paths.children.contains(&CssPath::new("a b c d".to_owned())));
    }

    #[test]
    fn test_comparison() {
        let x = r#"
a {
    b {
        c {}
    }
}
"#;

        let y = r#"
a {
    b {}
}
"#;

        let against = load_css_paths(y.as_bytes());
        let other = load_css_paths(x.as_bytes());

        let mut ret = Vec::new();
        get_differences(&against, &other, &mut ret);
        assert!(ret.is_empty());
        get_differences(&other, &against, &mut ret);
        assert_eq!(ret, vec!["  Missing \"c\" rule".to_owned()]);
    }
}
<commit_msg>Rollup merge of #61181 - GuillaumeGomez:fix-theme-checker, r=kinnison<commit_after>use rustc_data_structures::fx::FxHashSet;
use std::fs;
use std::hash::{Hash, Hasher};
use std::path::Path;

use errors::Handler;

macro_rules! try_something {
    ($e:expr, $diag:expr, $out:expr) => ({
        match $e {
            Ok(c) => c,
            Err(e) => {
                $diag.struct_err(&e.to_string()).emit();
                return $out;
            }
        }
    })
}

#[derive(Debug, Clone, Eq)]
pub struct CssPath {
    pub name: String,
    pub children: FxHashSet<CssPath>,
}

// This PartialEq implementation IS NOT COMMUTATIVE!!!
//
// The order is very important: the second object must have all first's rules.
// However, the first doesn't require to have all second's rules.
impl PartialEq for CssPath {
    fn eq(&self, other: &CssPath) -> bool {
        if self.name != other.name {
            false
        } else {
            for child in &self.children {
                if !other.children.iter().any(|c| child == c) {
                    return false;
                }
            }
            true
        }
    }
}

impl Hash for CssPath {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.name.hash(state);
        for x in &self.children {
            x.hash(state);
        }
    }
}

impl CssPath {
    fn new(name: String) -> CssPath {
        CssPath {
            name,
            children: FxHashSet::default(),
        }
    }
}

/// All variants contain the position they occur.
#[derive(Debug, Clone, Copy)]
enum Events {
    StartLineComment(usize),
    StartComment(usize),
    EndComment(usize),
    InBlock(usize),
    OutBlock(usize),
}

impl Events {
    fn get_pos(&self) -> usize {
        match *self {
            Events::StartLineComment(p) |
            Events::StartComment(p) |
            Events::EndComment(p) |
            Events::InBlock(p) |
            Events::OutBlock(p) => p,
        }
    }

    fn is_comment(&self) -> bool {
        match *self {
            Events::StartLineComment(_) |
            Events::StartComment(_) |
            Events::EndComment(_) => true,
            _ => false,
        }
    }
}

fn previous_is_line_comment(events: &[Events]) -> bool {
    if let Some(&Events::StartLineComment(_)) = events.last() {
        true
    } else {
        false
    }
}

fn is_line_comment(pos: usize, v: &[u8], events: &[Events]) -> bool {
    if let Some(&Events::StartComment(_)) = events.last() {
        return false;
    }
    v[pos + 1] == b'/'
}

fn load_css_events(v: &[u8]) -> Vec<Events> {
    let mut pos = 0;
    let mut events = Vec::with_capacity(100);

    while pos + 1 < v.len() {
        match v[pos] {
            b'/' if v[pos + 1] == b'*' => {
                events.push(Events::StartComment(pos));
                pos += 1;
            }
            b'/' if is_line_comment(pos, v, &events) => {
                events.push(Events::StartLineComment(pos));
                pos += 1;
            }
            b'\n' if previous_is_line_comment(&events) => {
                events.push(Events::EndComment(pos));
            }
            b'*' if v[pos + 1] == b'/' => {
                events.push(Events::EndComment(pos + 2));
                pos += 1;
            }
            b'{' if !previous_is_line_comment(&events) => {
                if let Some(&Events::StartComment(_)) = events.last() {
                    pos += 1;
                    continue
                }
                events.push(Events::InBlock(pos + 1));
            }
            b'}' if !previous_is_line_comment(&events) => {
                if let Some(&Events::StartComment(_)) = events.last() {
                    pos += 1;
                    continue
                }
                events.push(Events::OutBlock(pos + 1));
            }
            _ => {}
        }
        pos += 1;
    }
    events
}

fn get_useful_next(events: &[Events], pos: &mut usize) -> Option<Events> {
    while *pos < events.len() {
        if !events[*pos].is_comment() {
            return Some(events[*pos]);
        }
        *pos += 1;
    }
    None
}

fn get_previous_positions(events: &[Events], mut pos: usize) -> Vec<usize> {
    let mut ret = Vec::with_capacity(3);

    ret.push(events[pos].get_pos());
    if pos > 0 {
        pos -= 1;
    }
    loop {
        if pos < 1 || !events[pos].is_comment() {
            let x = events[pos].get_pos();
            if *ret.last().unwrap() != x {
                ret.push(x);
            } else {
                ret.push(0);
            }
            break
        }
        ret.push(events[pos].get_pos());
        pos -= 1;
    }
    if ret.len() & 1 != 0 && events[pos].is_comment() {
        ret.push(0);
    }
    ret.iter().rev().cloned().collect()
}

fn build_rule(v: &[u8], positions: &[usize]) -> String {
    positions.chunks(2)
             .map(|x| ::std::str::from_utf8(&v[x[0]..x[1]]).unwrap_or(""))
             .collect::<String>()
             .trim()
             .replace("\n", " ")
             .replace("/", "")
             .replace("\t", " ")
             .replace("{", "")
             .replace("}", "")
             .split(' ')
             .filter(|s| s.len() > 0)
             .collect::<Vec<&str>>()
             .join(" ")
}

fn inner(v: &[u8], events: &[Events], pos: &mut usize) -> FxHashSet<CssPath> {
    let mut paths = Vec::with_capacity(50);

    while *pos < events.len() {
        if let Some(Events::OutBlock(_)) = get_useful_next(events, pos) {
            *pos += 1;
            break
        }
        if let Some(Events::InBlock(_)) = get_useful_next(events, pos) {
            paths.push(CssPath::new(build_rule(v, &get_previous_positions(events, *pos))));
            *pos += 1;
        }
        while let Some(Events::InBlock(_)) = get_useful_next(events, pos) {
            if let Some(ref mut path) = paths.last_mut() {
                for entry in inner(v, events, pos).iter() {
                    path.children.insert(entry.clone());
                }
            }
        }
        if let Some(Events::OutBlock(_)) = get_useful_next(events, pos) {
            *pos += 1;
        }
    }
    paths.iter().cloned().collect()
}

pub fn load_css_paths(v: &[u8]) -> CssPath {
    let events = load_css_events(v);
    let mut pos = 0;

    let mut parent = CssPath::new("parent".to_owned());
    parent.children = inner(v, &events, &mut pos);
    parent
}

pub fn get_differences(against: &CssPath, other: &CssPath, v: &mut Vec<String>) {
    if against.name != other.name {
        return
    } else {
        for child in &against.children {
            let mut found = false;
            let mut found_working = false;
            let mut tmp = Vec::new();

            for other_child in &other.children {
                if child.name == other_child.name {
                    if child != other_child {
                        get_differences(child, other_child, &mut tmp);
                    } else {
                        found_working = true;
                    }
                    found = true;
                    break
                }
            }
            if found == false {
                v.push(format!("  Missing \"{}\" rule", child.name));
            } else if found_working == false {
                v.extend(tmp.iter().cloned());
            }
        }
    }
}

pub fn test_theme_against<P: AsRef<Path>>(
    f: &P,
    against: &CssPath,
    diag: &Handler,
) -> (bool, Vec<String>) {
    let data = try_something!(fs::read(f), diag, (false, vec![]));
    let paths = load_css_paths(&data);
    let mut ret = vec![];
    get_differences(against, &paths, &mut ret);
    (true, ret)
}

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

    #[test]
    fn test_comments_in_rules() {
        let text = r#"
rule a {}

rule b, c
// a line comment
{}

rule d
// another line comment
e {}

rule f/* a multine

comment*/{}

rule g/* another multine

comment*/h

i {}

rule j/*commeeeeent

you like things like "{}" in there? :)
*/
end {}"#;

        let against = r#"
rule a {}

rule b, c {}

rule d e {}

rule f {}

rule gh i {}

rule j end {}
"#;

        let mut ret = Vec::new();
        get_differences(&load_css_paths(against.as_bytes()),
                        &load_css_paths(text.as_bytes()),
                        &mut ret);
        assert!(ret.is_empty());
    }

    #[test]
    fn test_text() {
        let text = r#"
a
/* sdfs
*/ b
c // sdf
d {}
"#;
        let paths = load_css_paths(text.as_bytes());
        assert!(paths.children.contains(&CssPath::new("a b c d".to_owned())));
    }

    #[test]
    fn test_comparison() {
        let x = r#"
a {
    b {
        c {}
    }
}
"#;

        let y = r#"
a {
    b {}
}
"#;

        let against = load_css_paths(y.as_bytes());
        let other = load_css_paths(x.as_bytes());

        let mut ret = Vec::new();
        get_differences(&against, &other, &mut ret);
        assert!(ret.is_empty());
        get_differences(&other, &against, &mut ret);
        assert_eq!(ret, vec!["  Missing \"c\" rule".to_owned()]);
    }

    #[test]
    fn check_empty_css() {
        let events = load_css_events(&[]);
        assert_eq!(events.len(), 0);
    }

    #[test]
    fn check_invalid_css() {
        let events = load_css_events(b"*");
        assert_eq!(events.len(), 0);
    }
}
<|endoftext|>


<commit_before>//! [GET /_matrix/client/r0/rooms/{roomId}/messages](https://matrix.org/docs/spec/client_server/r0.4.0.html#get-matrix-client-r0-rooms-roomid-messages)

use js_int::UInt;
use ruma_api::ruma_api;
use ruma_events::{collections::only, EventResult};
use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};

ruma_api! {
    metadata {
        description: "Get message events for a room.",
        method: GET,
        name: "get_message_events",
        path: "/_matrix/client/r0/rooms/:room_id/messages",
        rate_limited: false,
        requires_authentication: true,
    }

    request {
        /// The room to get events from.
        #[ruma_api(path)]
        pub room_id: RoomId,
        /// The token to start returning events from.
        ///
        /// This token can be obtained from a
        /// prev_batch token returned for each room by the sync API, or from a start or end token
        /// returned by a previous request to this endpoint.
        pub from: String,
        /// The token to stop returning events at.
        ///
        /// This token can be obtained from a prev_batch
        /// token returned for each room by the sync endpoint, or from a start or end token returned
        /// by a previous request to this endpoint.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub to: Option<String>,
        /// The direction to return events from.
        pub dir: Direction,
        /// The maximum number of events to return.
        ///
        /// Default: 10.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub limit: Option<UInt>,
    }

    response {
        /// The token the pagination starts from.
        pub start: String,
        /// A list of room events.
        pub chunk: Vec<EventResult<only::RoomEvent>>,
        /// The token the pagination ends at.
        pub end: String,
    }
}

/// The direction to return events from.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum Direction {
    /// Return events backwards in time from the requested `from` token.
    #[serde(rename = "b")]
    Backward,
    /// Return events forwards in time from the requested `from` token.
    #[serde(rename = "f")]
    Forward,
}
<commit_msg>Fix wrong parameter type in get_message_events<commit_after>//! [GET /_matrix/client/r0/rooms/{roomId}/messages](https://matrix.org/docs/spec/client_server/r0.4.0.html#get-matrix-client-r0-rooms-roomid-messages)

use js_int::UInt;
use ruma_api::ruma_api;
use ruma_events::{collections::only, EventResult};
use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};

ruma_api! {
    metadata {
        description: "Get message events for a room.",
        method: GET,
        name: "get_message_events",
        path: "/_matrix/client/r0/rooms/:room_id/messages",
        rate_limited: false,
        requires_authentication: true,
    }

    request {
        /// The room to get events from.
        #[ruma_api(path)]
        pub room_id: RoomId,
        /// The token to start returning events from.
        ///
        /// This token can be obtained from a
        /// prev_batch token returned for each room by the sync API, or from a start or end token
        /// returned by a previous request to this endpoint.
        #[ruma_api(query)]
        pub from: String,
        /// The token to stop returning events at.
        ///
        /// This token can be obtained from a prev_batch
        /// token returned for each room by the sync endpoint, or from a start or end token returned
        /// by a previous request to this endpoint.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub to: Option<String>,
        /// The direction to return events from.
        #[ruma_api(query)]
        pub dir: Direction,
        /// The maximum number of events to return.
        ///
        /// Default: 10.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub limit: Option<UInt>,
    }

    response {
        /// The token the pagination starts from.
        pub start: String,
        /// A list of room events.
        pub chunk: Vec<EventResult<only::RoomEvent>>,
        /// The token the pagination ends at.
        pub end: String,
    }
}

/// The direction to return events from.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum Direction {
    /// Return events backwards in time from the requested `from` token.
    #[serde(rename = "b")]
    Backward,
    /// Return events forwards in time from the requested `from` token.
    #[serde(rename = "f")]
    Forward,
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_use]
extern crate foo;

#[derive(A)]
struct A;

fn main() {
    let _b = B;
}
<commit_msg>tests: use a #![no_std] target crate in run-make/rustc-macro-dep-files.<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![no_std]
#![crate_type = "lib"]

#[macro_use]
extern crate foo;

#[derive(A)]
struct A;
<|endoftext|>


<commit_before>//! This module holds the machinery behind LabelledGeneric.
//!
//! A LabelledGeneric instance is pretty much exactly the same as a Generic instance, except
//! that the generic representation should contain information about field names.
//!
//! Having a separate trait for LabelledGenerics gives us the freedom to derive both
//! lablled and non-labelled generic type class instances for our types.
//!
//! Asides from the main LabelledGeneric trait, this module holds helper methods that allow
//! users to use LabelledGeneric without using universal function call syntax.
//!
//! In addition, this module holds macro-generated enums that map to letters in field names (identifiers).

use std::marker::PhantomData;
use hlist::*;
use std::fmt;

/// A trait that converts from a type to a labelled generic representation
///
/// For the most part, you should be using the derivation that is available through
/// frunk_derive to generate instances of this typeclass for your types.
///
/// I would highly recommend you check out `derivation_tests.rs` to see how to actually use
/// this trait in real life. Since frunk_derive depends on this trait, I can't actually
/// pull it in as a dependency here (otherwise the dependency would be circular) and show
/// how to use it in a proper doc test.
///
/// ```rust,ignore
/// #[derive(LabelledGeneric)]
/// struct NewUser<'a> {
///     first_name: &'a str,
///     last_name: &'a str,
///     age: usize,
/// }
///
/// #[derive(LabelledGeneric)]
/// struct SavedUser<'a> {
///     first_name: &'a str,
///     last_name: &'a str,
///     age: usize,
/// }
///
/// let n_user = NewUser {
///     first_name: "Joe",
///     last_name: "Blow",
///     age: 30,
/// };
///
/// let s_user = <SavedUser as LabelledGeneric>::convert_from(n_user); // done
/// ```
pub trait LabelledGeneric {
    /// The labelled generic representation type
    type Repr;

    /// Go from something to Repr
    fn into(self) -> Self::Repr;

    /// Go from labelled Repr to something
    fn from(r: Self::Repr) -> Self;

    /// From one type to another using a type with a compatible labelled generic representation
    fn convert_from<A>(a: A) -> Self
        where A: LabelledGeneric<Repr = Self::Repr>,
              Self: Sized
    {
        let repr = <A as LabelledGeneric>::into(a);
        <Self as LabelledGeneric>::from(repr)
    }

    /// Converts from another type A into Self assuming that A and Self have labelled generic representations
    /// that can be sculpted into each other.
    ///
    /// Note that this method tosses away the "remainder" of the sculpted representation. In other
    /// words, anything that is not needed from A gets tossed out.
    fn sculpted_convert_from<A, Indices>(a: A) -> Self
        where A: LabelledGeneric,
              Self: Sized,
    // The labelled representation of A must be sculpt-able into the labelled representation of Self
              <A as LabelledGeneric>::Repr: Sculptor<<Self as LabelledGeneric>::Repr, Indices> {
        let a_gen = <A as LabelledGeneric>::into(a);
        // We toss away the remainder.
        let (self_gen, _): (<Self as LabelledGeneric>::Repr, _) = a_gen.sculpt();
        <Self as LabelledGeneric>::from(self_gen)
    }
}

/// Given a labelled generic Representation of an A, returns A
pub fn from_labelled_generic<A, Repr>(gen: Repr) -> A
    where A: LabelledGeneric<Repr = Repr>
{
    <A as LabelledGeneric>::from(gen)
}

/// Given an A, returns its labelled generic Representation
pub fn into_labelled_generic<A, Repr>(a: A) -> Repr
    where A: LabelledGeneric<Repr = Repr>
{
    <A as LabelledGeneric>::into(a)
}

/// Converts one type into another assuming they have the same labelled generic Representation
pub fn labelled_convert_from<A, B, Repr>(a: A) -> B
    where A: LabelledGeneric<Repr = Repr>,
          B: LabelledGeneric<Repr = Repr>
{
    <B as LabelledGeneric>::convert_from(a)
}

/// Converts from one type into another assuming that their labelled generic representations
/// can be sculpted into each other.
///
/// The "Indices" type parameter allows the compiler to figure out that the two representations
/// can indeed be morphed into each other.
pub fn sculpted_convert_from<A, B, Indices>(a: A) -> B
    where A: LabelledGeneric,
          B: LabelledGeneric,
// The labelled representation of A must be sculpt-able into the labelled representation of B
          <A as LabelledGeneric>::Repr: Sculptor<<B as LabelledGeneric>::Repr, Indices> {
    <B as LabelledGeneric>::sculpted_convert_from(a)
}

// Create a bunch of enums that can be used to represent characters on the type level
macro_rules! create_enums_for {
    ($($i: ident)*) => {
        $(
            #[allow(non_snake_case, non_camel_case_types)]
            #[derive(PartialEq, Debug, Eq, Clone, Copy, PartialOrd, Ord)]
            pub enum $i {}
        )*
    }
}

// Add more as needed.
create_enums_for! { a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z __ _1 _2 _3 _4 _5 _6 _7 _8 _9 _0 }

#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
pub struct Labelled<Name, Type> {
    name_type_holder: PhantomData<Name>,
    pub name: &'static str,
    pub value: Type,
}

impl <Name, Type> fmt::Debug for Labelled<Name, Type>
    where Type: fmt::Debug {

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let v_debug = format!("{:?}", self.value);
        write!(f, "Labelled{{ name: {}, value: {} }}", self.name, v_debug)
    }
}

/// Returns a new label for a given value and custom name.
///
/// If you don't want to provide a custom name and want to rely on the type you provide
/// to build a name, then please use the label! macro.
///
/// ```
/// # use frunk_core::labelled::*;
/// let l = label_with_name::<(n,a,m,e),_>("name", "joe");
/// assert_eq!(l.value, "joe");
/// assert_eq!(l.name, "name");
/// ```
pub fn label_with_name<Label, Value>(name: &'static str, value: Value) -> Labelled<Label, Value> {
    Labelled {
        name_type_holder: PhantomData,
        name: name,
        value: value,
    }
}

/// Trait for turning a Labelled HList into an un-labelled HList
pub trait IntoUnlabelled {
    type Output;

    /// Turns the current HList into an unlabelled on.
    ///
    /// Effectively extracts the values held inside the individual Labelled
    ///
    /// ```
    /// # #[macro_use] extern crate frunk_core;
    /// # use frunk_core::labelled::*;
    /// # use frunk_core::hlist::*;
    /// # fn main() {
    ///
    /// let labelled_hlist = hlist![
    ///     label!((n, a, m, e), "joe"),
    ///     label!((a, g, e), 3)
    /// ];
    ///
    /// let unlabelled = labelled_hlist.into_unlabelled();
    ///
    /// assert_eq!(unlabelled, hlist!["joe", 3])
    /// # }
    /// ```
    fn into_unlabelled(self) -> Self::Output;
}

/// Implementation for HNil
impl IntoUnlabelled for HNil {
    type Output = HNil;
    fn into_unlabelled(self) -> Self::Output {
        self
    }
}

/// Implementation when we have a non-empty HCons holding a label in its head
impl<Label, Value, Tail> IntoUnlabelled for HCons<Labelled<Label, Value>, Tail>
    where Tail: IntoUnlabelled
{
    type Output = HCons<Value, <Tail as IntoUnlabelled>::Output>;

    fn into_unlabelled(self) -> Self::Output {
        HCons {
            head: self.head.value,
            tail: self.tail.into_unlabelled(),
        }
    }
}

/// Returns a string resulting from the concatenation of the types provided
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// assert_eq!(type_string!(a), "a");
/// assert_eq!(type_string!(a,b,c,d), "abcd");
/// assert_eq!(type_string!(a,b,c,d,), "abcd");
/// assert_eq!(type_string!(), "")
/// # }
/// ```
#[macro_export]
macro_rules! type_string {
    // Nothing
    () => { "" };

    // Just a single item
    ($single: ty) => {
        stringify!($single)
    };

    ($($repeated: ty),+) => {
        concat!($( type_string!($repeated)), * )
    };
    // Trailing comma case
    ($($repeated: ty,)+) => {
        type_string!($($repeated), *)
    };

}

#[macro_export]
macro_rules! label {
    // We are provided a stable name
    (($($repeated: ty),*), $value: expr, $name: expr) => {
        $crate::labelled::label_with_name::<($($repeated),*),_>($name, $value)
    };
    // No name provided, trailing comma types case
    (($($repeated: ty,)*), $value: expr, $name: expr) => {
        label!( ($($repeated),*), $value, $name )
    };
    // No name provided
    (($($repeated: ty),*), $value: expr) => {
        label!( ($($repeated),*), $value, type_string!($($repeated),*))
    };
    // No name provided, trailing comma types case
    (($($repeated: ty,)*), $value: expr) => {
        label!( ($($repeated),*), $value )
    }
}

#[test]
fn test_label_new_building() {
    let l1 = label!((a, b, c), 3);
    assert_eq!(l1.value, 3);
    assert_eq!(l1.name, "abc");
    let l2 = label!((a, b, c,), 3);
    assert_eq!(l2.value, 3);
    assert_eq!(l2.name, "abc");

    // test named
    let l3 = label!((a,b,c), 3, "nope");
    assert_eq!(l3.value, 3);
    assert_eq!(l3.name, "nope");
    let l4 = label!((a,b,c,), 3, "nope");
    assert_eq!(l4.value, 3);
    assert_eq!(l4.name, "nope");
}

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

    #[test]
    fn test_field_construction() {
        let f1 = label!((a, g, e), 3);
        let f2 = label!((a, g, e), 3);
        assert_eq!(f1, f2)
    }

    #[test]
    fn test_anonymous_record_useage() {
        let record = hlist![
            label!((n, a, m, e), "Joe"),
            label!((a, g, e), 30)
        ];
        let (name, _): (Labelled<(n, a, m, e), _>, _) = record.pluck();
        assert_eq!(name.value, "Joe")
    }

    #[test]
    fn test_unlabelling() {
        let labelled_hlist = hlist![
            label!((n, a, m, e), "joe"),
            label!((a, g, e), 3)];
        let unlabelled = labelled_hlist.into_unlabelled();
        assert_eq!(unlabelled, hlist!["joe", 3])
    }

    #[test]
    fn test_name() {
        let labelled = label!((n, a, m, e), "joe");
        assert_eq!(labelled.name, "name")
    }
}
<commit_msg>Refactor the label! macro to support non-tuples<commit_after>//! This module holds the machinery behind LabelledGeneric.
//!
//! A LabelledGeneric instance is pretty much exactly the same as a Generic instance, except
//! that the generic representation should contain information about field names.
//!
//! Having a separate trait for LabelledGenerics gives us the freedom to derive both
//! lablled and non-labelled generic type class instances for our types.
//!
//! Asides from the main LabelledGeneric trait, this module holds helper methods that allow
//! users to use LabelledGeneric without using universal function call syntax.
//!
//! In addition, this module holds macro-generated enums that map to letters in field names (identifiers).

use std::marker::PhantomData;
use hlist::*;
use std::fmt;

/// A trait that converts from a type to a labelled generic representation
///
/// For the most part, you should be using the derivation that is available through
/// frunk_derive to generate instances of this typeclass for your types.
///
/// I would highly recommend you check out `derivation_tests.rs` to see how to actually use
/// this trait in real life. Since frunk_derive depends on this trait, I can't actually
/// pull it in as a dependency here (otherwise the dependency would be circular) and show
/// how to use it in a proper doc test.
///
/// ```rust,ignore
/// #[derive(LabelledGeneric)]
/// struct NewUser<'a> {
///     first_name: &'a str,
///     last_name: &'a str,
///     age: usize,
/// }
///
/// #[derive(LabelledGeneric)]
/// struct SavedUser<'a> {
///     first_name: &'a str,
///     last_name: &'a str,
///     age: usize,
/// }
///
/// let n_user = NewUser {
///     first_name: "Joe",
///     last_name: "Blow",
///     age: 30,
/// };
///
/// let s_user = <SavedUser as LabelledGeneric>::convert_from(n_user); // done
/// ```
pub trait LabelledGeneric {
    /// The labelled generic representation type
    type Repr;

    /// Go from something to Repr
    fn into(self) -> Self::Repr;

    /// Go from labelled Repr to something
    fn from(r: Self::Repr) -> Self;

    /// From one type to another using a type with a compatible labelled generic representation
    fn convert_from<A>(a: A) -> Self
        where A: LabelledGeneric<Repr = Self::Repr>,
              Self: Sized
    {
        let repr = <A as LabelledGeneric>::into(a);
        <Self as LabelledGeneric>::from(repr)
    }

    /// Converts from another type A into Self assuming that A and Self have labelled generic representations
    /// that can be sculpted into each other.
    ///
    /// Note that this method tosses away the "remainder" of the sculpted representation. In other
    /// words, anything that is not needed from A gets tossed out.
    fn sculpted_convert_from<A, Indices>(a: A) -> Self
        where A: LabelledGeneric,
              Self: Sized,
    // The labelled representation of A must be sculpt-able into the labelled representation of Self
              <A as LabelledGeneric>::Repr: Sculptor<<Self as LabelledGeneric>::Repr, Indices> {
        let a_gen = <A as LabelledGeneric>::into(a);
        // We toss away the remainder.
        let (self_gen, _): (<Self as LabelledGeneric>::Repr, _) = a_gen.sculpt();
        <Self as LabelledGeneric>::from(self_gen)
    }
}

/// Given a labelled generic Representation of an A, returns A
pub fn from_labelled_generic<A, Repr>(gen: Repr) -> A
    where A: LabelledGeneric<Repr = Repr>
{
    <A as LabelledGeneric>::from(gen)
}

/// Given an A, returns its labelled generic Representation
pub fn into_labelled_generic<A, Repr>(a: A) -> Repr
    where A: LabelledGeneric<Repr = Repr>
{
    <A as LabelledGeneric>::into(a)
}

/// Converts one type into another assuming they have the same labelled generic Representation
pub fn labelled_convert_from<A, B, Repr>(a: A) -> B
    where A: LabelledGeneric<Repr = Repr>,
          B: LabelledGeneric<Repr = Repr>
{
    <B as LabelledGeneric>::convert_from(a)
}

/// Converts from one type into another assuming that their labelled generic representations
/// can be sculpted into each other.
///
/// The "Indices" type parameter allows the compiler to figure out that the two representations
/// can indeed be morphed into each other.
pub fn sculpted_convert_from<A, B, Indices>(a: A) -> B
    where A: LabelledGeneric,
          B: LabelledGeneric,
// The labelled representation of A must be sculpt-able into the labelled representation of B
          <A as LabelledGeneric>::Repr: Sculptor<<B as LabelledGeneric>::Repr, Indices> {
    <B as LabelledGeneric>::sculpted_convert_from(a)
}

// Create a bunch of enums that can be used to represent characters on the type level
macro_rules! create_enums_for {
    ($($i: ident)*) => {
        $(
            #[allow(non_snake_case, non_camel_case_types)]
            #[derive(PartialEq, Debug, Eq, Clone, Copy, PartialOrd, Ord)]
            pub enum $i {}
        )*
    }
}

// Add more as needed.
create_enums_for! { a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z __ _1 _2 _3 _4 _5 _6 _7 _8 _9 _0 }

#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
pub struct Labelled<Name, Type> {
    name_type_holder: PhantomData<Name>,
    pub name: &'static str,
    pub value: Type,
}

impl <Name, Type> fmt::Debug for Labelled<Name, Type>
    where Type: fmt::Debug {

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let v_debug = format!("{:?}", self.value);
        write!(f, "Labelled{{ name: {}, value: {} }}", self.name, v_debug)
    }
}

/// Returns a new label for a given value and custom name.
///
/// If you don't want to provide a custom name and want to rely on the type you provide
/// to build a name, then please use the label! macro.
///
/// ```
/// # use frunk_core::labelled::*;
/// let l = label_with_name::<(n,a,m,e),_>("name", "joe");
/// assert_eq!(l.value, "joe");
/// assert_eq!(l.name, "name");
/// ```
pub fn label_with_name<Label, Value>(name: &'static str, value: Value) -> Labelled<Label, Value> {
    Labelled {
        name_type_holder: PhantomData,
        name: name,
        value: value,
    }
}

/// Trait for turning a Labelled HList into an un-labelled HList
pub trait IntoUnlabelled {
    type Output;

    /// Turns the current HList into an unlabelled on.
    ///
    /// Effectively extracts the values held inside the individual Labelled
    ///
    /// ```
    /// # #[macro_use] extern crate frunk_core;
    /// # use frunk_core::labelled::*;
    /// # use frunk_core::hlist::*;
    /// # fn main() {
    ///
    /// let labelled_hlist = hlist![
    ///     label!((n, a, m, e), "joe"),
    ///     label!((a, g, e), 3)
    /// ];
    ///
    /// let unlabelled = labelled_hlist.into_unlabelled();
    ///
    /// assert_eq!(unlabelled, hlist!["joe", 3])
    /// # }
    /// ```
    fn into_unlabelled(self) -> Self::Output;
}

/// Implementation for HNil
impl IntoUnlabelled for HNil {
    type Output = HNil;
    fn into_unlabelled(self) -> Self::Output {
        self
    }
}

/// Implementation when we have a non-empty HCons holding a label in its head
impl<Label, Value, Tail> IntoUnlabelled for HCons<Labelled<Label, Value>, Tail>
    where Tail: IntoUnlabelled
{
    type Output = HCons<Value, <Tail as IntoUnlabelled>::Output>;

    fn into_unlabelled(self) -> Self::Output {
        HCons {
            head: self.head.value,
            tail: self.tail.into_unlabelled(),
        }
    }
}

/// Used for creating a Labelled value
///
/// There are two forms of this macro:
///
/// * Create an instance of the `Labelled` struct with the name
///   set to the the concatenation of the types passed in the
///   tuple used as the first argument.
///
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = label![(n,a,m,e), 30];
/// assert_eq!(labelled.name, "name")
/// # }
/// ```
///
/// * Create an instance of the `Labelled` struct with a custom, name,
///   passed as the last argument in the macro
/// ```
/// # #[macro_use] extern crate frunk_core;
/// # use frunk_core::labelled::*;
/// # use frunk_core::hlist::*;
/// # fn main() {
/// let labelled = label![(a,g,e), 30, "Age"];
/// assert_eq!(labelled.name, "Age");
/// # }
/// ```
#[macro_export]
macro_rules! label {
    // No name provided and type is a tuple
    (($($repeated: ty),*), $value: expr) => {
        label!( ($($repeated),*), $value, concat!( $(stringify!($repeated)),* ) )
    };
    // No name provided and type is a tuple, but with trailing commas
    (($($repeated: ty,)*), $value: expr) => {
        label!( ($($repeated),*), $value )
    };
    // We are provided any type, with a stable name
    ($name_type: ty, $value: expr, $name: expr) => {
        $crate::labelled::label_with_name::<$name_type,_>($name, $value)
    }
}

#[test]
fn test_label_new_building() {
    let l1 = label!((a, b, c), 3);
    assert_eq!(l1.value, 3);
    assert_eq!(l1.name, "abc");
    let l2 = label!((a, b, c,), 3);
    assert_eq!(l2.value, 3);
    assert_eq!(l2.name, "abc");

    // test named
    let l3 = label!((a,b,c), 3, "nope");
    assert_eq!(l3.value, 3);
    assert_eq!(l3.name, "nope");
    let l4 = label!((a,b,c,), 3, "nope");
    assert_eq!(l4.value, 3);
    assert_eq!(l4.name, "nope");
}

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

    #[test]
    fn test_field_construction() {
        let f1 = label!((a, g, e), 3);
        let f2 = label!((a, g, e), 3);
        assert_eq!(f1, f2)
    }

    #[test]
    fn test_anonymous_record_useage() {
        let record = hlist![
            label!((n, a, m, e), "Joe"),
            label!((a, g, e), 30)
        ];
        let (name, _): (Labelled<(n, a, m, e), _>, _) = record.pluck();
        assert_eq!(name.value, "Joe")
    }

    #[test]
    fn test_unlabelling() {
        let labelled_hlist = hlist![
            label!((n, a, m, e), "joe"),
            label!((a, g, e), 3)];
        let unlabelled = labelled_hlist.into_unlabelled();
        assert_eq!(unlabelled, hlist!["joe", 3])
    }

    #[test]
    fn test_name() {
        let labelled = label!((n, a, m, e), "joe");
        assert_eq!(labelled.name, "name")
    }
}
<|endoftext|>


<commit_before>pub trait Peripheral {
    fn read_port(&self, port: u16) -> u8;
    fn write_port(&mut self, port: u16, val: u8);
}

#[derive(RustcEncodable, RustcDecodable)]
pub struct Ula {
    pub value: u8
}

impl Peripheral for Ula {
    fn read_port(&self, _: u16) -> u8 {
        self.value
    }

    fn write_port(&mut self, _ : u16, val: u8) {
        if val & 0x10 != 0 {
            self.value = 0xff;
        } else {
            self.value = 0xbf;
        }
    }
}

#[derive(RustcEncodable, RustcDecodable)]
pub struct Ay {
    pub value: u8
}

impl Peripheral for Ay {
    fn read_port(&self, _: u16) -> u8 {
        0
    }

    fn write_port(&mut self, _: u16, val: u8) {
        self.value = 0;
    }
}
<commit_msg>Fix Ay port values<commit_after>pub trait Peripheral {
    fn read_port(&self, port: u16) -> u8;
    fn write_port(&mut self, port: u16, val: u8);
}

#[derive(RustcEncodable, RustcDecodable)]
pub struct Ula {
    pub value: u8
}

impl Peripheral for Ula {
    fn read_port(&self, _: u16) -> u8 {
        self.value
    }

    fn write_port(&mut self, _ : u16, val: u8) {
        if val & 0x10 != 0 {
            self.value = 0xff;
        } else {
            self.value = 0xbf;
        }
    }
}

#[derive(RustcEncodable, RustcDecodable)]
pub struct Ay {
    pub value: u8
}

impl Peripheral for Ay {
    fn read_port(&self, _: u16) -> u8 {
        0xff
    }

    fn write_port(&mut self, _: u16, val: u8) {
        self.value = val;
    }
}
<|endoftext|>