<commit_before>use std::fs;
use std::path;
use std::process;
use std::str::FromStr;
use std::sync::mpsc::channel;
use std::thread;
use std::time;

use clap;
use cobalt::cobalt_model;
use failure::ResultExt;
use notify;
use notify::Watcher;
use open;
use tiny_http::{Request, Response, Server};

use crate::args;
use crate::build;
use crate::error::*;

pub fn serve_command_args() -> clap::App<'static, 'static> {
    clap::SubCommand::with_name("serve")
        .about("build, serve, and watch the project at the source dir")
        .args(&args::get_config_args())
        .arg(
            clap::Arg::with_name("port")
                .short("P")
                .long("port")
                .value_name("INT")
                .help("Port to serve from")
                .default_value("3000")
                .takes_value(true),
        )
        .arg(
            clap::Arg::with_name("host")
                .long("host")
                .value_name("host-name/IP")
                .help("Host to serve from")
                .default_value("localhost")
                .takes_value(true),
        )
        .arg(
            clap::Arg::with_name("no-watch")
                .long("no-watch")
                .help("Disable rebuilding on change")
                .conflicts_with("drafts")
                .takes_value(false),
        )
        .arg(
            clap::Arg::with_name("open")
                .long("open")
                .help("Open in browser")
                .takes_value(false),
        )
}

pub fn serve_command(matches: &clap::ArgMatches) -> Result<()> {
    let host = matches.value_of("host").unwrap().to_string();
    let port = matches.value_of("port").unwrap().to_string();
    let ip = format!("{}:{}", host, port);
    let open_in_browser = matches.is_present("open");
    let url = format!("http://{}", ip);

    let mut config = args::get_config(matches)?;
    debug!("Overriding config `site.base_url` with `{}`", ip);
    config.site.base_url = Some(format!("http://{}", ip));
    let config = config.build()?;
    let dest = path::Path::new(&config.destination).to_owned();

    build::build(config.clone())?;

    if open_in_browser {
        open_browser(url)?;
    }

    if matches.is_present("no-watch") {
        serve(&dest, &ip)?;
    } else {
        info!("Watching {:?} for changes", &config.source);
        thread::spawn(move || {
            let e = serve(&dest, &ip);
            if let Some(e) = e.err() {
                error!("{}", e);
            }
            process::exit(1)
        });

        watch(&config)?;
    }
    Ok(())
}

fn static_file_handler(dest: &path::Path, req: Request) -> Result<()> {
    // grab the requested path
    let mut req_path = req.url().to_string();

    // strip off any querystrings so path.is_file() matches and doesn't stick index.html on the end
    // of the path (querystrings often used for cachebusting)
    if let Some(position) = req_path.rfind('?') {
        req_path.truncate(position);
    }

    // find the path of the file in the local system
    // (this gets rid of the '/' in `p`, so the `join()` will not replace the path)
    let path = dest.to_path_buf().join(&req_path[1..]);

    let serve_path = if path.is_file() {
        // try to point the serve path to `path` if it corresponds to a file
        path
    } else {
        // try to point the serve path into a "index.html" file in the requested
        // path
        path.join("index.html")
    };

    // if the request points to a file and it exists, read and serve it
    if serve_path.exists() {
        let file = fs::File::open(&serve_path)?;
        let mut response = Response::from_file(file);
        if let Some(mime) = mime_guess::MimeGuess::from_path(&serve_path).first_raw() {
            let content_type = format!("Content-Type:{}", mime);
            let content_type =
                tiny_http::Header::from_str(&content_type).expect("formatted correctly");
            response.add_header(content_type);
        }
        req.respond(response)?;
    } else {
        // write a simple body for the 404 page
        req.respond(
            Response::from_string("<h1> <center> 404: Page not found </center> </h1>")
                .with_status_code(404)
                .with_header(
                    tiny_http::Header::from_str("Content-Type: text/html")
                        .expect("formatted correctly"),
                ),
        )?;
    }

    Ok(())
}

fn serve(dest: &path::Path, ip: &str) -> Result<()> {
    info!("Serving {:?} through static file server", dest);
    info!("Server Listening on http://{}", &ip);
    info!("Ctrl-c to stop the server");

    // attempts to create a server
    let server = Server::http(ip).map_err(Error::from_boxed_compat)?;

    for request in server.incoming_requests() {
        if let Err(e) = static_file_handler(&dest, request) {
            error!("{}", e);
        }
    }
    Ok(())
}

fn open_browser(url: String) -> Result<()> {
    match open::that(url) {
        Ok(exit_status) => {
            if exit_status.success() {
                info!("Please check your browser!");
            } else {
                info!(
                    "Command returned non-zero exit status {:?}",
                    exit_status.code()
                );
            }
        }
        Err(why) => println!("Failure to execute command: {}", why),
    }
    Ok(())
}

fn watch(config: &cobalt_model::Config) -> Result<()> {
    // canonicalize is to ensure there is no question that `watcher`s paths come back safe for
    // Files::includes_file
    let source = path::Path::new(&config.source)
        .canonicalize()
        .with_context(|_| failure::err_msg("Failed in processing source"))?;

    let (tx, rx) = channel();
    let mut watcher = notify::watcher(tx, time::Duration::from_secs(1))
        .with_context(|_| failure::err_msg("Notify error"))?;
    watcher
        .watch(&source, notify::RecursiveMode::Recursive)
        .with_context(|_| failure::err_msg("Notify error"))?;
    info!("Watching {:?} for changes", &config.source);

    loop {
        let event = rx
            .recv()
            .with_context(|_| failure::err_msg("Notify error"))?;
        let event_path = match event {
            notify::DebouncedEvent::Create(ref path)
            | notify::DebouncedEvent::NoticeWrite(ref path)
            | notify::DebouncedEvent::Write(ref path)
            | notify::DebouncedEvent::NoticeRemove(ref path)
            | notify::DebouncedEvent::Remove(ref path) => Some(path),
            notify::DebouncedEvent::Rename(_, ref to) => Some(to),
            _ => None,
        };
        let rebuild = if let Some(event_path) = event_path {
            // Be as broad as possible in what can cause a rebuild to
            // ensure we don't miss anything (normal file walks will miss
            // `_layouts`, etc).
            if event_path.starts_with(&config.destination) {
                trace!("Ignored file changed {:?}", event);
                false
            } else {
                debug!("Page changed {:?}", event);
                true
            }
        } else {
            trace!("Assuming change {:?} is relevant", event);
            true
        };
        if rebuild {
            let result = build::build(config.clone());
            if let Err(fail) = result {
                let fail: exitfailure::ExitFailure = fail.into();
                error!("build failed\n{:?}", fail);
            }
        }
    }
}
<commit_msg>fix(serve): Resolve infinite loop om Windows. (#855)<commit_after>use std::fs;
use std::path;
use std::process;
use std::str::FromStr;
use std::sync::mpsc::channel;
use std::thread;
use std::time;

use clap;
use cobalt::cobalt_model;
use failure::ResultExt;
use notify;
use notify::Watcher;
use open;
use tiny_http::{Request, Response, Server};

use crate::args;
use crate::build;
use crate::error::*;

pub fn serve_command_args() -> clap::App<'static, 'static> {
    clap::SubCommand::with_name("serve")
        .about("build, serve, and watch the project at the source dir")
        .args(&args::get_config_args())
        .arg(
            clap::Arg::with_name("port")
                .short("P")
                .long("port")
                .value_name("INT")
                .help("Port to serve from")
                .default_value("3000")
                .takes_value(true),
        )
        .arg(
            clap::Arg::with_name("host")
                .long("host")
                .value_name("host-name/IP")
                .help("Host to serve from")
                .default_value("localhost")
                .takes_value(true),
        )
        .arg(
            clap::Arg::with_name("no-watch")
                .long("no-watch")
                .help("Disable rebuilding on change")
                .conflicts_with("drafts")
                .takes_value(false),
        )
        .arg(
            clap::Arg::with_name("open")
                .long("open")
                .help("Open in browser")
                .takes_value(false),
        )
}

pub fn serve_command(matches: &clap::ArgMatches) -> Result<()> {
    let host = matches.value_of("host").unwrap().to_string();
    let port = matches.value_of("port").unwrap().to_string();
    let ip = format!("{}:{}", host, port);
    let open_in_browser = matches.is_present("open");
    let url = format!("http://{}", ip);

    let mut config = args::get_config(matches)?;
    debug!("Overriding config `site.base_url` with `{}`", ip);
    config.site.base_url = Some(format!("http://{}", ip));
    let config = config.build()?;
    let dest = path::Path::new(&config.destination).to_owned();

    build::build(config.clone())?;

    if open_in_browser {
        open_browser(url)?;
    }

    if matches.is_present("no-watch") {
        serve(&dest, &ip)?;
    } else {
        info!("Watching {:?} for changes", &config.source);
        thread::spawn(move || {
            let e = serve(&dest, &ip);
            if let Some(e) = e.err() {
                error!("{}", e);
            }
            process::exit(1)
        });

        watch(&config)?;
    }
    Ok(())
}

fn static_file_handler(dest: &path::Path, req: Request) -> Result<()> {
    // grab the requested path
    let mut req_path = req.url().to_string();

    // strip off any querystrings so path.is_file() matches and doesn't stick index.html on the end
    // of the path (querystrings often used for cachebusting)
    if let Some(position) = req_path.rfind('?') {
        req_path.truncate(position);
    }

    // find the path of the file in the local system
    // (this gets rid of the '/' in `p`, so the `join()` will not replace the path)
    let path = dest.to_path_buf().join(&req_path[1..]);

    let serve_path = if path.is_file() {
        // try to point the serve path to `path` if it corresponds to a file
        path
    } else {
        // try to point the serve path into a "index.html" file in the requested
        // path
        path.join("index.html")
    };

    // if the request points to a file and it exists, read and serve it
    if serve_path.exists() {
        let file = fs::File::open(&serve_path)?;
        let mut response = Response::from_file(file);
        if let Some(mime) = mime_guess::MimeGuess::from_path(&serve_path).first_raw() {
            let content_type = format!("Content-Type:{}", mime);
            let content_type =
                tiny_http::Header::from_str(&content_type).expect("formatted correctly");
            response.add_header(content_type);
        }
        req.respond(response)?;
    } else {
        // write a simple body for the 404 page
        req.respond(
            Response::from_string("<h1> <center> 404: Page not found </center> </h1>")
                .with_status_code(404)
                .with_header(
                    tiny_http::Header::from_str("Content-Type: text/html")
                        .expect("formatted correctly"),
                ),
        )?;
    }

    Ok(())
}

fn serve(dest: &path::Path, ip: &str) -> Result<()> {
    info!("Serving {:?} through static file server", dest);
    info!("Server Listening on http://{}", &ip);
    info!("Ctrl-c to stop the server");

    // attempts to create a server
    let server = Server::http(ip).map_err(Error::from_boxed_compat)?;

    for request in server.incoming_requests() {
        if let Err(e) = static_file_handler(&dest, request) {
            error!("{}", e);
        }
    }
    Ok(())
}

fn open_browser(url: String) -> Result<()> {
    match open::that(url) {
        Ok(exit_status) => {
            if exit_status.success() {
                info!("Please check your browser!");
            } else {
                info!(
                    "Command returned non-zero exit status {:?}",
                    exit_status.code()
                );
            }
        }
        Err(why) => println!("Failure to execute command: {}", why),
    }
    Ok(())
}

fn watch(config: &cobalt_model::Config) -> Result<()> {
    // canonicalize is to ensure there is no question that `watcher`s paths come back safe for
    // Files::includes_file
    let source = path::Path::new(&config.source)
        .canonicalize()
        .with_context(|_| failure::err_msg("Failed in processing source"))?;

    // Also canonicalize the destination folder. In particular for Windows, notify-rs
    // generates the absolute path by prepending the above source path.
    // On Windows canonicalize() adds a \\?\ to the start of the path.
    let destination = config
        .destination
        .canonicalize()
        .with_context(|_| failure::err_msg("Failed to canonicalize destination folder"))?;

    let (tx, rx) = channel();
    let mut watcher = notify::watcher(tx, time::Duration::from_secs(1))
        .with_context(|_| failure::err_msg("Notify error"))?;
    watcher
        .watch(&source, notify::RecursiveMode::Recursive)
        .with_context(|_| failure::err_msg("Notify error"))?;
    info!("Watching {:?} for changes", &config.source);

    loop {
        let event = rx
            .recv()
            .with_context(|_| failure::err_msg("Notify error"))?;
        let event_path = match event {
            notify::DebouncedEvent::Create(ref path)
            | notify::DebouncedEvent::NoticeWrite(ref path)
            | notify::DebouncedEvent::Write(ref path)
            | notify::DebouncedEvent::NoticeRemove(ref path)
            | notify::DebouncedEvent::Remove(ref path) => Some(path),
            notify::DebouncedEvent::Rename(_, ref to) => Some(to),
            _ => None,
        };
        let rebuild = if let Some(event_path) = event_path {
            // Be as broad as possible in what can cause a rebuild to
            // ensure we don't miss anything (normal file walks will miss
            // `_layouts`, etc).
            if event_path.starts_with(&destination) {
                trace!("Ignored file changed {:?}", event);
                false
            } else {
                debug!("Page changed {:?}", event);
                true
            }
        } else {
            trace!("Assuming change {:?} is relevant", event);
            true
        };
        if rebuild {
            let result = build::build(config.clone());
            if let Err(fail) = result {
                let fail: exitfailure::ExitFailure = fail.into();
                error!("build failed\n{:?}", fail);
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use super::constant_directive::ConstantDirective;
use super::constant_value::ConstantValue;
use super::primitive::*;
use super::type_annotation::TypeAnnotation;
use common::Span;
use std::fmt;

/// A document only consisting of executable definitions (fragments and operations).
/// This excludes schema definitions and schema extensions.
#[derive(Debug)]
pub struct SchemaDocument {
    pub span: Span,
    pub definitions: Vec<TypeSystemDefinition>,
}

#[derive(PartialEq, Debug)]
pub enum TypeSystemDefinition {
    SchemaDefinition(SchemaDefinition),
    SchemaExtension(SchemaExtension),
    EnumTypeDefinition(EnumTypeDefinition),
    EnumTypeExtension(EnumTypeExtension),
    InterfaceTypeDefinition(InterfaceTypeDefinition),
    InterfaceTypeExtension(InterfaceTypeExtension),
    ObjectTypeDefinition(ObjectTypeDefinition),
    ObjectTypeExtension(ObjectTypeExtension),
    UnionTypeDefinition(UnionTypeDefinition),
    UnionTypeExtension(UnionTypeExtension),
    InputObjectTypeDefinition(InputObjectTypeDefinition),
    InputObjectTypeExtension(InputObjectTypeExtension),
    ScalarTypeDefinition(ScalarTypeDefinition),
    ScalarTypeExtension(ScalarTypeExtension),
    DirectiveDefinition(DirectiveDefinition),
}

#[derive(PartialEq, Debug)]
pub struct SchemaDefinition {
    pub directives: Vec<ConstantDirective>,
    pub operation_types: List<OperationTypeDefinition>,
}

#[derive(PartialEq, Debug)]
pub struct SchemaExtension {
    pub directives: Vec<ConstantDirective>,
    pub operation_types: Option<List<OperationTypeDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct OperationTypeDefinition {
    pub operation: OperationType,
    pub type_: Identifier,
}

#[derive(PartialEq, Debug, Copy, Clone)]
pub enum OperationType {
    Query,
    Mutation,
    Subscription,
}

#[derive(PartialEq, Debug)]
pub struct ObjectTypeDefinition {
    pub name: Identifier,
    pub interfaces: Vec<Identifier>,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<FieldDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct ObjectTypeExtension {
    pub name: Identifier,
    pub interfaces: Vec<Identifier>,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<FieldDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct InterfaceTypeDefinition {
    pub name: Identifier,
    pub interfaces: Vec<Identifier>,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<FieldDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct InterfaceTypeExtension {
    pub name: Identifier,
    pub interfaces: Vec<Identifier>,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<FieldDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct UnionTypeDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub members: Vec<Identifier>,
}

#[derive(PartialEq, Debug)]
pub struct UnionTypeExtension {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub members: Vec<Identifier>,
}

#[derive(PartialEq, Debug)]
pub struct ScalarTypeDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
}

#[derive(PartialEq, Debug)]
pub struct ScalarTypeExtension {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
}

#[derive(PartialEq, Debug)]
pub struct EnumTypeDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub values: Option<List<EnumValueDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct EnumTypeExtension {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub values: Option<List<EnumValueDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct InputObjectTypeDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<InputValueDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct InputObjectTypeExtension {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<InputValueDefinition>>,
}

#[derive(PartialEq, Debug)]
pub struct EnumValueDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
}

#[derive(PartialEq, Debug)]
pub struct DirectiveDefinition {
    pub name: Identifier,
    pub arguments: Option<List<InputValueDefinition>>,
    pub repeatable: bool,
    pub locations: Vec<DirectiveLocation>,
}

#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
pub enum DirectiveLocation {
    Query,
    Mutation,
    Subscription,
    Field,
    FragmentDefinition,
    FragmentSpread,
    InlineFragment,
    Schema,
    Scalar,
    Object,
    FieldDefinition,
    ArgumentDefinition,
    Interface,
    Union,
    Enum,
    EnumValue,
    InputObject,
    InputFieldDefinition,
    VariableDefinition,
}

impl fmt::Display for DirectiveLocation {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            DirectiveLocation::Query => write!(f, "QUERY"),
            DirectiveLocation::Mutation => write!(f, "MUTATION"),
            DirectiveLocation::Subscription => write!(f, "SUBSCRIPTION"),
            DirectiveLocation::Field => write!(f, "FIELD"),
            DirectiveLocation::FragmentDefinition => write!(f, "FRAGMENT_DEFINITION"),
            DirectiveLocation::FragmentSpread => write!(f, "FRAGMENT_SPREAD"),
            DirectiveLocation::InlineFragment => write!(f, "INLINE_FRAGMENT"),
            DirectiveLocation::Schema => write!(f, "SCHEMA"),
            DirectiveLocation::Scalar => write!(f, "SCALAR"),
            DirectiveLocation::Object => write!(f, "OBJECT"),
            DirectiveLocation::FieldDefinition => write!(f, "FIELD_DEFINITION"),
            DirectiveLocation::ArgumentDefinition => write!(f, "ARGUMENT_DEFINITION"),
            DirectiveLocation::Interface => write!(f, "INTERFACE"),
            DirectiveLocation::Union => write!(f, "UNION"),
            DirectiveLocation::Enum => write!(f, "ENUM"),
            DirectiveLocation::EnumValue => write!(f, "ENUM_VALUE"),
            DirectiveLocation::InputObject => write!(f, "INPUT_OBJECT"),
            DirectiveLocation::InputFieldDefinition => write!(f, "INPUT_FIELD_DEFINITION"),
            DirectiveLocation::VariableDefinition => write!(f, "VARIABLE_DEFINITION"),
        }
    }
}

#[derive(PartialEq, Debug)]
pub struct InputValueDefinition {
    pub name: Identifier,
    pub type_: TypeAnnotation,
    pub default_value: Option<ConstantValue>,
    pub directives: Vec<ConstantDirective>,
}

#[derive(PartialEq, Debug)]
pub struct FieldDefinition {
    pub name: Identifier,
    pub type_: TypeAnnotation,
    pub arguments: Option<List<InputValueDefinition>>,
    pub directives: Vec<ConstantDirective>,
}
<commit_msg>Add traits to support type system comparator<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use super::constant_directive::ConstantDirective;
use super::constant_value::ConstantValue;
use super::primitive::*;
use super::type_annotation::TypeAnnotation;
use common::Span;
use std::fmt;

/// A document only consisting of executable definitions (fragments and operations).
/// This excludes schema definitions and schema extensions.
#[derive(Debug)]
pub struct SchemaDocument {
    pub span: Span,
    pub definitions: Vec<TypeSystemDefinition>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub enum TypeSystemDefinition {
    SchemaDefinition(SchemaDefinition),
    SchemaExtension(SchemaExtension),
    EnumTypeDefinition(EnumTypeDefinition),
    EnumTypeExtension(EnumTypeExtension),
    InterfaceTypeDefinition(InterfaceTypeDefinition),
    InterfaceTypeExtension(InterfaceTypeExtension),
    ObjectTypeDefinition(ObjectTypeDefinition),
    ObjectTypeExtension(ObjectTypeExtension),
    UnionTypeDefinition(UnionTypeDefinition),
    UnionTypeExtension(UnionTypeExtension),
    InputObjectTypeDefinition(InputObjectTypeDefinition),
    InputObjectTypeExtension(InputObjectTypeExtension),
    ScalarTypeDefinition(ScalarTypeDefinition),
    ScalarTypeExtension(ScalarTypeExtension),
    DirectiveDefinition(DirectiveDefinition),
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct SchemaDefinition {
    pub directives: Vec<ConstantDirective>,
    pub operation_types: List<OperationTypeDefinition>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct SchemaExtension {
    pub directives: Vec<ConstantDirective>,
    pub operation_types: Option<List<OperationTypeDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct OperationTypeDefinition {
    pub operation: OperationType,
    pub type_: Identifier,
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
pub enum OperationType {
    Query,
    Mutation,
    Subscription,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct ObjectTypeDefinition {
    pub name: Identifier,
    pub interfaces: Vec<Identifier>,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<FieldDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct ObjectTypeExtension {
    pub name: Identifier,
    pub interfaces: Vec<Identifier>,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<FieldDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct InterfaceTypeDefinition {
    pub name: Identifier,
    pub interfaces: Vec<Identifier>,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<FieldDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct InterfaceTypeExtension {
    pub name: Identifier,
    pub interfaces: Vec<Identifier>,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<FieldDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct UnionTypeDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub members: Vec<Identifier>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct UnionTypeExtension {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub members: Vec<Identifier>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct ScalarTypeDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct ScalarTypeExtension {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct EnumTypeDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub values: Option<List<EnumValueDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct EnumTypeExtension {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub values: Option<List<EnumValueDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct InputObjectTypeDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<InputValueDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct InputObjectTypeExtension {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
    pub fields: Option<List<InputValueDefinition>>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct EnumValueDefinition {
    pub name: Identifier,
    pub directives: Vec<ConstantDirective>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct DirectiveDefinition {
    pub name: Identifier,
    pub arguments: Option<List<InputValueDefinition>>,
    pub repeatable: bool,
    pub locations: Vec<DirectiveLocation>,
}

#[derive(PartialEq, Eq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
pub enum DirectiveLocation {
    Query,
    Mutation,
    Subscription,
    Field,
    FragmentDefinition,
    FragmentSpread,
    InlineFragment,
    Schema,
    Scalar,
    Object,
    FieldDefinition,
    ArgumentDefinition,
    Interface,
    Union,
    Enum,
    EnumValue,
    InputObject,
    InputFieldDefinition,
    VariableDefinition,
}

impl fmt::Display for DirectiveLocation {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            DirectiveLocation::Query => write!(f, "QUERY"),
            DirectiveLocation::Mutation => write!(f, "MUTATION"),
            DirectiveLocation::Subscription => write!(f, "SUBSCRIPTION"),
            DirectiveLocation::Field => write!(f, "FIELD"),
            DirectiveLocation::FragmentDefinition => write!(f, "FRAGMENT_DEFINITION"),
            DirectiveLocation::FragmentSpread => write!(f, "FRAGMENT_SPREAD"),
            DirectiveLocation::InlineFragment => write!(f, "INLINE_FRAGMENT"),
            DirectiveLocation::Schema => write!(f, "SCHEMA"),
            DirectiveLocation::Scalar => write!(f, "SCALAR"),
            DirectiveLocation::Object => write!(f, "OBJECT"),
            DirectiveLocation::FieldDefinition => write!(f, "FIELD_DEFINITION"),
            DirectiveLocation::ArgumentDefinition => write!(f, "ARGUMENT_DEFINITION"),
            DirectiveLocation::Interface => write!(f, "INTERFACE"),
            DirectiveLocation::Union => write!(f, "UNION"),
            DirectiveLocation::Enum => write!(f, "ENUM"),
            DirectiveLocation::EnumValue => write!(f, "ENUM_VALUE"),
            DirectiveLocation::InputObject => write!(f, "INPUT_OBJECT"),
            DirectiveLocation::InputFieldDefinition => write!(f, "INPUT_FIELD_DEFINITION"),
            DirectiveLocation::VariableDefinition => write!(f, "VARIABLE_DEFINITION"),
        }
    }
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct InputValueDefinition {
    pub name: Identifier,
    pub type_: TypeAnnotation,
    pub default_value: Option<ConstantValue>,
    pub directives: Vec<ConstantDirective>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct FieldDefinition {
    pub name: Identifier,
    pub type_: TypeAnnotation,
    pub arguments: Option<List<InputValueDefinition>>,
    pub directives: Vec<ConstantDirective>,
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

#![allow(non_snake_case)]

register_diagnostic!(E0001, r##"
    This error suggests that the expression arm corresponding to the noted pattern
    will never be reached as for all possible values of the expression being matched,
    one of the preceeding patterns will match.

    This means that perhaps some of the preceeding patterns are too general, this
    one is too specific or the ordering is incorrect.
"##)

register_diagnostics!(
    E0002,
    E0003,
    E0004,
    E0005,
    E0006,
    E0007,
    E0008,
    E0009,
    E0010,
    E0011,
    E0012,
    E0013,
    E0014,
    E0015,
    E0016,
    E0017,
    E0019,
    E0020,
    E0021,
    E0022,
    E0023,
    E0024,
    E0025,
    E0026,
    E0027,
    E0028,
    E0029,
    E0030,
    E0031,
    E0032,
    E0033,
    E0034,
    E0035,
    E0036,
    E0038,
    E0039,
    E0040,
    E0041,
    E0042,
    E0043,
    E0044,
    E0045,
    E0046,
    E0047,
    E0048,
    E0049,
    E0050,
    E0051,
    E0052,
    E0053,
    E0054,
    E0055,
    E0056,
    E0057,
    E0058,
    E0059,
    E0060,
    E0061,
    E0062,
    E0063,
    E0066,
    E0067,
    E0068,
    E0069,
    E0070,
    E0071,
    E0072,
    E0073,
    E0074,
    E0075,
    E0076,
    E0077,
    E0078,
    E0079,
    E0080,
    E0081,
    E0082,
    E0083,
    E0084,
    E0085,
    E0086,
    E0087,
    E0088,
    E0089,
    E0090,
    E0091,
    E0092,
    E0093,
    E0094,
    E0095,
    E0096,
    E0097,
    E0098,
    E0099,
    E0100,
    E0101,
    E0102,
    E0103,
    E0104,
    E0105,
    E0106,
    E0107,
    E0108,
    E0109,
    E0110,
    E0113,
    E0114,
    E0115,
    E0116,
    E0117,
    E0118,
    E0119,
    E0120,
    E0121,
    E0122,
    E0124,
    E0125,
    E0126,
    E0127,
    E0128,
    E0129,
    E0130,
    E0131,
    E0132,
    E0133,
    E0134,
    E0135,
    E0136,
    E0137,
    E0138,
    E0139,
    E0140,
    E0141,
    E0142,
    E0143,
    E0144,
    E0145,
    E0146,
    E0147,
    E0148,
    E0149,
    E0150,
    E0151,
    E0152,
    E0153,
    E0154,
    E0155,
    E0156,
    E0157,
    E0158,
    E0159,
    E0160
)
<commit_msg>auto merge of #17016 : steveklabnik/rust/fix_diagnostic_codes, r=huonw<commit_after>// Copyright 2014 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.

#![allow(non_snake_case)]

register_diagnostic!(E0001, r##"
    This error suggests that the expression arm corresponding to the noted pattern
    will never be reached as for all possible values of the expression being matched,
    one of the preceeding patterns will match.

    This means that perhaps some of the preceeding patterns are too general, this
    one is too specific or the ordering is incorrect.
"##)

register_diagnostics!(
    E0002,
    E0003,
    E0004,
    E0005,
    E0006,
    E0007,
    E0008,
    E0009,
    E0010,
    E0011,
    E0012,
    E0013,
    E0014,
    E0015,
    E0016,
    E0017,
    E0019,
    E0020,
    E0021,
    E0022,
    E0023,
    E0024,
    E0025,
    E0026,
    E0027,
    E0028,
    E0029,
    E0030,
    E0031,
    E0032,
    E0033,
    E0034,
    E0035,
    E0036,
    E0038,
    E0039,
    E0040,
    E0041,
    E0042,
    E0043,
    E0044,
    E0045,
    E0046,
    E0047,
    E0048,
    E0049,
    E0050,
    E0051,
    E0052,
    E0053,
    E0054,
    E0055,
    E0056,
    E0057,
    E0058,
    E0059,
    E0060,
    E0061,
    E0062,
    E0063,
    E0066,
    E0067,
    E0068,
    E0069,
    E0070,
    E0071,
    E0072,
    E0073,
    E0074,
    E0075,
    E0076,
    E0077,
    E0078,
    E0079,
    E0080,
    E0081,
    E0082,
    E0083,
    E0084,
    E0085,
    E0086,
    E0087,
    E0088,
    E0089,
    E0090,
    E0091,
    E0092,
    E0093,
    E0094,
    E0095,
    E0096,
    E0097,
    E0098,
    E0099,
    E0100,
    E0101,
    E0102,
    E0103,
    E0104,
    E0105,
    E0106,
    E0107,
    E0108,
    E0109,
    E0110,
    E0113,
    E0114,
    E0115,
    E0116,
    E0117,
    E0118,
    E0119,
    E0120,
    E0121,
    E0122,
    E0124,
    E0125,
    E0126,
    E0127,
    E0128,
    E0129,
    E0130,
    E0131,
    E0132,
    E0133,
    E0134,
    E0135,
    E0136,
    E0137,
    E0138,
    E0139,
    E0140,
    E0141,
    E0142,
    E0143,
    E0144,
    E0145,
    E0146,
    E0147,
    E0148,
    E0151,
    E0152,
    E0153,
    E0154,
    E0155,
    E0156,
    E0157,
    E0158,
    E0159,
    E0160
)
<|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.

use hir::def_id::DefId;
use ty::{self, Ty, TypeFoldable, Substs};
use util::ppaux;

use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
    pub def: InstanceDef<'tcx>,
    pub substs: &'tcx Substs<'tcx>,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum InstanceDef<'tcx> {
    Item(DefId),
    Intrinsic(DefId),

    /// <fn() as FnTrait>::call_*
    /// def-id is FnTrait::call_*
    FnPtrShim(DefId, Ty<'tcx>),

    /// <Trait as Trait>::fn
    Virtual(DefId, usize),

    /// <[mut closure] as FnOnce>::call_once
    ClosureOnceShim { call_once: DefId },

    /// drop_in_place::<T>; None for empty drop glue.
    DropGlue(DefId, Option<Ty<'tcx>>),

    /// Builtin method implementation, e.g. `Clone::clone`.
    CloneShim(DefId, Ty<'tcx>),
}

impl<'tcx> InstanceDef<'tcx> {
    #[inline]
    pub fn def_id(&self) -> DefId {
        match *self {
            InstanceDef::Item(def_id) |
            InstanceDef::FnPtrShim(def_id, _) |
            InstanceDef::Virtual(def_id, _) |
            InstanceDef::Intrinsic(def_id, ) |
            InstanceDef::ClosureOnceShim { call_once: def_id } |
            InstanceDef::DropGlue(def_id, _) |
            InstanceDef::CloneShim(def_id, _) => def_id
        }
    }

    #[inline]
    pub fn def_ty<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
        tcx.type_of(self.def_id())
    }

    #[inline]
    pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
        tcx.get_attrs(self.def_id())
    }
}

impl<'tcx> fmt::Display for Instance<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
        match self.def {
            InstanceDef::Item(_) => Ok(()),
            InstanceDef::Intrinsic(_) => {
                write!(f, " - intrinsic")
            }
            InstanceDef::Virtual(_, num) => {
                write!(f, " - shim(#{})", num)
            }
            InstanceDef::FnPtrShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::ClosureOnceShim { .. } => {
                write!(f, " - shim")
            }
            InstanceDef::DropGlue(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::CloneShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
        }
    }
}

impl<'a, 'b, 'tcx> Instance<'tcx> {
    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
               -> Instance<'tcx> {
        assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
                "substs of instance {:?} not normalized for trans: {:?}",
                def_id, substs);
        Instance { def: InstanceDef::Item(def_id), substs: substs }
    }

    pub fn mono(tcx: ty::TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
        Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
    }

    #[inline]
    pub fn def_id(&self) -> DefId {
        self.def.def_id()
    }
}
<commit_msg>bring TyCtxt into scope<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.

use hir::def_id::DefId;
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
use util::ppaux;

use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
    pub def: InstanceDef<'tcx>,
    pub substs: &'tcx Substs<'tcx>,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum InstanceDef<'tcx> {
    Item(DefId),
    Intrinsic(DefId),

    /// <fn() as FnTrait>::call_*
    /// def-id is FnTrait::call_*
    FnPtrShim(DefId, Ty<'tcx>),

    /// <Trait as Trait>::fn
    Virtual(DefId, usize),

    /// <[mut closure] as FnOnce>::call_once
    ClosureOnceShim { call_once: DefId },

    /// drop_in_place::<T>; None for empty drop glue.
    DropGlue(DefId, Option<Ty<'tcx>>),

    /// Builtin method implementation, e.g. `Clone::clone`.
    CloneShim(DefId, Ty<'tcx>),
}

impl<'tcx> InstanceDef<'tcx> {
    #[inline]
    pub fn def_id(&self) -> DefId {
        match *self {
            InstanceDef::Item(def_id) |
            InstanceDef::FnPtrShim(def_id, _) |
            InstanceDef::Virtual(def_id, _) |
            InstanceDef::Intrinsic(def_id, ) |
            InstanceDef::ClosureOnceShim { call_once: def_id } |
            InstanceDef::DropGlue(def_id, _) |
            InstanceDef::CloneShim(def_id, _) => def_id
        }
    }

    #[inline]
    pub fn def_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
        tcx.type_of(self.def_id())
    }

    #[inline]
    pub fn attrs<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
        tcx.get_attrs(self.def_id())
    }
}

impl<'tcx> fmt::Display for Instance<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
        match self.def {
            InstanceDef::Item(_) => Ok(()),
            InstanceDef::Intrinsic(_) => {
                write!(f, " - intrinsic")
            }
            InstanceDef::Virtual(_, num) => {
                write!(f, " - shim(#{})", num)
            }
            InstanceDef::FnPtrShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::ClosureOnceShim { .. } => {
                write!(f, " - shim")
            }
            InstanceDef::DropGlue(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::CloneShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
        }
    }
}

impl<'a, 'b, 'tcx> Instance<'tcx> {
    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
               -> Instance<'tcx> {
        assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
                "substs of instance {:?} not normalized for trans: {:?}",
                def_id, substs);
        Instance { def: InstanceDef::Item(def_id), substs: substs }
    }

    pub fn mono(tcx: TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
        Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
    }

    #[inline]
    pub fn def_id(&self) -> DefId {
        self.def.def_id()
    }
}
<|endoftext|>


<commit_before>/*!

DC (Distance Coding) forward and backward transformation.
Designed to be used on BWT block output for compression.

# Links

http://www.data-compression.info/Algorithms/DC/

# Example

```rust
use compress::bwt::dc;

let bytes = bytes!("abracadabra");
let (alphabet,distances) = dc::encode_simple::<uint>(bytes);
let decoded = dc::decode_simple(bytes.len(),
                                alphabet.as_slice(),
                                distances.as_slice());
```

# Credit

This is an original implementation.
Thanks to Edgar Binder for inventing DC!

*/

use std::{io, vec};
use super::mtf::MTF;

pub type Symbol = u8;
pub type Rank = u8;
pub static TotalSymbols: uint = 0x100;

/// encode a block of bytes 'input'
/// write output distance stream into 'distances'
/// return: unique bytes encountered in the order they appear
/// with the corresponding initial distances
pub fn encode<D: Clone + Eq + NumCast>(input: &[Symbol], distances: &mut [D], mtf: &mut MTF) -> ~[(Symbol,D)] {
    let N = input.len();
    assert_eq!(distances.len(), N);
    let mut last = [N, ..TotalSymbols];
    let mut unique: ~[(Symbol,D)] = ~[];
    let filler: D = NumCast::from(N).unwrap();
    for (i,&sym) in input.iter().enumerate() {
        distances[i] = filler.clone();
        let base = last[sym];
        last[sym] = i;
        debug!("\tProcessing symbol {} at position {}, last known at {}", sym, i, base);
        if base == N {
            let rank = unique.len();
            mtf.symbols[rank] = sym;
            mtf.encode(sym);    //==rank
            // initial distances are not ordered to support re-shuffle
            debug!("\t\tUnique => assigning rank {}, encoding {}", rank, i);
            let d = NumCast::from(i).unwrap();
            unique.push((sym,d));
        }else {
            let rank = mtf.encode(sym) as uint;
            if rank > 0 {
                debug!("\t\tRegular at rank {}, encoding {}", rank, i-base-rank-1);
                assert!(i >= base+rank+1);
                distances[base] = NumCast::from(i-base-rank-1).unwrap();
            }
        }
    }
    for (rank,&sym) in mtf.symbols.slice_to(unique.len()).iter().enumerate() {
        let base = last[sym];
        debug!("\tSweep symbol {} of rank {}, last known at {}, encoding {}", sym, rank, base, N-base-rank-1);
        assert!(N >= base+rank+1);
        distances[base] = NumCast::from(N-base-rank-1).unwrap();
    }
    assert_eq!(input.iter().zip(input.iter().skip(1)).zip(distances.iter()).
        position(|((&a,&b),d)| *d==filler && a!=b), None);
    unique
}

/// encode with "batteries included" for quick testing
pub fn encode_simple<D: Clone + Eq + NumCast>(input: &[Symbol]) -> (~[Symbol],~[D]) {
    let N = input.len();
    if N==0 {
        (~[],~[])
    }else   {
        let mut raw_dist: ~[D] = vec::from_elem(N, NumCast::from(0).unwrap());
        let pairs = encode(input, raw_dist, &mut MTF::new());
        let symbols = pairs.map(|&(sym,_)| sym);
        let init_iter = pairs.iter().map(|pair| { let (_, ref d) = *pair; d.clone() });
        let filler: D = NumCast::from(N).unwrap();
        // chain initial distances with intermediate ones
        let raw_iter = raw_dist.iter().filter_map(|d| if *d!=filler {Some(d.clone())} else {None});
        let mut combined = init_iter.chain(raw_iter);
        (symbols,combined.collect())
    }
}

/// Decode a block of distances with a list of initial symbols
pub fn decode(alphabet: Option<&[Symbol]>, output: &mut [Symbol], mtf: &mut MTF,
        fn_dist: |Symbol|->io::IoResult<uint>) -> io::IoResult<()> {
    let N = output.len();
    let mut next = [N, ..TotalSymbols];
    let E = match alphabet  {
        Some([]) => {
            // alphabet is empty
            assert_eq!(N,0);
            return Ok(())
        },
        Some([sym]) => {
            // there is only one known symbol
            for out in output.mut_iter()    {
                *out = sym;
            }
            return Ok(())
        }
        Some(list) => {
            // given fixed alphabet
            for (rank,&sym) in list.iter().enumerate()   {
                // initial distances are not ordered
                next[sym] = match fn_dist(sym) {
                    Ok(d) => d, // + (rank as Distance)
                    Err(e) => return Err(e)
                };
                mtf.symbols[rank] = sym;
                debug!("\tRegistering symbol {} of rank {} at position {}", sym, rank, next[sym]);
            }
            for rank in range(list.len(),TotalSymbols) {
                mtf.symbols[rank] = 0; //erazing unused symbols
            }
            list.len()
        },
        None => {
            // alphabet is large, total range of symbols is assumed
            for i in range(0,TotalSymbols) {
                next[i] = match fn_dist(i as Symbol) {
                    Ok(d) => d,
                    Err(e) => return Err(e)
                };
                mtf.symbols[i] = i as Symbol;
                debug!("\tRegistering symbol {} at position {}", i, next[i]);
            }
            TotalSymbols
        },
    };
    let mut i = 0u;
    while i<N {
        let sym = mtf.symbols[0];
        let stop = next[mtf.symbols[1]];
        debug!("\tFilling region [{}-{}) with symbol {}", i, stop, sym);
        while i<stop    {
            output[i] = sym;
            i += 1;
        }
        let future = match fn_dist(sym) {
            Ok(d) => stop + d,
            Err(e) => return Err(e)
        };
        debug!("\t\tLooking for future position {}", future);
        let mut rank = 1u;
        while rank < E && future+rank > next[mtf.symbols[rank]] {
            mtf.symbols[rank-1] = mtf.symbols[rank];
            rank += 1;
        }
        if rank<E {
            debug!("\t\tFound sym {} of rank {} at position {}", mtf.symbols[rank],
                rank, next[mtf.symbols[rank]]);
        }else {
            debug!("\t\tNot found");
        }
        mtf.symbols[rank-1] = sym;
        debug!("\t\tAssigning future pos {} for symbol {}", future+rank-1, sym);
        next[sym] = future+rank-1;
    }
    assert_eq!(next.iter().position(|&d| d<N || d>=N+E), None);
    assert_eq!(i, N);
    Ok(())
}

/// decode with "batteries included" for quick testing
pub fn decode_simple<D: ToPrimitive>(N: uint, alphabet: &[Symbol], distances: &[D]) -> ~[Symbol] {
    let mut output = vec::from_elem(N, 0 as Symbol);
    let mut di = 0u;
    decode(Some(alphabet), output.as_mut_slice(), &mut MTF::new(), |_sym| {
        di += 1;
        if di > distances.len() {
            Err(io::standard_error(io::EndOfFile))
        }else {
            Ok(distances[di-1].to_uint().unwrap())
        }
    }).unwrap();
    output
}

#[cfg(test)]
mod test {
    //use extra::test;
    use super::{encode_simple, decode_simple};

    fn roundtrip(bytes: &[u8]) {
        info!("Roundtrip DC of size {}", bytes.len());
        let (alphabet,distances) = encode_simple::<uint>(bytes);
        debug!("Roundtrip DC input: {:?}, alphabet: {:?}, distances: {:?}", bytes, alphabet, distances);
        let decoded = decode_simple(bytes.len(), alphabet.as_slice(), distances.as_slice());
        assert_eq!(decoded.as_slice(), bytes);
    }

    #[test]
    fn some_roundtrips() {
        roundtrip(bytes!("teeesst_dc"));
        roundtrip(bytes!(""));
        roundtrip(include_bin!("../data/test.txt"));
    }
}
<commit_msg>DC - fixed full alphabet decoding, added a test for it.<commit_after>/*!

DC (Distance Coding) forward and backward transformation.
Designed to be used on BWT block output for compression.

# Links

http://www.data-compression.info/Algorithms/DC/

# Example

```rust
use compress::bwt::dc;

let bytes = bytes!("abracadabra");
let (alphabet,distances) = dc::encode_simple::<uint>(bytes);
let decoded = dc::decode_simple(bytes.len(),
                                alphabet.as_slice(),
                                distances.as_slice());
```

# Credit

This is an original implementation.
Thanks to Edgar Binder for inventing DC!

*/

use std::{io, vec};
use super::mtf::MTF;

pub type Symbol = u8;
pub type Rank = u8;
pub static TotalSymbols: uint = 0x100;

/// encode a block of bytes 'input'
/// write output distance stream into 'distances'
/// return: unique bytes encountered in the order they appear
/// with the corresponding initial distances
pub fn encode<D: Clone + Eq + NumCast>(input: &[Symbol], distances: &mut [D], mtf: &mut MTF) -> ~[(Symbol,D)] {
    let N = input.len();
    assert_eq!(distances.len(), N);
    let mut last = [N, ..TotalSymbols];
    let mut unique: ~[(Symbol,D)] = ~[];
    let filler: D = NumCast::from(N).unwrap();
    for (i,&sym) in input.iter().enumerate() {
        distances[i] = filler.clone();
        let base = last[sym];
        last[sym] = i;
        debug!("\tProcessing symbol {} at position {}, last known at {}", sym, i, base);
        if base == N {
            let rank = unique.len();
            mtf.symbols[rank] = sym;
            mtf.encode(sym);    //==rank
            // initial distances are not ordered to support re-shuffle
            debug!("\t\tUnique => assigning rank {}, encoding {}", rank, i);
            let d = NumCast::from(i).unwrap();
            unique.push((sym,d));
        }else {
            let rank = mtf.encode(sym) as uint;
            if rank > 0 {
                debug!("\t\tRegular at rank {}, encoding {}", rank, i-base-rank-1);
                assert!(i >= base+rank+1);
                distances[base] = NumCast::from(i-base-rank-1).unwrap();
            }
        }
    }
    for (rank,&sym) in mtf.symbols.slice_to(unique.len()).iter().enumerate() {
        let base = last[sym];
        debug!("\tSweep symbol {} of rank {}, last known at {}, encoding {}", sym, rank, base, N-base-rank-1);
        assert!(N >= base+rank+1);
        distances[base] = NumCast::from(N-base-rank-1).unwrap();
    }
    assert_eq!(input.iter().zip(input.iter().skip(1)).zip(distances.iter()).
        position(|((&a,&b),d)| *d==filler && a!=b), None);
    unique
}

/// encode with "batteries included" for quick testing
pub fn encode_simple<D: Clone + Eq + NumCast>(input: &[Symbol]) -> (~[Symbol],~[D]) {
    let N = input.len();
    if N==0 {
        (~[],~[])
    }else   {
        let mut raw_dist: ~[D] = vec::from_elem(N, NumCast::from(0).unwrap());
        let pairs = encode(input, raw_dist, &mut MTF::new());
        let symbols = pairs.map(|&(sym,_)| sym);
        let init_iter = pairs.iter().map(|pair| { let (_, ref d) = *pair; d.clone() });
        let filler: D = NumCast::from(N).unwrap();
        // chain initial distances with intermediate ones
        let raw_iter = raw_dist.iter().filter_map(|d| if *d!=filler {Some(d.clone())} else {None});
        let mut combined = init_iter.chain(raw_iter);
        (symbols,combined.collect())
    }
}

/// Decode a block of distances with a list of initial symbols
pub fn decode(alphabet: Option<&[Symbol]>, output: &mut [Symbol], mtf: &mut MTF,
        fn_dist: |Symbol|->io::IoResult<uint>) -> io::IoResult<()> {
    let N = output.len();
    let mut next = [N, ..TotalSymbols];
    let E = match alphabet  {
        Some([]) => {
            // alphabet is empty
            assert_eq!(N,0);
            return Ok(())
        },
        Some([sym]) => {
            // there is only one known symbol
            for out in output.mut_iter()    {
                *out = sym;
            }
            return Ok(())
        }
        Some(list) => {
            // given fixed alphabet
            for (rank,&sym) in list.iter().enumerate()   {
                // initial distances are not ordered
                next[sym] = match fn_dist(sym) {
                    Ok(d) => d, // + (rank as Distance)
                    Err(e) => return Err(e)
                };
                mtf.symbols[rank] = sym;
                debug!("\tRegistering symbol {} of rank {} at position {}", sym, rank, next[sym]);
            }
            for rank in range(list.len(),TotalSymbols) {
                mtf.symbols[rank] = 0; //erazing unused symbols
            }
            list.len()
        },
        None => {
            // alphabet is large, total range of symbols is assumed
            for i in range(0,TotalSymbols) {
                next[i] = match fn_dist(i as Symbol) {
                    Ok(d) => d,
                    Err(e) => return Err(e)
                };
                mtf.symbols[i] = i as Symbol;
                debug!("\tRegistering symbol {} at position {}", i, next[i]);
            }
            // sort ranks by first occurrence
            mtf.symbols.mut_slice_to(TotalSymbols).sort_by(|&a,&b| next[a].cmp(&next[b]));
            TotalSymbols
        },
    };
    let mut i = 0u;
    while i<N {
        let sym = mtf.symbols[0];
        let stop = next[mtf.symbols[1]];
        debug!("\tFilling region [{}-{}) with symbol {}", i, stop, sym);
        while i<stop    {
            output[i] = sym;
            i += 1;
        }
        let future = match fn_dist(sym) {
            Ok(d) => stop + d,
            Err(e) => return Err(e)
        };
        debug!("\t\tLooking for future position {}", future);
        assert!(future <= N);
        let mut rank = 1u;
        while rank < E && future+rank > next[mtf.symbols[rank]] {
            mtf.symbols[rank-1] = mtf.symbols[rank];
            rank += 1;
        }
        if rank < E {
            debug!("\t\tFound sym {} of rank {} at position {}", mtf.symbols[rank],
                rank, next[mtf.symbols[rank]]);
        }else {
            debug!("\t\tNot found");
        }
        mtf.symbols[rank-1] = sym;
        debug!("\t\tAssigning future pos {} for symbol {}", future+rank-1, sym);
        next[sym] = future+rank-1;
    }
    assert_eq!(next.iter().position(|&d| d<N || d>=N+E), None);
    assert_eq!(i, N);
    Ok(())
}

/// decode with "batteries included" for quick testing
pub fn decode_simple<D: ToPrimitive>(N: uint, alphabet: &[Symbol], distances: &[D]) -> ~[Symbol] {
    let mut output = vec::from_elem(N, 0 as Symbol);
    let mut di = 0u;
    decode(Some(alphabet), output.as_mut_slice(), &mut MTF::new(), |_sym| {
        di += 1;
        if di > distances.len() {
            Err(io::standard_error(io::EndOfFile))
        }else {
            Ok(distances[di-1].to_uint().unwrap())
        }
    }).unwrap();
    output
}

#[cfg(test)]
mod test {
    use std;

    fn roundtrip(bytes: &[u8]) {
        info!("Roundtrip DC of size {}", bytes.len());
        let (alphabet,distances) = super::encode_simple::<uint>(bytes);
        debug!("Roundtrip DC input: {:?}, alphabet: {:?}, distances: {:?}", bytes, alphabet, distances);
        let decoded = super::decode_simple(bytes.len(), alphabet.as_slice(), distances.as_slice());
        assert_eq!(decoded.as_slice(), bytes);
    }

    fn roundtrip_full_alphabet(bytes: &[u8]) {
        let N = bytes.len();
        info!("Roundtrip DC (full alphabet) of size {}", N);
        let mut mtf = super::MTF::new();
        // encoding with full alphabet
        let mut raw_dist = std::vec::from_elem(N, 0u);
        let pairs = super::encode(bytes, raw_dist, &mut mtf);
        let mut alphabet = std::vec::from_elem(0x100, N);
        for &(sym,dist) in pairs.iter() {
            alphabet[sym] = dist;
        }
        let raw_iter = raw_dist.iter().filter(|&d| *d!=N);
        let distances = alphabet.iter().chain(raw_iter).to_owned_vec();
        // decoding with full alphabet
        let mut decoded = std::vec::from_elem(N, 0 as super::Symbol);
        let mut di = 0u;
        super::decode(None, decoded.as_mut_slice(), &mut mtf, |_sym| {
            di += 1;
            Ok(distances[di-1].to_uint().unwrap())
        }).unwrap();
        // comparing with input
        assert_eq!(decoded.as_slice(), bytes);
    }

    #[test]
    fn roundtrips_short() {
        roundtrip(bytes!("teeesst_dc"));
        roundtrip(bytes!(""));
        roundtrip(include_bin!("../data/test.txt"));
    }

    #[test]
    fn roundtrips_long() {
        roundtrip_full_alphabet(std::iter::range_inclusive(0u8, 0xFFu8).to_owned_vec());
    }
}
<|endoftext|>


<commit_before>#![feature(custom_test_frameworks)]
// Custom test runner, to avoid libtest being wrapped around compiletest which wraps libtest.
#![test_runner(test_runner)]

use std::path::PathBuf;
use std::env;

use compiletest_rs as compiletest;
use colored::*;

fn miri_path() -> PathBuf {
    if rustc_test_suite().is_some() {
        PathBuf::from(option_env!("MIRI_PATH").unwrap())
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/miri"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn run_tests(mode: &str, path: &str, target: &str, mut flags: Vec<String>) {
    // Some flags we always want.
    if rustc_test_suite().is_none() {
      // Only `-Dwarnings` on the Miri side to make the rustc toolstate management less painful.
      // (We often get warnings when e.g. a feature gets stabilized or some lint gets added/improved.)
      flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
    }
    flags.push("--edition 2018".to_owned());
    if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") {
        flags.push(format!("--sysroot {}", sysroot));
    }

    // The rest of the configuration.
    let mut config = compiletest::Config::default().tempdir();
    config.mode = mode.parse().expect("Invalid mode");
    config.rustc_path = miri_path();
    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.filter = env::args().nth(1);
    config.host = get_host();
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.target_rustcflags = Some(flags.join(" "));
    compiletest::run_tests(&config);
}

fn compile_fail(path: &str, target: &str, opt: bool) {
    let opt_str = if opt { " with optimizations" } else { "" };
    eprintln!("{}", format!(
        "## Running compile-fail tests in {} against miri for target {}{}",
        path,
        target,
        opt_str
    ).green().bold());

    let mut flags = Vec::new();
    if opt {
        // Optimizing too aggressivley makes UB detection harder, but test at least
        // the default value.
        // FIXME: Opt level 3 ICEs during stack trace generation.
        flags.push("-Zmir-opt-level=1".to_owned());
    }

    run_tests("compile-fail", path, target, flags);
}

fn miri_pass(path: &str, target: &str, opt: bool) {
    let opt_str = if opt { " with optimizations" } else { "" };
    eprintln!("{}", format!(
        "## Running run-pass tests in {} against miri for target {}{}",
        path,
        target,
        opt_str
    ).green().bold());

    let mut flags = Vec::new();
    if opt {
        flags.push("-Zmir-opt-level=3".to_owned());
    }

    run_tests("ui", path, target, flags);
}

fn get_host() -> String {
    let rustc = rustc_test_suite().unwrap_or(PathBuf::from("rustc"));
    let rustc_version = std::process::Command::new(rustc)
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let rustc_version = std::str::from_utf8(&rustc_version).expect("rustc -vV is not utf8");
    let version_meta = rustc_version::version_meta_for(&rustc_version)
        .expect("failed to parse rustc version info");
    version_meta.host
}

fn get_target() -> String {
    std::env::var("MIRI_TEST_TARGET").unwrap_or_else(|_| get_host())
}

fn run_pass_miri(opt: bool) {
    miri_pass("tests/run-pass", &get_target(), opt);
}

fn compile_fail_miri(opt: bool) {
    compile_fail("tests/compile-fail", &get_target(), opt);
    if rustc_test_suite().is_none() {
        // FIXME: Some tests disabled in rustc test suite because
        // they run with a debug-assertion libstd which changes the errors.
        // We should build our own libstd for testing, see
        // <https://github.com/rust-lang/rust/issues/61833>.
        compile_fail("tests/compile-fail-norustc", &get_target(), opt);
    }
}

fn test_runner(_tests: &[&()]) {
    run_pass_miri(false);
    run_pass_miri(true);

    compile_fail_miri(false);
    compile_fail_miri(true);
}
<commit_msg>dedup code a bit<commit_after>#![feature(custom_test_frameworks)]
// Custom test runner, to avoid libtest being wrapped around compiletest which wraps libtest.
#![test_runner(test_runner)]

use std::path::PathBuf;
use std::env;

use compiletest_rs as compiletest;
use colored::*;

fn miri_path() -> PathBuf {
    if rustc_test_suite().is_some() {
        PathBuf::from(option_env!("MIRI_PATH").unwrap())
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/miri"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn run_tests(mode: &str, path: &str, target: &str, mut flags: Vec<String>) {
    let in_rustc_test_suite = rustc_test_suite().is_some();
    // Add some flags we always want.
    if !in_rustc_test_suite {
      // Only `-Dwarnings` on the Miri side to make the rustc toolstate management less painful.
      // (We often get warnings when e.g. a feature gets stabilized or some lint gets added/improved.)
      flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
    }
    flags.push("--edition 2018".to_owned());
    if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") {
        flags.push(format!("--sysroot {}", sysroot));
    }

    // The rest of the configuration.
    let mut config = compiletest::Config::default().tempdir();
    config.mode = mode.parse().expect("Invalid mode");
    config.rustc_path = miri_path();
    if in_rustc_test_suite {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.filter = env::args().nth(1);
    config.host = get_host();
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.target_rustcflags = Some(flags.join(" "));
    compiletest::run_tests(&config);
}

fn compile_fail(path: &str, target: &str, opt: bool) {
    let opt_str = if opt { " with optimizations" } else { "" };
    eprintln!("{}", format!(
        "## Running compile-fail tests in {} against miri for target {}{}",
        path,
        target,
        opt_str
    ).green().bold());

    let mut flags = Vec::new();
    if opt {
        // Optimizing too aggressivley makes UB detection harder, but test at least
        // the default value.
        // FIXME: Opt level 3 ICEs during stack trace generation.
        flags.push("-Zmir-opt-level=1".to_owned());
    }

    run_tests("compile-fail", path, target, flags);
}

fn miri_pass(path: &str, target: &str, opt: bool) {
    let opt_str = if opt { " with optimizations" } else { "" };
    eprintln!("{}", format!(
        "## Running run-pass tests in {} against miri for target {}{}",
        path,
        target,
        opt_str
    ).green().bold());

    let mut flags = Vec::new();
    if opt {
        flags.push("-Zmir-opt-level=3".to_owned());
    }

    run_tests("ui", path, target, flags);
}

fn get_host() -> String {
    let rustc = rustc_test_suite().unwrap_or(PathBuf::from("rustc"));
    let rustc_version = std::process::Command::new(rustc)
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let rustc_version = std::str::from_utf8(&rustc_version).expect("rustc -vV is not utf8");
    let version_meta = rustc_version::version_meta_for(&rustc_version)
        .expect("failed to parse rustc version info");
    version_meta.host
}

fn get_target() -> String {
    std::env::var("MIRI_TEST_TARGET").unwrap_or_else(|_| get_host())
}

fn run_pass_miri(opt: bool) {
    miri_pass("tests/run-pass", &get_target(), opt);
}

fn compile_fail_miri(opt: bool) {
    compile_fail("tests/compile-fail", &get_target(), opt);
    if rustc_test_suite().is_none() {
        // FIXME: Some tests disabled in rustc test suite because
        // they run with a debug-assertion libstd which changes the errors.
        // We should build our own libstd for testing, see
        // <https://github.com/rust-lang/rust/issues/61833>.
        compile_fail("tests/compile-fail-norustc", &get_target(), opt);
    }
}

fn test_runner(_tests: &[&()]) {
    run_pass_miri(false);
    run_pass_miri(true);

    compile_fail_miri(false);
    compile_fail_miri(true);
}
<|endoftext|>


<commit_before>//! The integration suite helpers.

use regex::Regex;
use std::process::Command;
use std::path::Path;
use std::collections::HashMap;
use std::str::FromStr;

/// List windows will give details about the active sessions in testing.
/// target: A string represented by the {named_session}:{named_window}
pub fn list_windows(target: &String) -> String {
    let output = Command::new("tmux")
                     .arg("list-windows")
                     .arg("-t")
                     .arg(target)
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn open_muxed(project: &String, project_root: &Path) -> () {
    println!("root: {}", project_root.display());
    let output = Command::new("./target/debug/muxed")
        .arg("-d")
        .arg("-p")
        .arg(format!("{}", project_root.display()))
        .arg(project)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}

pub fn kill_session(target: &String) -> () {
    Command::new("tmux")
        .arg("kill-session")
        .arg("-t")
        .arg(target)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

#[derive(Debug)]
pub struct TmuxSession {
    pub num_of_windows: usize,
    pub windows: HashMap<String, HashMap<String, usize>>
}

impl TmuxSession {
    pub fn from_string(results: &String) -> TmuxSession {
        let window_name = Regex::new(r":\s(\w*)[$\*-]?\s+\(").unwrap();

        let lines: Vec<&str> = results.split("\n").collect();
        let (_, window_lines) = lines.split_last().unwrap();

        let mut windows: HashMap<String, HashMap<String, usize>> = HashMap::new();
        let mut h = HashMap::new();

        for line in window_lines {
            for cap in window_name.captures_iter(line) {
                let name = cap.at(1).unwrap();
                h.insert("Panes".to_string(), TmuxSession::count_panes(line));
                windows.insert(name.to_string(), h.clone());
            }
        }

        TmuxSession {
          num_of_windows: window_lines.len(),
          windows: windows
        }
    }

    pub fn count_panes(line: &str) -> usize {
        let panes = Regex::new(r"\((\d*) panes\)").unwrap();
        let mut num: &str = "";

        for cap in panes.captures_iter(line) {
            num = cap.at(1).unwrap_or("0");
        }

        usize::from_str(num).unwrap()
    }
}

#[test]
fn count_panes_returns_two() {
    let num = TmuxSession::count_panes("1: ssh (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0");
    assert_eq!(num, 2)
}

#[test]
fn count_panes_returns_one() {
    let num = TmuxSession::count_panes("1: ssh (1 panes) [173x42] [layout b5bd,173x42,0,0,0] @0");
    assert_eq!(num, 1)
}

#[test]
fn parses_with_trailing_whitespace_after_window_name() {
    let config = "1: ssh  (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_previous_flag() {
    let config = "1: ssh- (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_dollar_sign_flag() {
    let config = "1: ssh$ (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_window_flag() {
    let config = "1: ssh* (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn count_three_windows() {
    let config = "1: ssh  (1 panes) [173x42] [layout b5bd,173x42,0,0,0] @0
                  2: vim- (1 panes) [173x42] [layout b5be,173x42,0,0,1] @1
                  3: bash* (2 panes) [173x42] [layout b5bf,173x42,0,0,2] @2 (active)\n";
    let num = TmuxSession::from_string(&config.to_string()).num_of_windows;
    assert_eq!(num, 3)
}

#[test]
fn count_four_total_panes() {
    let config = "1: ssh  (1 panes) [173x42] [layout b5bd,173x42,0,0,0] @0
                  2: vim- (1 panes) [173x42] [layout b5be,173x42,0,0,1] @1
                  3: bash* (2 panes) [173x42] [layout b5bf,173x42,0,0,2] @2 (active)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let num = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    let num1 = session.windows.get("vim").unwrap().get("Panes").unwrap().to_owned();
    let num2 = session.windows.get("bash").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(num.to_owned(), 1);
    assert_eq!(num1.to_owned(), 1);
    assert_eq!(num2.to_owned(), 2)
}
<commit_msg>No need to call to_owned()<commit_after>//! The integration suite helpers.

use regex::Regex;
use std::process::Command;
use std::path::Path;
use std::collections::HashMap;
use std::str::FromStr;

/// List windows will give details about the active sessions in testing.
/// target: A string represented by the {named_session}:{named_window}
pub fn list_windows(target: &String) -> String {
    let output = Command::new("tmux")
                     .arg("list-windows")
                     .arg("-t")
                     .arg(target)
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn open_muxed(project: &String, project_root: &Path) -> () {
    println!("root: {}", project_root.display());
    let output = Command::new("./target/debug/muxed")
        .arg("-d")
        .arg("-p")
        .arg(format!("{}", project_root.display()))
        .arg(project)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}

pub fn kill_session(target: &String) -> () {
    Command::new("tmux")
        .arg("kill-session")
        .arg("-t")
        .arg(target)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

#[derive(Debug)]
pub struct TmuxSession {
    pub num_of_windows: usize,
    pub windows: HashMap<String, HashMap<String, usize>>
}

impl TmuxSession {
    pub fn from_string(results: &String) -> TmuxSession {
        let window_name = Regex::new(r":\s(\w*)[$\*-]?\s+\(").unwrap();

        let lines: Vec<&str> = results.split("\n").collect();
        let (_, window_lines) = lines.split_last().unwrap();

        let mut windows: HashMap<String, HashMap<String, usize>> = HashMap::new();
        let mut h = HashMap::new();

        for line in window_lines {
            for cap in window_name.captures_iter(line) {
                let name = cap.at(1).unwrap();
                h.insert("Panes".to_string(), TmuxSession::count_panes(line));
                windows.insert(name.to_string(), h.clone());
            }
        }

        TmuxSession {
          num_of_windows: window_lines.len(),
          windows: windows
        }
    }

    pub fn count_panes(line: &str) -> usize {
        let panes = Regex::new(r"\((\d*) panes\)").unwrap();
        let mut num: &str = "";

        for cap in panes.captures_iter(line) {
            num = cap.at(1).unwrap_or("0");
        }

        usize::from_str(num).unwrap()
    }
}

#[test]
fn count_panes_returns_two() {
    let num = TmuxSession::count_panes("1: ssh (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0");
    assert_eq!(num, 2)
}

#[test]
fn count_panes_returns_one() {
    let num = TmuxSession::count_panes("1: ssh (1 panes) [173x42] [layout b5bd,173x42,0,0,0] @0");
    assert_eq!(num, 1)
}

#[test]
fn parses_with_trailing_whitespace_after_window_name() {
    let config = "1: ssh  (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_previous_flag() {
    let config = "1: ssh- (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_dollar_sign_flag() {
    let config = "1: ssh$ (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_window_flag() {
    let config = "1: ssh* (2 panes) [173x42] [layout b5bd,173x42,0,0,0] @0\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn count_three_windows() {
    let config = "1: ssh  (1 panes) [173x42] [layout b5bd,173x42,0,0,0] @0
                  2: vim- (1 panes) [173x42] [layout b5be,173x42,0,0,1] @1
                  3: bash* (2 panes) [173x42] [layout b5bf,173x42,0,0,2] @2 (active)\n";
    let num = TmuxSession::from_string(&config.to_string()).num_of_windows;
    assert_eq!(num, 3)
}

#[test]
fn count_four_total_panes() {
    let config = "1: ssh  (1 panes) [173x42] [layout b5bd,173x42,0,0,0] @0
                  2: vim- (1 panes) [173x42] [layout b5be,173x42,0,0,1] @1
                  3: bash* (2 panes) [173x42] [layout b5bf,173x42,0,0,2] @2 (active)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let num = session.windows.get("ssh").unwrap().get("Panes").unwrap().to_owned();
    let num1 = session.windows.get("vim").unwrap().get("Panes").unwrap().to_owned();
    let num2 = session.windows.get("bash").unwrap().get("Panes").unwrap().to_owned();
    assert_eq!(num, 1);
    assert_eq!(num1, 1);
    assert_eq!(num2, 2)
}
<|endoftext|>


<commit_before>use memory::{MemoryBlock, Size, CellPosition};

pub type Operations = Vec<Operation>;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operation {
    /// Denotes a "block" of operations
    /// Any allocations in this block will be freed at the end of the block
    Block {
        body: Operations,
    },

    /// Allocates the given size in bytes on the tape so that it is not used by any other code
    /// accidentally. The addr is generated automatically and represents the position which will
    /// eventually be determined when the memory layout is generated. Nothing is guaranteed about
    /// the position other than that `size` consecutive cells including the position will be
    /// available for use without conflicts. This is also used to ensure memory is automatically
    /// dropped at the end of its scope (stack frame).
    Allocate(MemoryBlock),

    /// While most allocations can be dropped at the end of their scope, temporary cells
    /// should be dropped as soon as possible so that they are available in the memory
    /// layout again as soon as possible
    /// This way we can avoid a lot of unnecessary move operations over cells
    /// that aren't being used anymore
    /// While this could be an optimization as well, temporary cells in particular are
    /// *known* to have this property since we generate temporary cells in the compiler itself
    /// The temporary cells are guaranteed to last for the duration of the given body
    /// They are then freed immediately afterwards
    TempAllocate {
        // The memory block used as temporary memory in the provided operations
        temp: MemoryBlock,
        body: Operations,
    },

    /// Frees the given memory id and all cells associated with it
    /// Typically not used unless an explicit free is necessary before the end of the scope
    /// Freeing means both marking those cells available and zeroing their values
    /// This memory block should not be used after this
    Free(MemoryBlock),

    /// Increment the value of the given cell by a certain amount (relative to whatever the
    /// current amount in the cell is)
    Increment {
        target: CellPosition,
        amount: usize,
    },

    /// Decrement the value of the given cell by a certain amount (relative to whatever the
    /// current amount in the cell is)
    Decrement {
        target: CellPosition,
        amount: usize,
    },

    /// Read bytes into the given memory block
    /// Note: this generates both read instructions and move right instructions
    Read {
        target: MemoryBlock,
    },

    /// Write bytes into the given memory block
    /// Note: this generates both write instructions and move right instructions
    Write {
        target: MemoryBlock,
    },

    /// Set the value of every cell inside the given memory block to zero
    /// Note: this generates instructions to zero the value and move to the right towards each
    /// consecutive cell
    Zero {
        target: MemoryBlock,
    },

    /// Loop with the given operations as the loop body
    /// cond is the cell position that represents the loop condition
    /// This will be moved to before the loop and at the end of the loop body
    /// It is up to the surrounding operations to determine when to evaluate the condition
    Loop {
        /// This field in particular is VERY important because it creates a guarantee about the
        /// position of the cell pointer both before and after a loop
        /// Without this, solving for the current position in order to generate
        /// movement instructions would be nearly impossible
        cond: CellPosition,
        body: Operations,
    },

    /// Copy `size` cells from the source cell to the target cell using a single temporary cell
    /// WARNING: If size is greater than the allocated size of either memory block, this can result
    /// in buffer overrun.
    Copy {
        source: CellPosition,
        target: CellPosition,
        size: Size,
    },

    /// Relocate the value at the source memory block to the target memory block
    /// leaving only zeros at the source memory block
    /// Both memory blocks must be the same size
    Relocate {
        source: MemoryBlock,
        target: MemoryBlock,
    },
}

impl Operation {
    pub fn increment_to_value(mem: MemoryBlock, value: &Vec<u8>) -> Operations {
        debug_assert!(mem.size() == value.len());

        value.iter().enumerate().map(|(i, &byte)| {
            Operation::Increment {
                target: mem.position_at(i),
                amount: byte as usize,
            }
        }).collect()
    }
}
<commit_msg>Updated increment/decrement to use u8 instead of usize since cells are byte-sized<commit_after>use memory::{MemoryBlock, Size, CellPosition};

pub type Operations = Vec<Operation>;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operation {
    /// Denotes a "block" of operations
    /// Any allocations in this block will be freed at the end of the block
    Block {
        body: Operations,
    },

    /// Allocates the given size in bytes on the tape so that it is not used by any other code
    /// accidentally. The addr is generated automatically and represents the position which will
    /// eventually be determined when the memory layout is generated. Nothing is guaranteed about
    /// the position other than that `size` consecutive cells including the position will be
    /// available for use without conflicts. This is also used to ensure memory is automatically
    /// dropped at the end of its scope (stack frame).
    Allocate(MemoryBlock),

    /// While most allocations can be dropped at the end of their scope, temporary cells
    /// should be dropped as soon as possible so that they are available in the memory
    /// layout again as soon as possible
    /// This way we can avoid a lot of unnecessary move operations over cells
    /// that aren't being used anymore
    /// While this could be an optimization as well, temporary cells in particular are
    /// *known* to have this property since we generate temporary cells in the compiler itself
    /// The temporary cells are guaranteed to last for the duration of the given body
    /// They are then freed immediately afterwards
    TempAllocate {
        // The memory block used as temporary memory in the provided operations
        temp: MemoryBlock,
        body: Operations,
    },

    /// Frees the given memory id and all cells associated with it
    /// Typically not used unless an explicit free is necessary before the end of the scope
    /// Freeing means both marking those cells available and zeroing their values
    /// This memory block should not be used after this
    Free(MemoryBlock),

    /// Increment the value of the given cell by a certain amount (relative to whatever the
    /// current amount in the cell is)
    Increment {
        target: CellPosition,
        // u8 since cells are byte-sized
        amount: u8,
    },

    /// Decrement the value of the given cell by a certain amount (relative to whatever the
    /// current amount in the cell is)
    Decrement {
        target: CellPosition,
        // u8 since cells are byte-sized
        amount: u8,
    },

    /// Read bytes into the given memory block
    /// Note: this generates both read instructions and move right instructions
    Read {
        target: MemoryBlock,
    },

    /// Write bytes into the given memory block
    /// Note: this generates both write instructions and move right instructions
    Write {
        target: MemoryBlock,
    },

    /// Set the value of every cell inside the given memory block to zero
    /// Note: this generates instructions to zero the value and move to the right towards each
    /// consecutive cell
    Zero {
        target: MemoryBlock,
    },

    /// Loop with the given operations as the loop body
    /// cond is the cell position that represents the loop condition
    /// This will be moved to before the loop and at the end of the loop body
    /// It is up to the surrounding operations to determine when to evaluate the condition
    Loop {
        /// This field in particular is VERY important because it creates a guarantee about the
        /// position of the cell pointer both before and after a loop
        /// Without this, solving for the current position in order to generate
        /// movement instructions would be nearly impossible
        cond: CellPosition,
        body: Operations,
    },

    /// Copy `size` cells from the source cell to the target cell using a single temporary cell
    /// WARNING: If size is greater than the allocated size of either memory block, this can result
    /// in buffer overrun.
    Copy {
        source: CellPosition,
        target: CellPosition,
        size: Size,
    },

    /// Relocate the value at the source memory block to the target memory block
    /// leaving only zeros at the source memory block
    /// Both memory blocks must be the same size
    Relocate {
        source: MemoryBlock,
        target: MemoryBlock,
    },
}

impl Operation {
    pub fn increment_to_value(mem: MemoryBlock, value: &Vec<u8>) -> Operations {
        debug_assert!(mem.size() == value.len());

        value.iter().enumerate().map(|(i, &byte)| {
            Operation::Increment {
                target: mem.position_at(i),
                amount: byte,
            }
        }).collect()
    }
}
<|endoftext|>


<commit_before>macro_rules! def_swap {
    ($swap:ident, $fn:ident) => {
        pub trait $swap {
            type Output;
            fn $fn(self) -> Self::Output;
        }
    };
}
def_swap!(Swap1, swap1);
def_swap!(Swap2, swap2);
def_swap!(Swap4, swap4);
def_swap!(Swap8, swap8);
def_swap!(Swap16, swap16);
def_swap!(Swap32, swap32);
def_swap!(Swap64, swap64);
pub trait AndNot {
    type Output;
    fn andnot(self, rhs: Self) -> Self::Output;
}
pub trait RotateWordsRight {
    type Output;
    fn rotate_words_right(self, i: u32) -> Self::Output;
}
pub trait SplatRotateRight {
    type Output;
    fn splat_rotate_right(self, i: u32) -> Self::Output;
}

#[cfg(feature = "packed_simd")]
#[macro_use]
extern crate packed_simd_crate;
#[cfg(feature = "packed_simd")]
pub mod packed_simd {
    use super::*;
    use core::ops::{Add, AddAssign, BitAnd, BitOr, BitXor, BitXorAssign};
    use packed_simd_crate::{u128x1, u128x2, u32x4, u64x4};
    impl AndNot for u128x2 {
        type Output = u128x2;
        #[inline(always)]
        fn andnot(self, rhs: Self) -> Self::Output {
            !self & rhs
        }
    }
    #[inline(always)]
    fn swap128(x: u128x1, m: u128, i: u32) -> u128x1 {
        let m = u128x1::new(m);
        ((x & m) >> i) | ((x << i) & m)
    }
    macro_rules! impl_swap {
        ($swap:ident, $fn:ident, $mask:expr, $n:expr) => {
            impl $swap for u128x1 {
                type Output = u128x1;
                #[inline(always)]
                fn $fn(self) -> Self::Output {
                    swap128(self, $mask, $n)
                }
            }
        };
    }
    impl_swap!(Swap1, swap1, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 1);
    impl_swap!(Swap2, swap2, 0xcccccccccccccccccccccccccccccccc, 2);
    impl_swap!(Swap4, swap4, 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0, 4);
    impl_swap!(Swap8, swap8, 0xff00ff00ff00ff00ff00ff00ff00ff00, 8);
    impl_swap!(Swap16, swap16, 0xffff0000ffff0000ffff0000ffff0000, 16);
    impl_swap!(Swap32, swap32, 0xffffffff00000000ffffffff00000000, 32);
    impl Swap64 for u128x1 {
        type Output = u128x1;
        #[inline(always)]
        fn swap64(self) -> Self::Output {
            (self << 64) | (self >> 64)
        }
    }
    macro_rules! impl_rotate_words_right {
        ($vec:ident) => {
            impl RotateWordsRight for $vec {
                type Output = Self;
                fn rotate_words_right(self, i: u32) -> Self::Output {
                    debug_assert_eq!(i & !3, 0);
                    match i & 3 {
                        0 => self,
                        1 => shuffle!(self, [3, 0, 1, 2]),
                        2 => shuffle!(self, [2, 3, 0, 1]),
                        3 => shuffle!(self, [1, 2, 3, 0]),
                        _ => unreachable!(),
                    }
                }
            }
        };
    }
    impl_rotate_words_right!(u32x4);
    impl_rotate_words_right!(u64x4);
    macro_rules! impl_splat_rotate_right {
        ($vec:ident, $word:ty) => {
            impl SplatRotateRight for $vec {
                type Output = Self;
                fn splat_rotate_right(self, i: u32) -> Self::Output {
                    self.rotate_right(Self::splat(i as $word))
                }
            }
        };
    }
    impl_splat_rotate_right!(u32x4, u32);
    impl_splat_rotate_right!(u64x4, u64);

    // TODO: macroize this for other types
    #[allow(non_camel_case_types)]
    #[derive(Copy, Clone)]
    pub struct u32x4x2(u32x4, u32x4);
    impl u32x4x2 {
        #[inline(always)]
        pub fn from_halves(a: u32x4, b: u32x4) -> Self {
            u32x4x2(a, b)
        }
        #[inline(always)]
        pub fn from_half(a: u32x4) -> Self {
            u32x4x2(a, u32x4::splat(0))
        }
        #[inline(always)]
        pub fn into_halves(self) -> (u32x4, u32x4) {
            (self.0, self.1)
        }
    }
    impl BitXor for u32x4x2 {
        type Output = u32x4x2;
        #[inline(always)]
        fn bitxor(self, rhs: Self) -> Self::Output {
            u32x4x2(self.0 ^ rhs.0, self.1 ^ rhs.1)
        }
    }
    impl BitOr for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn bitor(self, rhs: Self) -> Self::Output {
            u32x4x2(self.0 | rhs.0, self.1 | rhs.1)
        }
    }
    impl BitAnd for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn bitand(self, rhs: Self) -> Self::Output {
            u32x4x2(self.0 & rhs.0, self.1 & rhs.1)
        }
    }
    impl BitXorAssign for u32x4x2 {
        #[inline(always)]
        fn bitxor_assign(&mut self, rhs: Self) {
            self.0 = self.0 ^ rhs.0;
            self.1 = self.1 ^ rhs.1;
        }
    }
    impl Add for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn add(self, rhs: Self) -> Self::Output {
            u32x4x2(self.0 + rhs.0, self.1 + rhs.1)
        }
    }
    impl AddAssign for u32x4x2 {
        #[inline(always)]
        fn add_assign(&mut self, rhs: Self) {
            self.0 = self.0 + rhs.0;
            self.1 = self.1 + rhs.1;
        }
    }
    impl RotateWordsRight for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn rotate_words_right(self, i: u32) -> Self::Output {
            u32x4x2(self.0.rotate_words_right(i), self.1.rotate_words_right(i))
        }
    }
    impl SplatRotateRight for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn splat_rotate_right(self, i: u32) -> Self::Output {
            u32x4x2(self.0.splat_rotate_right(i), self.1.splat_rotate_right(i))
        }
    }
}
<commit_msg>crypto-simd +packed_simd: enable avx2 for u32x4x2<commit_after>macro_rules! def_swap {
    ($swap:ident, $fn:ident) => {
        pub trait $swap {
            type Output;
            fn $fn(self) -> Self::Output;
        }
    };
}
def_swap!(Swap1, swap1);
def_swap!(Swap2, swap2);
def_swap!(Swap4, swap4);
def_swap!(Swap8, swap8);
def_swap!(Swap16, swap16);
def_swap!(Swap32, swap32);
def_swap!(Swap64, swap64);
pub trait AndNot {
    type Output;
    fn andnot(self, rhs: Self) -> Self::Output;
}
pub trait RotateWordsRight {
    type Output;
    fn rotate_words_right(self, i: u32) -> Self::Output;
}
pub trait SplatRotateRight {
    type Output;
    fn splat_rotate_right(self, i: u32) -> Self::Output;
}

#[cfg(feature = "packed_simd")]
#[macro_use]
extern crate packed_simd_crate;
#[cfg(feature = "packed_simd")]
pub mod packed_simd {
    use super::*;
    use core::ops::{Add, AddAssign, BitAnd, BitOr, BitXor, BitXorAssign};
    use packed_simd_crate::{u128x1, u128x2, u32x4, u32x8, u64x4};
    impl AndNot for u128x2 {
        type Output = u128x2;
        #[inline(always)]
        fn andnot(self, rhs: Self) -> Self::Output {
            !self & rhs
        }
    }
    #[inline(always)]
    fn swap128(x: u128x1, m: u128, i: u32) -> u128x1 {
        let m = u128x1::new(m);
        ((x & m) >> i) | ((x << i) & m)
    }
    macro_rules! impl_swap {
        ($swap:ident, $fn:ident, $mask:expr, $n:expr) => {
            impl $swap for u128x1 {
                type Output = u128x1;
                #[inline(always)]
                fn $fn(self) -> Self::Output {
                    swap128(self, $mask, $n)
                }
            }
        };
    }
    impl_swap!(Swap1, swap1, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 1);
    impl_swap!(Swap2, swap2, 0xcccccccccccccccccccccccccccccccc, 2);
    impl_swap!(Swap4, swap4, 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0, 4);
    impl_swap!(Swap8, swap8, 0xff00ff00ff00ff00ff00ff00ff00ff00, 8);
    impl_swap!(Swap16, swap16, 0xffff0000ffff0000ffff0000ffff0000, 16);
    impl_swap!(Swap32, swap32, 0xffffffff00000000ffffffff00000000, 32);
    impl Swap64 for u128x1 {
        type Output = u128x1;
        #[inline(always)]
        fn swap64(self) -> Self::Output {
            (self << 64) | (self >> 64)
        }
    }
    macro_rules! impl_rotate_words_right {
        ($vec:ident) => {
            impl RotateWordsRight for $vec {
                type Output = Self;
                fn rotate_words_right(self, i: u32) -> Self::Output {
                    debug_assert_eq!(i & !3, 0);
                    match i & 3 {
                        0 => self,
                        1 => shuffle!(self, [3, 0, 1, 2]),
                        2 => shuffle!(self, [2, 3, 0, 1]),
                        3 => shuffle!(self, [1, 2, 3, 0]),
                        _ => unreachable!(),
                    }
                }
            }
        };
    }
    impl_rotate_words_right!(u32x4);
    impl_rotate_words_right!(u64x4);
    macro_rules! impl_splat_rotate_right {
        ($vec:ident, $word:ty) => {
            impl SplatRotateRight for $vec {
                type Output = Self;
                fn splat_rotate_right(self, i: u32) -> Self::Output {
                    self.rotate_right(Self::splat(i as $word))
                }
            }
        };
    }
    impl_splat_rotate_right!(u32x4, u32);
    impl_splat_rotate_right!(u64x4, u64);

    #[allow(non_camel_case_types)]
    #[derive(Copy, Clone)]
    pub struct u32x4x2(u32x8);
    impl u32x4x2 {
        #[inline(always)]
        pub fn from_halves(a: u32x4, b: u32x4) -> Self {
            u32x4x2(u32x8::new(
                a.extract(0),
                a.extract(1),
                a.extract(2),
                a.extract(3),
                b.extract(0),
                b.extract(1),
                b.extract(2),
                b.extract(3),
            ))
        }
        #[inline(always)]
        pub fn from_half(a: u32x4) -> Self {
            u32x4x2::from_halves(a, u32x4::splat(0))
        }
        #[inline(always)]
        pub fn into_halves(self) -> (u32x4, u32x4) {
            let a = u32x4::new(
                self.0.extract(0),
                self.0.extract(1),
                self.0.extract(2),
                self.0.extract(3),
            );
            let b = u32x4::new(
                self.0.extract(4),
                self.0.extract(5),
                self.0.extract(6),
                self.0.extract(7),
            );
            (a, b)
        }
    }
    impl BitXor for u32x4x2 {
        type Output = u32x4x2;
        #[inline(always)]
        fn bitxor(self, rhs: Self) -> Self::Output {
            u32x4x2(self.0 ^ rhs.0)
        }
    }
    impl BitOr for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn bitor(self, rhs: Self) -> Self::Output {
            u32x4x2(self.0 | rhs.0)
        }
    }
    impl BitAnd for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn bitand(self, rhs: Self) -> Self::Output {
            u32x4x2(self.0 & rhs.0)
        }
    }
    impl BitXorAssign for u32x4x2 {
        #[inline(always)]
        fn bitxor_assign(&mut self, rhs: Self) {
            self.0 ^= rhs.0;
        }
    }
    impl Add for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn add(self, rhs: Self) -> Self::Output {
            u32x4x2(self.0 + rhs.0)
        }
    }
    impl AddAssign for u32x4x2 {
        #[inline(always)]
        fn add_assign(&mut self, rhs: Self) {
            self.0 += rhs.0;
        }
    }
    impl RotateWordsRight for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn rotate_words_right(self, i: u32) -> Self::Output {
            match i {
                0 => self,
                1 => u32x4x2(shuffle!(self.0, [3, 0, 1, 2, 7, 4, 5, 6])),
                2 => u32x4x2(shuffle!(self.0, [2, 3, 0, 1, 6, 7, 4, 5])),
                3 => u32x4x2(shuffle!(self.0, [1, 2, 3, 0, 5, 6, 7, 4])),
                _ => panic!("rotate_words_right index must be in the range 0..4"),
            }
        }
    }
    impl SplatRotateRight for u32x4x2 {
        type Output = Self;
        #[inline(always)]
        fn splat_rotate_right(self, i: u32) -> Self::Output {
            u32x4x2(self.0.rotate_right(u32x8::splat(i)))
        }
    }
}
<|endoftext|>