<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod apply {
    use std::str;
    use std::path::Path;
    use std::io::{self, Read};
    use std::fs::File;
    use std::thread;
    use std::time;

    use butterfly::client::Client;
    use common::ui::{Status, UI};
    use hcore::crypto::{SymKey, BoxKeyPair};
    use hcore::service::ServiceGroup;
    use toml;

    use error::{Error, Result};

    pub fn start(
        ui: &mut UI,
        sg: &ServiceGroup,
        number: u64,
        file_path: Option<&Path>,
        peers: &Vec<String>,
        ring_key: Option<&SymKey>,
        user_pair: Option<&BoxKeyPair>,
        service_pair: Option<&BoxKeyPair>,
    ) -> Result<()> {
        ui.begin(
            format!("Applying configuration for {} incarnation {}", sg, number, ),
        )?;

        ui.status(
            Status::Creating,
            format!("service configuration"),
        )?;

        let mut body = Vec::new();

        match file_path {
            Some(p) => {
                let mut file = File::open(&p)?;
                file.read_to_end(&mut body)?;
            }
            None => {
                io::stdin().read_to_end(&mut body)?;
            }
        };

        match toml::de::from_slice::<toml::value::Value>(&body) {
            Ok(_) => {
                ui.status(
                    Status::Verified,
                    "this configuration is valid TOML",
                )?
            }
            Err(err) => {
                ui.fatal("Invalid TOML")?;
                ui.br()?;
                ui.warn(&err)?;
                ui.br()?;
                return Err(Error::TomlDeserializeError(err));
            }
        }

        let mut encrypted = false;
        if service_pair.is_some() && user_pair.is_some() {
            ui.status(
                Status::Encrypting,
                format!(
                    "TOML as {} for {}",
                    user_pair.unwrap().name_with_rev(),
                    service_pair.unwrap().name_with_rev()
                ),
            )?;
            body = user_pair.unwrap().encrypt(
                &body,
                Some(service_pair.unwrap()),
            )?;
            encrypted = true;
        }

        for peer in peers.iter() {
            ui.status(Status::Applying, format!("to peer {}", peer))?;
            let mut client = Client::new(peer, ring_key.map(|k| k.clone())).map_err(
                |e| {
                    Error::ButterflyError(format!("{}", e))
                },
            )?;
            client
                .send_service_config(sg.clone(), number, body.clone(), encrypted)
                .map_err(|e| Error::ButterflyError(format!("{}", e)))?;

            // please take a moment to weep over the following line
            // of code. We must sleep to allow messages to be sent
            // before freeing the socket to prevent loss.
            // see https://github.com/zeromq/libzmq/issues/1264
            thread::sleep(time::Duration::from_millis(100));
        }
        ui.end("Applied configuration")?;
        Ok(())
    }
}
<commit_msg>Fixes annoying warn during hab-butterfly compilation<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod apply {
    use std::path::Path;
    use std::io::{self, Read};
    use std::fs::File;
    use std::thread;
    use std::time;

    use butterfly::client::Client;
    use common::ui::{Status, UI};
    use hcore::crypto::{SymKey, BoxKeyPair};
    use hcore::service::ServiceGroup;
    use toml;

    use error::{Error, Result};

    pub fn start(
        ui: &mut UI,
        sg: &ServiceGroup,
        number: u64,
        file_path: Option<&Path>,
        peers: &Vec<String>,
        ring_key: Option<&SymKey>,
        user_pair: Option<&BoxKeyPair>,
        service_pair: Option<&BoxKeyPair>,
    ) -> Result<()> {
        ui.begin(
            format!("Applying configuration for {} incarnation {}", sg, number, ),
        )?;

        ui.status(
            Status::Creating,
            format!("service configuration"),
        )?;

        let mut body = Vec::new();

        match file_path {
            Some(p) => {
                let mut file = File::open(&p)?;
                file.read_to_end(&mut body)?;
            }
            None => {
                io::stdin().read_to_end(&mut body)?;
            }
        };

        match toml::de::from_slice::<toml::value::Value>(&body) {
            Ok(_) => {
                ui.status(
                    Status::Verified,
                    "this configuration is valid TOML",
                )?
            }
            Err(err) => {
                ui.fatal("Invalid TOML")?;
                ui.br()?;
                ui.warn(&err)?;
                ui.br()?;
                return Err(Error::TomlDeserializeError(err));
            }
        }

        let mut encrypted = false;
        if service_pair.is_some() && user_pair.is_some() {
            ui.status(
                Status::Encrypting,
                format!(
                    "TOML as {} for {}",
                    user_pair.unwrap().name_with_rev(),
                    service_pair.unwrap().name_with_rev()
                ),
            )?;
            body = user_pair.unwrap().encrypt(
                &body,
                Some(service_pair.unwrap()),
            )?;
            encrypted = true;
        }

        for peer in peers.iter() {
            ui.status(Status::Applying, format!("to peer {}", peer))?;
            let mut client = Client::new(peer, ring_key.map(|k| k.clone())).map_err(
                |e| {
                    Error::ButterflyError(format!("{}", e))
                },
            )?;
            client
                .send_service_config(sg.clone(), number, body.clone(), encrypted)
                .map_err(|e| Error::ButterflyError(format!("{}", e)))?;

            // please take a moment to weep over the following line
            // of code. We must sleep to allow messages to be sent
            // before freeing the socket to prevent loss.
            // see https://github.com/zeromq/libzmq/issues/1264
            thread::sleep(time::Duration::from_millis(100));
        }
        ui.end("Applied configuration")?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>use super::*;
use crate::client::Context;
use crate::model::channel::Message;
use uwl::Stream;

pub mod map;

use map::{CommandMap, GroupMap, ParseMap};

use std::borrow::Cow;

#[inline]
fn to_lowercase<'a>(config: &Configuration, s: &'a str) -> Cow<'a, str> {
    if config.case_insensitive {
        Cow::Owned(s.to_lowercase())
    } else {
        Cow::Borrowed(s)
    }
}

/// Parse a mention in the message that is of either the direct (`<@id>`) or nickname (`<@!id>`) syntax,
/// and compare the encoded `id` with the id from [`Configuration::on_mention`] for a match.
/// Returns `Some(<id>)` on success, `None` otherwise.
///
/// [`Configuration::on_mention`]: ../struct.Configuration.html#method.on_mention
pub fn mention<'a>(stream: &mut Stream<'a>, config: &Configuration) -> Option<&'a str> {
    let on_mention = config.on_mention.as_ref().map(String::as_str)?;

    let start = stream.offset();

    if !stream.eat("<@") {
        return None;
    }

    // Optional.
    stream.eat("!");

    let id = stream.take_while(|b| b.is_ascii_digit());

    if !stream.eat(">") {
        // Backtrack to where we were.
        stream.set(start);

        return None;
    }

    if id == on_mention {
        Some(id)
    } else {
        stream.set(start);

        None
    }
}

fn find_prefix<'a>(
    ctx: &mut Context,
    msg: &Message,
    config: &Configuration,
    stream: &Stream<'a>,
) -> Option<Cow<'a, str>> {
    let try_match = |prefix: &str| {
        let peeked = stream.peek_for_char(prefix.chars().count());
        let peeked = to_lowercase(config, peeked);

        if prefix == &peeked {
            Some(peeked)
        } else {
            None
        }
    };

    for f in &config.dynamic_prefixes {
        if let Some(p) = f(ctx, msg) {
            if let Some(p) = try_match(&p) {
                return Some(p);
            }
        }
    }

    config.prefixes.iter().find_map(|p| try_match(&p))
}

/// Parse a prefix in the message.
///
/// The "prefix" may be one of the following:
/// - A mention (`<@id>`/`<@!id>`)
/// - A dynamically constructed prefix ([`Configuration::dynamic_prefix`])
/// - A static prefix ([`Configuration::prefix`])
/// - Nothing
///
/// In all cases, whitespace after the prefix is cleared.
///
/// [`Configuration::dynamic_prefix`]: ../struct.Configuration.html#method.dynamic_prefix
/// [`Configuration::prefix`]: ../struct.Configuration.html#method.prefix
pub fn prefix<'a>(
    ctx: &mut Context,
    msg: &Message,
    stream: &mut Stream<'a>,
    config: &Configuration,
) -> Option<Cow<'a, str>> {
    if let Some(id) = mention(stream, config) {
        stream.take_while_char(|c| c.is_whitespace());

        return Some(Cow::Borrowed(id));
    }

    let prefix = find_prefix(ctx, msg, config, stream);

    if let Some(prefix) = &prefix {
        stream.increment(prefix.len());
    }

    if config.with_whitespace.prefixes {
        stream.take_while_char(|c| c.is_whitespace());
    }

    prefix
}

/// Checked per valid group or command in the message.
fn check_discrepancy(
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    options: &impl CommonOptions,
) -> Result<(), DispatchError> {
    if options.owners_only() && !config.owners.contains(&msg.author.id) {
        return Err(DispatchError::OnlyForOwners);
    }

    if options.only_in() == OnlyIn::Dm && !msg.is_private() {
        return Err(DispatchError::OnlyForDM);
    }

    if (!config.allow_dm || options.only_in() == OnlyIn::Guild) && msg.is_private() {
        return Err(DispatchError::OnlyForGuilds);
    }

    #[cfg(feature = "cache")]
    {
        if let Some(guild_id) = msg.guild_id {
            let guild = match guild_id.to_guild_cached(&ctx) {
                Some(g) => g,
                None => return Ok(()),
            };

            let guild = guild.read();

            let perms = guild.user_permissions_in(msg.channel_id, msg.author.id);

            if !perms.contains(*options.required_permissions())
                && !(options.owner_privilege() && config.owners.contains(&msg.author.id))
            {
                return Err(DispatchError::LackingPermissions(
                    *options.required_permissions(),
                ));
            }

            if let Some(member) = guild.members.get(&msg.author.id) {
                if !perms.administrator() && !has_correct_roles(options, &guild, &member) {
                    return Err(DispatchError::LackingRole);
                }
            }
        }
    }

    Ok(())
}

fn try_parse<M: ParseMap>(
    stream: &mut Stream<'_>,
    map: &M,
    by_space: bool,
    f: impl Fn(&str) -> String,
) -> (String, Option<M::Storage>) {
    if by_space {
        let n = f(stream.peek_until_char(|c| c.is_whitespace()));

        let o = map.get(&n);

        (n, o)
    } else {
        let mut n = f(stream.peek_for_char(map.max_length()));
        let mut o = None;

        for _ in 0..(map.max_length() - map.min_length()) {
            o = map.get(&n);

            if o.is_some() {
                break;
            }

            n.pop();
        }

        (n, o)
    }
}

fn parse_cmd(
    stream: &mut Stream<'_>,
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    map: &CommandMap,
) -> Result<&'static Command, ParseError> {
    let (n, r) = try_parse(stream, map, config.by_space, |s| {
        to_lowercase(config, s).into_owned()
    });

    if config.disabled_commands.contains(&n) {
        return Err(ParseError::Dispatch(DispatchError::CommandDisabled(n)));
    }

    if let Some((cmd, map)) = r {
        stream.increment(n.len());

        if config.with_whitespace.commands {
            stream.take_while_char(|c| c.is_whitespace());
        }

        check_discrepancy(ctx, msg, config, &cmd.options)?;

        if map.is_empty() {
            return Ok(cmd);
        }

        return match parse_cmd(stream, ctx, msg, config, &map) {
            Err(ParseError::UnrecognisedCommand(Some(_))) => Ok(cmd),
            res => res,
        };
    }

    Err(ParseError::UnrecognisedCommand(Some(n.to_string())))
}

fn parse_group(
    stream: &mut Stream<'_>,
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    map: &GroupMap,
) -> Result<(&'static CommandGroup, Arc<CommandMap>), ParseError> {
    let (n, o) = try_parse(stream, map, config.by_space, ToString::to_string);

    if let Some((group, map, commands)) = o {
        stream.increment(n.len());

        if config.with_whitespace.groups {
            stream.take_while_char(|c| c.is_whitespace());
        }

        check_discrepancy(ctx, msg, config, &group.options)?;

        if map.is_empty() {
            return Ok((group, commands));
        }

        return match parse_group(stream, ctx, msg, config, &map) {
            Err(ParseError::UnrecognisedCommand(None)) => Ok((group, commands)),
            res => res,
        };
    }

    Err(ParseError::UnrecognisedCommand(None))
}

#[inline]
fn handle_command(
    stream: &mut Stream<'_>,
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    map: &CommandMap,
    group: &'static CommandGroup,
) -> Result<Invoke, ParseError> {
    match parse_cmd(stream, ctx, msg, config, map) {
        Ok(command) => Ok(Invoke::Command { group, command }),
        Err(err) => match group.options.default_command {
            Some(command) => Ok(Invoke::Command { group, command }),
            None => Err(err),
        },
    }
}

#[inline]
fn handle_group(
    stream: &mut Stream<'_>,
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    map: &GroupMap,
) -> Result<Invoke, ParseError> {
    parse_group(stream, ctx, msg, config, map)
        .and_then(|(group, map)| handle_command(stream, ctx, msg, config, &map, group))
}

#[derive(Debug)]
pub enum ParseError {
    UnrecognisedCommand(Option<String>),
    Dispatch(DispatchError),
}

impl From<DispatchError> for ParseError {
    #[inline]
    fn from(err: DispatchError) -> Self {
        ParseError::Dispatch(err)
    }
}

/// Parse a command from the message.
///
/// The "command" may be:
/// 1. A *help command* that provides a friendly browsing interface of all groups and commands,
/// explaining what each of them are, how they are layed out and how to invoke them.
/// There can only one help command registered, but might have many names defined for invocation of itself.
///
/// 2. A command defined under another command or a group, which may also belong to another group and so on.
/// To invoke this command, all names and prefixes of its parent commands and groups must be specified before it.
pub fn command(
    ctx: &Context,
    msg: &Message,
    stream: &mut Stream<'_>,
    groups: &[(&'static CommandGroup, Map)],
    config: &Configuration,
    help_was_set: Option<&[&'static str]>,
) -> Result<Invoke, ParseError> {
    // Precedence is taken over commands named as one of the help names.
    if let Some(names) = help_was_set {
        for name in names {
            let n = to_lowercase(config, stream.peek_for_char(name.chars().count()));

            if name == &n {
                stream.increment(n.len());

                stream.take_while_char(|c| c.is_whitespace());

                return Ok(Invoke::Help(name));
            }
        }
    }

    let mut last = Err(ParseError::UnrecognisedCommand(None));

    for (group, map) in groups {
        match map {
            // Includes [group] itself.
            Map::WithPrefixes(map) => {
                let res = handle_group(stream, ctx, msg, config, map);

                if res.is_ok() {
                    return res;
                }

                last = res;
            }
            Map::Prefixless(subgroups, commands) => {
                let res = handle_group(stream, ctx, msg, config, subgroups);

                if res.is_ok() {
                    check_discrepancy(ctx, msg, config, &group.options)?;

                    return res;
                }

                let res = handle_command(stream, ctx, msg, config, commands, group);

                if res.is_ok() {
                    check_discrepancy(ctx, msg, config, &group.options)?;

                    return res;
                }

                last = res;
            }
        }
    }

    last
}

#[derive(Debug)]
pub enum Invoke {
    Command {
        group: &'static CommandGroup,
        command: &'static Command,
    },
    Help(&'static str),
}
<commit_msg>Convert dynamic prefixes to lowercase if desired<commit_after>use super::*;
use crate::client::Context;
use crate::model::channel::Message;
use uwl::Stream;

pub mod map;

use map::{CommandMap, GroupMap, ParseMap};

use std::borrow::Cow;

#[inline]
fn to_lowercase<'a>(config: &Configuration, s: &'a str) -> Cow<'a, str> {
    if config.case_insensitive {
        Cow::Owned(s.to_lowercase())
    } else {
        Cow::Borrowed(s)
    }
}

/// Parse a mention in the message that is of either the direct (`<@id>`) or nickname (`<@!id>`) syntax,
/// and compare the encoded `id` with the id from [`Configuration::on_mention`] for a match.
/// Returns `Some(<id>)` on success, `None` otherwise.
///
/// [`Configuration::on_mention`]: ../struct.Configuration.html#method.on_mention
pub fn mention<'a>(stream: &mut Stream<'a>, config: &Configuration) -> Option<&'a str> {
    let on_mention = config.on_mention.as_ref().map(String::as_str)?;

    let start = stream.offset();

    if !stream.eat("<@") {
        return None;
    }

    // Optional.
    stream.eat("!");

    let id = stream.take_while(|b| b.is_ascii_digit());

    if !stream.eat(">") {
        // Backtrack to where we were.
        stream.set(start);

        return None;
    }

    if id == on_mention {
        Some(id)
    } else {
        stream.set(start);

        None
    }
}

fn find_prefix<'a>(
    ctx: &mut Context,
    msg: &Message,
    config: &Configuration,
    stream: &Stream<'a>,
) -> Option<Cow<'a, str>> {
    let try_match = |prefix: &str| {
        let peeked = stream.peek_for_char(prefix.chars().count());
        let peeked = to_lowercase(config, peeked);

        if prefix == &peeked {
            Some(peeked)
        } else {
            None
        }
    };

    for f in &config.dynamic_prefixes {
        if let Some(p) = f(ctx, msg) {
            let p = to_lowercase(config, &p);
            if let Some(p) = try_match(&p) {
                return Some(p);
            }
        }
    }

    config.prefixes.iter().find_map(|p| try_match(&p))
}

/// Parse a prefix in the message.
///
/// The "prefix" may be one of the following:
/// - A mention (`<@id>`/`<@!id>`)
/// - A dynamically constructed prefix ([`Configuration::dynamic_prefix`])
/// - A static prefix ([`Configuration::prefix`])
/// - Nothing
///
/// In all cases, whitespace after the prefix is cleared.
///
/// [`Configuration::dynamic_prefix`]: ../struct.Configuration.html#method.dynamic_prefix
/// [`Configuration::prefix`]: ../struct.Configuration.html#method.prefix
pub fn prefix<'a>(
    ctx: &mut Context,
    msg: &Message,
    stream: &mut Stream<'a>,
    config: &Configuration,
) -> Option<Cow<'a, str>> {
    if let Some(id) = mention(stream, config) {
        stream.take_while_char(|c| c.is_whitespace());

        return Some(Cow::Borrowed(id));
    }

    let prefix = find_prefix(ctx, msg, config, stream);

    if let Some(prefix) = &prefix {
        stream.increment(prefix.len());
    }

    if config.with_whitespace.prefixes {
        stream.take_while_char(|c| c.is_whitespace());
    }

    prefix
}

/// Checked per valid group or command in the message.
fn check_discrepancy(
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    options: &impl CommonOptions,
) -> Result<(), DispatchError> {
    if options.owners_only() && !config.owners.contains(&msg.author.id) {
        return Err(DispatchError::OnlyForOwners);
    }

    if options.only_in() == OnlyIn::Dm && !msg.is_private() {
        return Err(DispatchError::OnlyForDM);
    }

    if (!config.allow_dm || options.only_in() == OnlyIn::Guild) && msg.is_private() {
        return Err(DispatchError::OnlyForGuilds);
    }

    #[cfg(feature = "cache")]
    {
        if let Some(guild_id) = msg.guild_id {
            let guild = match guild_id.to_guild_cached(&ctx) {
                Some(g) => g,
                None => return Ok(()),
            };

            let guild = guild.read();

            let perms = guild.user_permissions_in(msg.channel_id, msg.author.id);

            if !perms.contains(*options.required_permissions())
                && !(options.owner_privilege() && config.owners.contains(&msg.author.id))
            {
                return Err(DispatchError::LackingPermissions(
                    *options.required_permissions(),
                ));
            }

            if let Some(member) = guild.members.get(&msg.author.id) {
                if !perms.administrator() && !has_correct_roles(options, &guild, &member) {
                    return Err(DispatchError::LackingRole);
                }
            }
        }
    }

    Ok(())
}

fn try_parse<M: ParseMap>(
    stream: &mut Stream<'_>,
    map: &M,
    by_space: bool,
    f: impl Fn(&str) -> String,
) -> (String, Option<M::Storage>) {
    if by_space {
        let n = f(stream.peek_until_char(|c| c.is_whitespace()));

        let o = map.get(&n);

        (n, o)
    } else {
        let mut n = f(stream.peek_for_char(map.max_length()));
        let mut o = None;

        for _ in 0..(map.max_length() - map.min_length()) {
            o = map.get(&n);

            if o.is_some() {
                break;
            }

            n.pop();
        }

        (n, o)
    }
}

fn parse_cmd(
    stream: &mut Stream<'_>,
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    map: &CommandMap,
) -> Result<&'static Command, ParseError> {
    let (n, r) = try_parse(stream, map, config.by_space, |s| {
        to_lowercase(config, s).into_owned()
    });

    if config.disabled_commands.contains(&n) {
        return Err(ParseError::Dispatch(DispatchError::CommandDisabled(n)));
    }

    if let Some((cmd, map)) = r {
        stream.increment(n.len());

        if config.with_whitespace.commands {
            stream.take_while_char(|c| c.is_whitespace());
        }

        check_discrepancy(ctx, msg, config, &cmd.options)?;

        if map.is_empty() {
            return Ok(cmd);
        }

        return match parse_cmd(stream, ctx, msg, config, &map) {
            Err(ParseError::UnrecognisedCommand(Some(_))) => Ok(cmd),
            res => res,
        };
    }

    Err(ParseError::UnrecognisedCommand(Some(n.to_string())))
}

fn parse_group(
    stream: &mut Stream<'_>,
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    map: &GroupMap,
) -> Result<(&'static CommandGroup, Arc<CommandMap>), ParseError> {
    let (n, o) = try_parse(stream, map, config.by_space, ToString::to_string);

    if let Some((group, map, commands)) = o {
        stream.increment(n.len());

        if config.with_whitespace.groups {
            stream.take_while_char(|c| c.is_whitespace());
        }

        check_discrepancy(ctx, msg, config, &group.options)?;

        if map.is_empty() {
            return Ok((group, commands));
        }

        return match parse_group(stream, ctx, msg, config, &map) {
            Err(ParseError::UnrecognisedCommand(None)) => Ok((group, commands)),
            res => res,
        };
    }

    Err(ParseError::UnrecognisedCommand(None))
}

#[inline]
fn handle_command(
    stream: &mut Stream<'_>,
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    map: &CommandMap,
    group: &'static CommandGroup,
) -> Result<Invoke, ParseError> {
    match parse_cmd(stream, ctx, msg, config, map) {
        Ok(command) => Ok(Invoke::Command { group, command }),
        Err(err) => match group.options.default_command {
            Some(command) => Ok(Invoke::Command { group, command }),
            None => Err(err),
        },
    }
}

#[inline]
fn handle_group(
    stream: &mut Stream<'_>,
    ctx: &Context,
    msg: &Message,
    config: &Configuration,
    map: &GroupMap,
) -> Result<Invoke, ParseError> {
    parse_group(stream, ctx, msg, config, map)
        .and_then(|(group, map)| handle_command(stream, ctx, msg, config, &map, group))
}

#[derive(Debug)]
pub enum ParseError {
    UnrecognisedCommand(Option<String>),
    Dispatch(DispatchError),
}

impl From<DispatchError> for ParseError {
    #[inline]
    fn from(err: DispatchError) -> Self {
        ParseError::Dispatch(err)
    }
}

/// Parse a command from the message.
///
/// The "command" may be:
/// 1. A *help command* that provides a friendly browsing interface of all groups and commands,
/// explaining what each of them are, how they are layed out and how to invoke them.
/// There can only one help command registered, but might have many names defined for invocation of itself.
///
/// 2. A command defined under another command or a group, which may also belong to another group and so on.
/// To invoke this command, all names and prefixes of its parent commands and groups must be specified before it.
pub fn command(
    ctx: &Context,
    msg: &Message,
    stream: &mut Stream<'_>,
    groups: &[(&'static CommandGroup, Map)],
    config: &Configuration,
    help_was_set: Option<&[&'static str]>,
) -> Result<Invoke, ParseError> {
    // Precedence is taken over commands named as one of the help names.
    if let Some(names) = help_was_set {
        for name in names {
            let n = to_lowercase(config, stream.peek_for_char(name.chars().count()));

            if name == &n {
                stream.increment(n.len());

                stream.take_while_char(|c| c.is_whitespace());

                return Ok(Invoke::Help(name));
            }
        }
    }

    let mut last = Err(ParseError::UnrecognisedCommand(None));

    for (group, map) in groups {
        match map {
            // Includes [group] itself.
            Map::WithPrefixes(map) => {
                let res = handle_group(stream, ctx, msg, config, map);

                if res.is_ok() {
                    return res;
                }

                last = res;
            }
            Map::Prefixless(subgroups, commands) => {
                let res = handle_group(stream, ctx, msg, config, subgroups);

                if res.is_ok() {
                    check_discrepancy(ctx, msg, config, &group.options)?;

                    return res;
                }

                let res = handle_command(stream, ctx, msg, config, commands, group);

                if res.is_ok() {
                    check_discrepancy(ctx, msg, config, &group.options)?;

                    return res;
                }

                last = res;
            }
        }
    }

    last
}

#[derive(Debug)]
pub enum Invoke {
    Command {
        group: &'static CommandGroup,
        command: &'static Command,
    },
    Help(&'static str),
}
<|endoftext|>


<commit_before>#![allow(unstable)]
#![feature(box_syntax)]

use std::cell::RefCell;
use std::{io, vec};
use std::rc::Rc;
use std::iter::range;

static LONG_LIVED: &'static str = "foo";

#[test]
fn looping() {

    // FOR
    let mut c = 0;
    for _ in 0..10 {
        c += 1;
    }
    assert!(c == 10);

    // endless LOOP
    let mut c = 1;
    loop {
        if c % 10 == 0 {
            break
        }
        c += 1;
    }
    assert!(c == 10);

    let mut c = 1;
    // WHILE
    while c % 10 != 0 {
        c += 1;
    }
}

#[test]
fn compound_data() {
    struct Point {
        x: i32,
        y: i32,
    }

    let mut p = Point { x: 0, y: 0 };
    let mut o = Point { x: p.x, y: p.y };

    p.x = 5;
    o.x = 10;
    assert!(o.x != p.x);

    struct PointT(i32, i32);

    let p = PointT(5, 10);
    assert!(p.0 == 5 && p.1 == 10);

    struct Inches(f32);
    let i = Inches(25.0);

    assert_eq!(i.0, 25.0);
}

#[test]
fn enumerations() {
    #[derive(PartialEq)]
    enum Order {
        Less,
        Equal,
        Greater
    }

    fn cmp(x: i32, y: i32) -> Order {
        if x < y { Order::Less }
        else if x > y { Order::Greater }
        else { Order::Equal }
    }

    let o = cmp(1, 10);
    assert!(o == Order::Less);
    let res = match o {
        Order::Greater => "g",
        Order::Less => "l",
        Order::Equal => "e",
    };
    assert!(res == "l");

    #[derive(PartialEq)]
    enum OptionalInt {
        Value(i32),
        Nothing
    }

    let m = OptionalInt::Value(30);
    let n = match m {
        OptionalInt::Value(r) => r,
        OptionalInt::Nothing => 0,
    };
    assert!(n == 30);
    assert!(!(m == OptionalInt::Nothing));
}

#[test]
fn strings() {
    let s = "Hi";                   // This is a string slice
    assert!(s.len() == 2);

    let si = s.to_string();
    assert!(si.len() == s.len());
    assert!(si.ends_with("i"));

    // Actually, replace is read-only as it returns a new string
    // assert!(si.replace("Hi", "Ho").as_slice() == "Ho")
    assert!(s.replace("Hi", "Ho").as_slice() == "Ho")
}

#[test]
#[should_fail]
fn no_static_inference() {
    // Compiler cannot see at compile time that this wouldn't work
    // First I put in a signed integer, which gets converted to a unsigned
    // Second, it doesn't realize that the index is  out of bounds in any case
    let b = ["a", "b", "c"];
    assert!(b[-1] == "c");
}

#[test]
fn arrays() {
    let a = [1,2,3];
    assert!(a[0] == 1);

    let mut b = ["a", "b"];
    b[1] = LONG_LIVED;
    assert!(b[1] == LONG_LIVED);

    for item in b.iter() {
        println!("{}", item);
    }

    // compile time constant !
    const S: usize = 20;
    let mut a = [5; S];
    assert!(a.len() == S);

    // This scope is needed as we have an immutable borrow
    // but want to borrow a mutable later
    {
        let sl: &[i32] = a.slice(1,2);  // type given just to show it ... useful for fn ()
        assert!(sl.len() == 1);
        assert!(sl[0] == a[1]);
    }

    let sl2 = &mut a[0..5];
    assert!(sl2.len() == 5);
    sl2[0] = 0;
    assert!(sl2[0] == 0);
}

#[test]
fn vectors() {
    // it's convention to use vec![] instead of vec!()
    let b = vec![1,2,3];
    assert!(b.len() == 3);
    for item in b.into_iter() {
        println!("{:?}", item);
    }
    // Can't use b anymore ! into_iter() takes ownership out of vector
    // assert!(b.len() == 0);

    // vec!() is also possible - it's just how macros can be called in general
    let mut b = vec!(1,2);
    assert!(b.len() == 2);
    b.push(3);
    assert!(b.len() == 3);

    struct Single {
        stream: io::LineBufferedWriter<io::stdio::StdWriter>
    };

    // It seems structs are being mem-copied, ownership is not transferred.
    // How to deal with resource allocation.
    // This actually works
    let mut v = Single{stream: io::stderr()};
    let mut b = vec::Vec::new();
    b.push(v);

    // v was moved, an even though assign works ...
    v.stream = io::stdout();
    // you can't access a moved v ... is that supposed to be like that ?
    // The cool thing is that members make their parent structs non-copyable automatically.
    // v.stream.write(b"hello");

    struct SingleInt {
        x: i32
    }

    let mut b = vec::Vec::new();
    let mut v = SingleInt{x: 3};
    b.push(v);
    v.x = 4;
    assert!(b[0].x == 3);
}

#[test]
#[allow(dead_code)]
#[allow(unused_variables)]
fn ownership() {
    struct Car {
        name: String,
    }

    #[derive(Copy)]
    struct Wheel<'a> {
        owner: &'a Car,
    }

    static NUM_WHEELS: u8 = 4;
    let car = Car { name: "DeLorean".to_string() };

    for _ in range(0, NUM_WHEELS) {
        Wheel { owner: &car };
    }

    // Borrows are always fine - they are read-only !
    let wheels = [Wheel { owner: &car }; 4];

    let mut dyn_wheels = Vec::with_capacity(NUM_WHEELS as usize);
    for _ in range(0, NUM_WHEELS) {
        dyn_wheels.push(box Wheel { owner: &car });
    }

    let ocar = Rc::new(RefCell::new(Car { name: "Trabant".to_string() }));

    // Mutable reference only really work with RefCell and refcounts in this case
    // also means the car needs heap allocation, even though stack allocation should
    // be fine ... is there a better way to this ?
    struct OWheel {
        owner: Rc<RefCell<Car>>,
    }

    let mut wheels = Vec::new();
    for _ in range(0, NUM_WHEELS) {
        wheels.push(OWheel { owner: ocar.clone() });
    }

    // Car with replaceable wheels and backpointer of wheel to car
    struct OCar<'a> {
        wheels: [Wheel<'a>; 4]
    }

    // // // TODO: WITH Generics on Wheel !! Car should be OCar here
    // impl<'a> OCar<'a> {
    //     fn replace_wheel(&'a mut self, wheel_id: usize) -> Wheel {
    //         let mut previous = self.wheels[wheel_id];
    //         self.wheels[wheel_id] = Wheel { owner: self };
    //         previous
    //     }
    // }
}

#[test]
#[allow(unused_variables)]
fn advanced_patterns() {

    let x = 3;
    match x {
        1 | 2 => assert!(false, "Shouldn't be here"),
        _ => (),
    }

    match x {
        e @ 0 ... 3 => { format!("x is between 0 and incl. 3: {}", e); () },
        _ => assert!(false, "inclusive range expected"),
    }

    let x = Some(5);
    match x {
        Some(..) => (),
        None => assert!(false, "Should have some"),
    }

    // pattern guards use if
    match x {
        Some(v) if v == 5 => (),
        _ => assert!(false, "Should have made conditional match")
    }

    // destructuring pattern (implicit derefenece ... kind of)
    let y: &i32 = &x.unwrap();
    match y {
        &y => (),   // note that here x, is dereferenced, so we get a value // i32
    }

    // You can ask for a ref explicitly though
    match x {
        ref z => (), // &i32
    }

    let mut x = 5;
    match x {
        ref mut z => (), //&mut i32
    }

    struct Point {
        x: i32,
        y: i32,
    }

    // Destructure members of struct
    let mut p = Point {x: 1, y: 2};
    match p {
        Point { x: u, y: v } => p.x += p.y,
    }
    assert!(p.x == 3);

    // Destruction only some members
    match p{
        // without ref mut, we would get a copy of the POD
        Point { y: ref mut u, .. } => {*u += 5; ()},
    }
    assert!(p.y == 7);

    match p {
        ref mut m if m.x == 3 => m.x += 3,
        // m => (), this would move p, so it can't be used anymore
        _ => assert!(false),
    }
    assert!(p.x == 6);

    // you can also define you want a borrow right away
    match &mut p {
        m => m.x += 3,
    }

    // decomposition cannot be nested, so Some(Point(x: x, y: y)) won't work
    let mut p = Some(Point { x: 5, y: 10 } );
    match p {
        Some(ref mut p) => { p.x += p.y; () },  // p is &Point, *p.x is a way to access it
        None => assert!(false),
    }
    assert!(p.unwrap().x == 15);

    // Tuple destucturing !
    let mut t = (5, "foo", 24.0);

    match t {
        (ref mut x, _, _) if *x == 5 => *x += 5,
        (_, x, _) if x == "bar" => (),
        (_, _, _) => (),
    }
    assert!(t.0 == 10);

    // Array destructuring
    // NOTE: For arrays with any unkonwn size, .. works !
    // Tuples require you to do
    let mut a = [1, 2, 3];
    match &mut a {
        &mut [ref mut u, ref mut v, _] if *u == 1 && *v == 2 => {
            *u += 3;
            *v += 2 },
        &mut [..] => (),
        // _ => (), would be equivalent
    }
    assert!(a[0] == a[1]);

}

#[test]
fn methods() {

    const FROM_BASE: f32 = 2.54;

    #[derive(PartialEq)]
    struct Centimeters(f32);
    struct Inches(f32);

    impl Centimeters {
        fn from_inches(inch: &Inches) -> Centimeters {
            inch.to_cm()
        }
    }

    impl Inches {
        fn from_cm(cm: &Centimeters) -> Inches {
            Inches(cm.0 * FROM_BASE)
        }

        fn to_cm(&self) -> Centimeters {
            Centimeters(self.0 / FROM_BASE)
        }
    }

    let cm = Centimeters(20.0);
    let inch = Inches::from_cm(&cm);

    assert!(cm.0 == 20.0);
    assert!(cm == inch.to_cm());

    let cm = Centimeters::from_inches(&inch);
    assert!(cm == inch.to_cm());

    // deconstruction/matching of a NewType
    let Centimeters(myone) = cm;
    assert!(myone == cm.0);
}<commit_msg>closures<commit_after>#![allow(unstable)]
#![feature(box_syntax)]

use std::cell::RefCell;
use std::{io, vec};
use std::rc::Rc;
use std::iter::range;

static LONG_LIVED: &'static str = "foo";

#[test]
fn looping() {

    // FOR
    let mut c = 0;
    for _ in 0..10 {
        c += 1;
    }
    assert!(c == 10);

    // endless LOOP
    let mut c = 1;
    loop {
        if c % 10 == 0 {
            break
        }
        c += 1;
    }
    assert!(c == 10);

    let mut c = 1;
    // WHILE
    while c % 10 != 0 {
        c += 1;
    }
}

#[test]
fn compound_data() {
    struct Point {
        x: i32,
        y: i32,
    }

    let mut p = Point { x: 0, y: 0 };
    let mut o = Point { x: p.x, y: p.y };

    p.x = 5;
    o.x = 10;
    assert!(o.x != p.x);

    struct PointT(i32, i32);

    let p = PointT(5, 10);
    assert!(p.0 == 5 && p.1 == 10);

    struct Inches(f32);
    let i = Inches(25.0);

    assert_eq!(i.0, 25.0);
}

#[test]
fn enumerations() {
    #[derive(PartialEq)]
    enum Order {
        Less,
        Equal,
        Greater
    }

    fn cmp(x: i32, y: i32) -> Order {
        if x < y { Order::Less }
        else if x > y { Order::Greater }
        else { Order::Equal }
    }

    let o = cmp(1, 10);
    assert!(o == Order::Less);
    let res = match o {
        Order::Greater => "g",
        Order::Less => "l",
        Order::Equal => "e",
    };
    assert!(res == "l");

    #[derive(PartialEq)]
    enum OptionalInt {
        Value(i32),
        Nothing
    }

    let m = OptionalInt::Value(30);
    let n = match m {
        OptionalInt::Value(r) => r,
        OptionalInt::Nothing => 0,
    };
    assert!(n == 30);
    assert!(!(m == OptionalInt::Nothing));
}

#[test]
fn strings() {
    let s = "Hi";                   // This is a string slice
    assert!(s.len() == 2);

    let si = s.to_string();
    assert!(si.len() == s.len());
    assert!(si.ends_with("i"));

    // Actually, replace is read-only as it returns a new string
    // assert!(si.replace("Hi", "Ho").as_slice() == "Ho")
    assert!(s.replace("Hi", "Ho").as_slice() == "Ho")
}

#[test]
#[should_fail]
fn no_static_inference() {
    // Compiler cannot see at compile time that this wouldn't work
    // First I put in a signed integer, which gets converted to a unsigned
    // Second, it doesn't realize that the index is  out of bounds in any case
    let b = ["a", "b", "c"];
    assert!(b[-1] == "c");
}

#[test]
fn arrays() {
    let a = [1,2,3];
    assert!(a[0] == 1);

    let mut b = ["a", "b"];
    b[1] = LONG_LIVED;
    assert!(b[1] == LONG_LIVED);

    for item in b.iter() {
        println!("{}", item);
    }

    // compile time constant !
    const S: usize = 20;
    let mut a = [5; S];
    assert!(a.len() == S);

    // This scope is needed as we have an immutable borrow
    // but want to borrow a mutable later
    {
        let sl: &[i32] = a.slice(1,2);  // type given just to show it ... useful for fn ()
        assert!(sl.len() == 1);
        assert!(sl[0] == a[1]);
    }

    let sl2 = &mut a[0..5];
    assert!(sl2.len() == 5);
    sl2[0] = 0;
    assert!(sl2[0] == 0);
}

#[test]
fn vectors() {
    // it's convention to use vec![] instead of vec!()
    let b = vec![1,2,3];
    assert!(b.len() == 3);
    for item in b.into_iter() {
        println!("{:?}", item);
    }
    // Can't use b anymore ! into_iter() takes ownership out of vector
    // assert!(b.len() == 0);

    // vec!() is also possible - it's just how macros can be called in general
    let mut b = vec!(1,2);
    assert!(b.len() == 2);
    b.push(3);
    assert!(b.len() == 3);

    struct Single {
        stream: io::LineBufferedWriter<io::stdio::StdWriter>
    };

    // It seems structs are being mem-copied, ownership is not transferred.
    // How to deal with resource allocation.
    // This actually works
    let mut v = Single{stream: io::stderr()};
    let mut b = vec::Vec::new();
    b.push(v);

    // v was moved, an even though assign works ...
    v.stream = io::stdout();
    // you can't access a moved v ... is that supposed to be like that ?
    // The cool thing is that members make their parent structs non-copyable automatically.
    // v.stream.write(b"hello");

    struct SingleInt {
        x: i32
    }

    let mut b = vec::Vec::new();
    let mut v = SingleInt{x: 3};
    b.push(v);
    v.x = 4;
    assert!(b[0].x == 3);
}

#[test]
#[allow(dead_code)]
#[allow(unused_variables)]
fn ownership() {
    struct Car {
        name: String,
    }

    #[derive(Copy)]
    struct Wheel<'a> {
        owner: &'a Car,
    }

    static NUM_WHEELS: u8 = 4;
    let car = Car { name: "DeLorean".to_string() };

    for _ in range(0, NUM_WHEELS) {
        Wheel { owner: &car };
    }

    // Borrows are always fine - they are read-only !
    let wheels = [Wheel { owner: &car }; 4];

    let mut dyn_wheels = Vec::with_capacity(NUM_WHEELS as usize);
    for _ in range(0, NUM_WHEELS) {
        dyn_wheels.push(box Wheel { owner: &car });
    }

    let ocar = Rc::new(RefCell::new(Car { name: "Trabant".to_string() }));

    // Mutable reference only really work with RefCell and refcounts in this case
    // also means the car needs heap allocation, even though stack allocation should
    // be fine ... is there a better way to this ?
    struct OWheel {
        owner: Rc<RefCell<Car>>,
    }

    let mut wheels = Vec::new();
    for _ in range(0, NUM_WHEELS) {
        wheels.push(OWheel { owner: ocar.clone() });
    }

    // Car with replaceable wheels and backpointer of wheel to car
    struct OCar<'a> {
        wheels: [Wheel<'a>; 4]
    }

    // // // TODO: WITH Generics on Wheel !! Car should be OCar here
    // impl<'a> OCar<'a> {
    //     fn replace_wheel(&'a mut self, wheel_id: usize) -> Wheel {
    //         let mut previous = self.wheels[wheel_id];
    //         self.wheels[wheel_id] = Wheel { owner: self };
    //         previous
    //     }
    // }
}

#[test]
#[allow(unused_variables)]
fn advanced_patterns() {

    let x = 3;
    match x {
        1 | 2 => assert!(false, "Shouldn't be here"),
        _ => (),
    }

    match x {
        e @ 0 ... 3 => { format!("x is between 0 and incl. 3: {}", e); () },
        _ => assert!(false, "inclusive range expected"),
    }

    let x = Some(5);
    match x {
        Some(..) => (),
        None => assert!(false, "Should have some"),
    }

    // pattern guards use if
    match x {
        Some(v) if v == 5 => (),
        _ => assert!(false, "Should have made conditional match")
    }

    // destructuring pattern (implicit derefenece ... kind of)
    let y: &i32 = &x.unwrap();
    match y {
        &y => (),   // note that here x, is dereferenced, so we get a value // i32
    }

    // You can ask for a ref explicitly though
    match x {
        ref z => (), // &i32
    }

    let mut x = 5;
    match x {
        ref mut z => (), //&mut i32
    }

    struct Point {
        x: i32,
        y: i32,
    }

    // Destructure members of struct
    let mut p = Point {x: 1, y: 2};
    match p {
        Point { x: u, y: v } => p.x += p.y,
    }
    assert!(p.x == 3);

    // Destruction only some members
    match p{
        // without ref mut, we would get a copy of the POD
        Point { y: ref mut u, .. } => {*u += 5; ()},
    }
    assert!(p.y == 7);

    match p {
        ref mut m if m.x == 3 => m.x += 3,
        // m => (), this would move p, so it can't be used anymore
        _ => assert!(false),
    }
    assert!(p.x == 6);

    // you can also define you want a borrow right away
    match &mut p {
        m => m.x += 3,
    }

    // decomposition cannot be nested, so Some(Point(x: x, y: y)) won't work
    let mut p = Some(Point { x: 5, y: 10 } );
    match p {
        Some(ref mut p) => { p.x += p.y; () },  // p is &Point, *p.x is a way to access it
        None => assert!(false),
    }
    assert!(p.unwrap().x == 15);

    // Tuple destucturing !
    let mut t = (5, "foo", 24.0);

    match t {
        (ref mut x, _, _) if *x == 5 => *x += 5,
        (_, x, _) if x == "bar" => (),
        (_, _, _) => (),
    }
    assert!(t.0 == 10);

    // Array destructuring
    // NOTE: For arrays with any unkonwn size, .. works !
    // Tuples require you to do
    let mut a = [1, 2, 3];
    match &mut a {
        &mut [ref mut u, ref mut v, _] if *u == 1 && *v == 2 => {
            *u += 3;
            *v += 2 },
        &mut [..] => (),
        // _ => (), would be equivalent
    }
    assert!(a[0] == a[1]);

}

#[test]
fn methods() {

    const FROM_BASE: f32 = 2.54;

    #[derive(PartialEq)]
    struct Centimeters(f32);
    struct Inches(f32);

    impl Centimeters {
        fn from_inches(inch: &Inches) -> Centimeters {
            inch.to_cm()
        }
    }

    impl Inches {
        fn from_cm(cm: &Centimeters) -> Inches {
            Inches(cm.0 * FROM_BASE)
        }

        fn to_cm(&self) -> Centimeters {
            Centimeters(self.0 / FROM_BASE)
        }
    }

    let cm = Centimeters(20.0);
    let inch = Inches::from_cm(&cm);

    assert!(cm.0 == 20.0);
    assert!(cm == inch.to_cm());

    let cm = Centimeters::from_inches(&inch);
    assert!(cm == inch.to_cm());

    // deconstruction/matching of a NewType
    let Centimeters(myone) = cm;
    assert!(myone == cm.0);
}

#[test]
fn closures() {
    // note that THIS doesnt work: x + 1 - type inference fails I guess
    // borrow closure for read-only access: |&:|
    let add_one_ref = |&: x| { 1 + x };
    let explicit_add_one_ref = |&: x: i32| { x + 1 };
    let x = 1;

    assert!(add_one_ref(x) == 2);
    assert!(x == 1);
    assert!(explicit_add_one_ref(x) == 2);
    assert!(x == 1);

    // mutable borrow closure returns ownership after so: |&mut|
    let mut x = 1;
    {
        let mut add_one_to_x = |&mut:| -> i32 { x += 1; x };
        assert!(add_one_to_x() == 2);
        // assert!(add_one_to_x() == x); // doesn't work because x is still borrowed mutably
        // assert!(2 == x);             // same here ... :)
        // x = 2;                       // no writing !
    }

    assert!(x == 2);
    x = 3;   // can adjust it again
    let x = x; // drop mutability
    assert!(x == 3);
    // x = 5;  // this fails now !

    // TODO: MOVING CLOSURE
    // let mut x = 1;
    {
        // let add_one_to_x = || { x += 1 };
        // add_one_to_x();
        // assert!(x == 2);
    }
    // assert!(x == 2);

    let x = 3;
    fn thrice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
        f(x) * 3
    }

    fn subtract_one(x: i32) -> i32 {
        x - 1
    }

    assert_eq!(thrice(x, |x| { x - 1 }), 6);
    assert!(x == 3);
    assert_eq!(thrice(x, subtract_one), 6);
}<|endoftext|>


<commit_before>use autograd::{Function, FuncIntf, FuncDelegate, FIWrap};
use tensor::TensorKindList;

#[builder(pattern="owned")]
#[derive(Builder, Clone)]
pub struct MaxPoolFArgs {
    // just for code re-use
    #[builder(default="vec![1]")]
    pub kernel_size: Vec<u32>,
    pub stride: Vec<u32>,
    pub padding: Vec<u32>,
    pub dilation: Vec<u32>,
    #[builder(default="false")]
    pub ceil_mode: bool,
    #[builder(default="false")]
    pub return_indices: bool,
}

pub struct MaxPool1dArgs {
    pub v: MaxPoolFArgs,
}
pub struct MaxPool2dArgs {
    pub v: MaxPoolFArgs,
}
pub struct MaxPool3dArgs {
    pub v: MaxPoolFArgs,
}

impl Default for MaxPool1dArgs {
    fn default() -> Self {
        let args = MaxPoolFArgsBuilder::default()
            .stride(vec![1])
            .padding(vec![0])
            .dilation(vec![1])
            .build()
            .unwrap();
        MaxPool1dArgs { v: args }
    }
}

impl Default for MaxPool2dArgs {
    fn default() -> Self {
        let args = MaxPoolFArgsBuilder::default()
            .stride(vec![1, 1])
            .padding(vec![0, 0])
            .dilation(vec![1, 1])
            .build()
            .unwrap();
        MaxPool2dArgs { v: args }
    }
}

impl Default for MaxPool3dArgs {
    fn default() -> Self {
        let args = MaxPoolFArgsBuilder::default()
            .stride(vec![1, 1, 1])
            .padding(vec![0, 0, 0])
            .dilation(vec![1, 1, 1])
            .build()
            .unwrap();
        MaxPool3dArgs { v: args }
    }
}

impl_func_args!(MaxPool2d, MaxPoolFArgs);

impl FuncIntf for MaxPool2d {
    fn forward(&mut self, input_: &mut TensorKindList) -> TensorKindList {
        let input = input_.remove(0);
        let input2d = input.unsqueeze(2);
        //        let backend = input.backend();
        let (indices, output) = (input2d.new().long(), input2d.new());

        vec![output]
    }
    fn backward(&mut self, mut input: &mut TensorKindList) -> TensorKindList {
        unimplemented!()
    }
}
<commit_msg>fix new usage post changes<commit_after>use autograd::{Function, FuncIntf, FuncDelegate, FIWrap};
use tensor::TensorKindList;
use tensor::*;

#[builder(pattern="owned")]
#[derive(Builder, Clone)]
pub struct MaxPoolFArgs {
    // just for code re-use
    #[builder(default="vec![1]")]
    pub kernel_size: Vec<u32>,
    pub stride: Vec<u32>,
    pub padding: Vec<u32>,
    pub dilation: Vec<u32>,
    #[builder(default="false")]
    pub ceil_mode: bool,
    #[builder(default="false")]
    pub return_indices: bool,
}

pub struct MaxPool1dArgs {
    pub v: MaxPoolFArgs,
}
pub struct MaxPool2dArgs {
    pub v: MaxPoolFArgs,
}
pub struct MaxPool3dArgs {
    pub v: MaxPoolFArgs,
}

impl Default for MaxPool1dArgs {
    fn default() -> Self {
        let args = MaxPoolFArgsBuilder::default()
            .stride(vec![1])
            .padding(vec![0])
            .dilation(vec![1])
            .build()
            .unwrap();
        MaxPool1dArgs { v: args }
    }
}

impl Default for MaxPool2dArgs {
    fn default() -> Self {
        let args = MaxPoolFArgsBuilder::default()
            .stride(vec![1, 1])
            .padding(vec![0, 0])
            .dilation(vec![1, 1])
            .build()
            .unwrap();
        MaxPool2dArgs { v: args }
    }
}

impl Default for MaxPool3dArgs {
    fn default() -> Self {
        let args = MaxPoolFArgsBuilder::default()
            .stride(vec![1, 1, 1])
            .padding(vec![0, 0, 0])
            .dilation(vec![1, 1, 1])
            .build()
            .unwrap();
        MaxPool3dArgs { v: args }
    }
}

impl_func_args!(MaxPool2d, MaxPoolFArgs);

impl FuncIntf for MaxPool2d {
    fn forward(&mut self, input_: &mut TensorKindList) -> TensorKindList {
        let input = input_.remove(0);
        let input2d = input.unsqueeze(2);
        //        let backend = input.backend();
        let (indices, output) = (input2d.new_(()).long(), input2d.new_(()));

        vec![output]
    }
    fn backward(&mut self, mut input: &mut TensorKindList) -> TensorKindList {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>use super::scheduler_future::*;

use futures::prelude::*;
use futures::task;
use futures::task::{Poll};
use futures::channel::oneshot;

use std::mem;
use std::pin::*;

///
/// The state of a SyncFuture operation
///
enum SyncFutureState<TFn, TFuture>
where TFuture: Future {
    /// Waiting for the queue to start running the future
    WaitingForQueue(oneshot::Receiver<()>, TFn),

    /// Evaluating an active future for its result
    WaitingForFuture(TFuture),

    /// The sync future has completed and now we're waiting for the scheduler to complete
    WaitingForScheduler(Box<TFuture::Output>),

    /// Finished evaluating
    Completed
}

///
/// Represents a future that runs synchronously with a queue
///
/// The future is only run in an exclusive time slot within the queue - this property is used to guarantee the
/// safety of `Desync::future_sync`, which provides exclusive access to the data store while the future is running.
/// The queue is allowed to continue once the returned future has completed.
///
pub struct SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    /// The state of this future
    state: SyncFutureState<TFn, TFuture>,

    /// Tracks this future on the scheduler (this allows polling this future to invoke desync's thread-stealing semantics instead of leaving the queue scheduling to a separate thread)
    scheduler_future: SchedulerFuture<()>,

    /// Signals when the future has finished running (None if this future is completed)
    task_finished: Option<oneshot::Sender<()>>
}

impl<TFn, TFuture> SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    ///
    /// Creates a new SyncFuture
    ///
    pub fn new(create_future: TFn, scheduler_future: SchedulerFuture<()>, queue_ready: oneshot::Receiver<()>, task_finished: oneshot::Sender<()>) -> SyncFuture<TFn, TFuture> {
        SyncFuture {
            state:              SyncFutureState::WaitingForQueue(queue_ready, create_future),
            scheduler_future:   scheduler_future,
            task_finished:      Some(task_finished)
        }
    }
}

impl<TFn, TFuture> Future for SyncFuture<TFn, TFuture>
where   TFn:                Unpin+Send+FnOnce() -> TFuture,
        TFuture:            Unpin+Send+Future,
        TFuture::Output:    Send {
    type Output = Result<TFuture::Output, oneshot::Canceled>;

    fn poll(mut self: Pin<&mut Self>, context: &mut task::Context) -> Poll<Self::Output> {
        use self::SyncFutureState::*;

        // Rust doesn't seem to have a way to let us update the state in-place, so we need to swap out the old state and swap in the new state
        let mut result;
        let mut state = Completed;
        mem::swap(&mut state, &mut self.state);

        // Update the state now we own it
        loop {
            // Set to true if a 'pending' result should trigger another state update (eg, if we start a new future, we should poll it)
            let mut retry = false;

            state = match state {
                WaitingForQueue(mut recv, create_future) => {
                    // Check the scheduler future (give it a chance to steal the thread)
                    if let Poll::Ready(Err(_)) = self.scheduler_future.poll_unpin(context) {
                        // The queue will never get to the point of polling this future
                        result = Poll::Ready(Err(oneshot::Canceled));
                        self.task_finished.take().map(|finished| finished.send(()));
                        Completed
                    } else {
                        // Poll the receiver
                        match recv.poll_unpin(context) {
                            Poll::Ready(Ok(())) => {
                                // Start the future
                                let future = create_future();

                                // Poll it immediately to determine its status
                                result = Poll::Pending;

                                retry = true;
                                WaitingForFuture(future)
                            }

                            Poll::Ready(Err(_)) => {
                                // Future never became ready
                                result = Poll::Ready(Err(oneshot::Canceled));
                                Completed
                            }

                            Poll::Pending => {
                                // Waiting for the queue to start this future
                                result = Poll::Pending;
                                WaitingForQueue(recv, create_future)
                            }
                        }
                    }
                }

                WaitingForFuture(mut future) => {
                    if let Poll::Ready(future_result) = future.poll_unpin(context) {
                        // Future has completed
                        result = Poll::Pending;
                        self.task_finished.take().map(|finished| finished.send(()));

                        retry = true;
                        WaitingForScheduler(Box::new(future_result))
                    } else {
                        // Future is still running
                        result = Poll::Pending;
                        WaitingForFuture(future)
                    }
                }

                WaitingForScheduler(future_result) => {
                    // Poll until the scheduler has finished running the task entirely (can deadlock while draining if we don't)
                    if let Poll::Ready(_) = self.scheduler_future.poll_unpin(context) {
                        result = Poll::Ready(Ok(*future_result));
                        Completed
                    } else {
                        result = Poll::Pending;
                        WaitingForScheduler(future_result)
                    }
                }

                Completed => {
                    // Polling after the result has been returned
                    result = Poll::Ready(Err(oneshot::Canceled));
                    Completed
                }
            };

            // Finish once retry is left at false
            if !retry {
                break;
            }
        }

        // Swap the state back into the structure
        self.state = state;

        result
    }
}
<commit_msg>Temporarily re-introduce the issue where the test will fail due to the signal being dropped early<commit_after>use super::scheduler_future::*;

use futures::prelude::*;
use futures::task;
use futures::task::{Poll};
use futures::channel::oneshot;

use std::mem;
use std::pin::*;

///
/// The state of a SyncFuture operation
///
enum SyncFutureState<TFn, TFuture>
where TFuture: Future {
    /// Waiting for the queue to start running the future
    WaitingForQueue(oneshot::Receiver<()>, TFn),

    /// Evaluating an active future for its result
    WaitingForFuture(TFuture),

    /// The sync future has completed and now we're waiting for the scheduler to complete
    WaitingForScheduler(Box<TFuture::Output>),

    /// Finished evaluating
    Completed
}

///
/// Represents a future that runs synchronously with a queue
///
/// The future is only run in an exclusive time slot within the queue - this property is used to guarantee the
/// safety of `Desync::future_sync`, which provides exclusive access to the data store while the future is running.
/// The queue is allowed to continue once the returned future has completed.
///
pub struct SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    /// The state of this future
    state: SyncFutureState<TFn, TFuture>,

    /// Tracks this future on the scheduler (this allows polling this future to invoke desync's thread-stealing semantics instead of leaving the queue scheduling to a separate thread)
    scheduler_future: SchedulerFuture<()>,

    /// Signals when the future has finished running (None if this future is completed)
    task_finished: Option<oneshot::Sender<()>>
}

impl<TFn, TFuture> SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    ///
    /// Creates a new SyncFuture
    ///
    pub fn new(create_future: TFn, scheduler_future: SchedulerFuture<()>, queue_ready: oneshot::Receiver<()>, task_finished: oneshot::Sender<()>) -> SyncFuture<TFn, TFuture> {
        SyncFuture {
            state:              SyncFutureState::WaitingForQueue(queue_ready, create_future),
            scheduler_future:   scheduler_future,
            task_finished:      Some(task_finished)
        }
    }
}

impl<TFn, TFuture> Future for SyncFuture<TFn, TFuture>
where   TFn:                Unpin+Send+FnOnce() -> TFuture,
        TFuture:            Unpin+Send+Future,
        TFuture::Output:    Send {
    type Output = Result<TFuture::Output, oneshot::Canceled>;

    fn poll(mut self: Pin<&mut Self>, context: &mut task::Context) -> Poll<Self::Output> {
        use self::SyncFutureState::*;

        // Rust doesn't seem to have a way to let us update the state in-place, so we need to swap out the old state and swap in the new state
        let mut result;
        let mut state = Completed;
        mem::swap(&mut state, &mut self.state);

        // Update the state now we own it
        loop {
            // Set to true if a 'pending' result should trigger another state update (eg, if we start a new future, we should poll it)
            let mut retry = false;

            state = match state {
                WaitingForQueue(mut recv, create_future) => {
                    // Check the scheduler future (give it a chance to steal the thread)
                    if let Poll::Ready(Err(_)) = self.scheduler_future.poll_unpin(context) {
                        // The queue will never get to the point of polling this future
                        result = Poll::Ready(Err(oneshot::Canceled));
                        self.task_finished.take().map(|finished| finished.send(()));
                        Completed
                    } else {
                        // Poll the receiver
                        match recv.poll_unpin(context) {
                            Poll::Ready(Ok(())) => {
                                // Start the future
                                let future = create_future();

                                // Poll it immediately to determine its status
                                result = Poll::Pending;

                                retry = true;
                                WaitingForFuture(future)
                            }

                            Poll::Ready(Err(_)) => {
                                // Future never became ready
                                result = Poll::Ready(Err(oneshot::Canceled));
                                Completed
                            }

                            Poll::Pending => {
                                // Waiting for the queue to start this future
                                result = Poll::Pending;
                                WaitingForQueue(recv, create_future)
                            }
                        }
                    }
                }

                WaitingForFuture(mut future) => {
                    if let Poll::Ready(future_result) = future.poll_unpin(context) {
                        // Future has completed
                        result = Poll::Pending;
                        self.task_finished.take().map(|finished| finished.send(()));

                        retry = true;
                        WaitingForScheduler(Box::new(future_result))
                    } else {
                        // Future is still running
                        result = Poll::Pending;
                        WaitingForFuture(future)
                    }
                }

                WaitingForScheduler(future_result) => {
                    // Poll until the scheduler has finished running the task entirely (can deadlock while draining if we don't)
                    if true {
                        result = Poll::Ready(Ok(*future_result));
                        Completed
                    } else {
                        result = Poll::Pending;
                        WaitingForScheduler(future_result)
                    }
                }

                Completed => {
                    // Polling after the result has been returned
                    result = Poll::Ready(Err(oneshot::Canceled));
                    Completed
                }
            };

            // Finish once retry is left at false
            if !retry {
                break;
            }
        }

        // Swap the state back into the structure
        self.state = state;

        result
    }
}
<|endoftext|>


<commit_before>pub extern crate cpp_to_rust_common as common;
use common::errors::{fancy_unwrap, ChainErr, Result};
use common::cpp_build_config::{CppBuildConfig, CppBuildPaths, CppLibraryType};
use common::build_script_data::BuildScriptData;
use common::file_utils::{PathBufWithAdded, load_json, create_file, file_to_string, path_to_str};
use common::cpp_lib_builder::{CppLibBuilder, CMakeVar, BuildType};
use common::target::current_target;
use common::utils::{get_command_output, exe_suffix};
use common::log;

use std::path::PathBuf;
use std::process::Command;

#[derive(Debug)]
pub struct Config {
  cpp_build_paths: CppBuildPaths,
  cpp_build_config: CppBuildConfig,
}

fn manifest_dir() -> Result<PathBuf> {
  let dir =
    std::env::var("CARGO_MANIFEST_DIR").chain_err(|| "CARGO_MANIFEST_DIR env var is missing")?;
  Ok(PathBuf::from(dir))
}
fn out_dir() -> Result<PathBuf> {
  let dir = std::env::var("OUT_DIR").chain_err(|| "OUT_DIR env var is missing")?;
  Ok(PathBuf::from(dir))
}

fn build_script_data() -> Result<BuildScriptData> {
  load_json(manifest_dir()?.with_added("build_script_data.json"))
}

impl Config {
  pub fn new() -> Result<Config> {
    Ok(Config {
         cpp_build_config: build_script_data()?.cpp_build_config,
         cpp_build_paths: CppBuildPaths::default(),
       })
  }
  pub fn cpp_build_config(&self) -> &CppBuildConfig {
    &self.cpp_build_config
  }
  pub fn cpp_build_config_mut(&mut self) -> &mut CppBuildConfig {
    &mut self.cpp_build_config
  }
  pub fn set_cpp_build_config(&mut self, config: CppBuildConfig) {
    self.cpp_build_config = config;
  }
  pub fn cpp_build_paths(&self) -> &CppBuildPaths {
    &self.cpp_build_paths
  }
  pub fn cpp_build_paths_mut(&mut self) -> &mut CppBuildPaths {
    &mut self.cpp_build_paths
  }
  pub fn set_cpp_build_paths(&mut self, config: CppBuildPaths) {
    self.cpp_build_paths = config;
  }

  pub fn run_and_return(mut self) -> Result<()> {
    self.cpp_build_paths.apply_env();
    let build_script_data = build_script_data()?;
    let cpp_build_config_data = self.cpp_build_config.eval(&current_target())?;
    let mut cmake_vars = Vec::new();
    cmake_vars.push(CMakeVar::new("C2R_LIBRARY_TYPE",
                                  match cpp_build_config_data.library_type() {
                                    Some(CppLibraryType::Shared) => "SHARED",
                                    Some(CppLibraryType::Static) |
                                    None => "STATIC",
                                  }));
    cmake_vars.push(CMakeVar::new_path_list("C2R_INCLUDE_PATHS",
                                            self.cpp_build_paths.include_paths())?);
    cmake_vars.push(CMakeVar::new_path_list("C2R_LIB_PATHS", self.cpp_build_paths.lib_paths())?);
    cmake_vars.push(CMakeVar::new_path_list("C2R_FRAMEWORK_PATHS",
                                            self.cpp_build_paths.framework_paths())?);
    cmake_vars.push(CMakeVar::new_list("C2R_LINKED_LIBS", cpp_build_config_data.linked_libs())?);
    cmake_vars.push(CMakeVar::new_list("C2R_LINKED_FRAMEWORKS",
                                       cpp_build_config_data.linked_frameworks())?);
    cmake_vars.push(CMakeVar::new("C2R_COMPILER_FLAGS",
                                  cpp_build_config_data.compiler_flags().join(" ")));
    let out_dir = out_dir()?;
    let c_lib_install_dir = out_dir.with_added("c_lib_install");
    let manifest_dir = manifest_dir()?;
    let profile = std::env::var("PROFILE").chain_err(|| "PROFILE env var is missing")?;
    log::status("Building C++ wrapper library");
    CppLibBuilder {
        cmake_source_dir: manifest_dir.with_added("c_lib"),
        build_dir: out_dir.with_added("c_lib_build"),
        install_dir: c_lib_install_dir.clone(),
        num_jobs: std::env::var("NUM_JOBS")
          .ok()
          .and_then(|x| x.parse().ok()),
        pipe_output: false,
        cmake_vars: cmake_vars,
        build_type: match profile.as_str() {
          "debug" => BuildType::Debug,
          "release" => BuildType::Release,
          _ => return Err(format!("unknown value of PROFILE env var: {}", profile).into()),
        },
      }.run()?;
    {
      log::status("Generating ffi.rs file");
      let mut ffi_file = create_file(out_dir.with_added("ffi.rs"))?;
      for name in cpp_build_config_data.linked_libs() {
        ffi_file.write(format!("#[link(name = \"{}\")]\n", name))?;
      }
      for name in cpp_build_config_data.linked_frameworks() {
        ffi_file.write(format!("#[link(name = \"{}\", kind = \"framework\")]\n", name))?;
      }
      if !::common::utils::is_msvc() {
        // TODO: make it configurable
        ffi_file.write("#[link(name = \"stdc++\")]\n")?;
      }
      if cpp_build_config_data.library_type() == Some(CppLibraryType::Shared) {
        ffi_file.write(format!("#[link(name = \"{}\")]\n",
                         &build_script_data.cpp_wrapper_lib_name))?;
      } else {
        ffi_file.write(format!("#[link(name = \"{}\", kind = \"static\")]\n",
                         &build_script_data.cpp_wrapper_lib_name))?;
      }
      ffi_file.write(file_to_string(manifest_dir.with_added("src").with_added("ffi.in.rs"))?)?;
    }
    {
      log::status("Requesting type sizes");
      let mut command = Command::new(c_lib_install_dir
                                       .with_added("lib")
                                       .with_added(format!("type_sizes{}", exe_suffix())));
      let mut file = create_file(out_dir.with_added("type_sizes.rs"))?;
      file.write(get_command_output(&mut command)?)?;
    }

    for path in self.cpp_build_paths.lib_paths() {
      println!("cargo:rustc-link-search=native={}", path_to_str(path)?);
    }
    for path in self.cpp_build_paths.framework_paths() {
      println!("cargo:rustc-link-search=framework={}", path_to_str(path)?);
    }
    println!("cargo:rustc-link-search=native={}",
             path_to_str(&c_lib_install_dir.with_added("lib"))?);
    log::status("cpp_to_rust build script finished.");
    Ok(())
  }
  pub fn run(self) -> ! {
    fancy_unwrap(self.run_and_return());
    std::process::exit(0)
  }
}

pub fn run_and_return() -> Result<()> {
  Config::new()?.run_and_return()
}

pub fn run() -> ! {
  let config = fancy_unwrap(Config::new());
  config.run()
}
<commit_msg>fixed link errors on windows<commit_after>pub extern crate cpp_to_rust_common as common;
use common::errors::{fancy_unwrap, ChainErr, Result};
use common::cpp_build_config::{CppBuildConfig, CppBuildPaths, CppLibraryType};
use common::build_script_data::BuildScriptData;
use common::file_utils::{PathBufWithAdded, load_json, create_file, file_to_string, path_to_str};
use common::cpp_lib_builder::{CppLibBuilder, CMakeVar, BuildType};
use common::target::current_target;
use common::utils::{get_command_output, exe_suffix};
use common::log;

use std::path::PathBuf;
use std::process::Command;

#[derive(Debug)]
pub struct Config {
  cpp_build_paths: CppBuildPaths,
  cpp_build_config: CppBuildConfig,
}

fn manifest_dir() -> Result<PathBuf> {
  let dir =
    std::env::var("CARGO_MANIFEST_DIR").chain_err(|| "CARGO_MANIFEST_DIR env var is missing")?;
  Ok(PathBuf::from(dir))
}
fn out_dir() -> Result<PathBuf> {
  let dir = std::env::var("OUT_DIR").chain_err(|| "OUT_DIR env var is missing")?;
  Ok(PathBuf::from(dir))
}

fn build_script_data() -> Result<BuildScriptData> {
  load_json(manifest_dir()?.with_added("build_script_data.json"))
}

impl Config {
  pub fn new() -> Result<Config> {
    Ok(Config {
         cpp_build_config: build_script_data()?.cpp_build_config,
         cpp_build_paths: CppBuildPaths::default(),
       })
  }
  pub fn cpp_build_config(&self) -> &CppBuildConfig {
    &self.cpp_build_config
  }
  pub fn cpp_build_config_mut(&mut self) -> &mut CppBuildConfig {
    &mut self.cpp_build_config
  }
  pub fn set_cpp_build_config(&mut self, config: CppBuildConfig) {
    self.cpp_build_config = config;
  }
  pub fn cpp_build_paths(&self) -> &CppBuildPaths {
    &self.cpp_build_paths
  }
  pub fn cpp_build_paths_mut(&mut self) -> &mut CppBuildPaths {
    &mut self.cpp_build_paths
  }
  pub fn set_cpp_build_paths(&mut self, config: CppBuildPaths) {
    self.cpp_build_paths = config;
  }

  pub fn run_and_return(mut self) -> Result<()> {
    self.cpp_build_paths.apply_env();
    let build_script_data = build_script_data()?;
    let cpp_build_config_data = self.cpp_build_config.eval(&current_target())?;
    let mut cmake_vars = Vec::new();
    cmake_vars.push(CMakeVar::new("C2R_LIBRARY_TYPE",
                                  match cpp_build_config_data.library_type() {
                                    Some(CppLibraryType::Shared) => "SHARED",
                                    Some(CppLibraryType::Static) |
                                    None => "STATIC",
                                  }));
    cmake_vars.push(CMakeVar::new_path_list("C2R_INCLUDE_PATHS",
                                            self.cpp_build_paths.include_paths())?);
    cmake_vars.push(CMakeVar::new_path_list("C2R_LIB_PATHS", self.cpp_build_paths.lib_paths())?);
    cmake_vars.push(CMakeVar::new_path_list("C2R_FRAMEWORK_PATHS",
                                            self.cpp_build_paths.framework_paths())?);
    cmake_vars.push(CMakeVar::new_list("C2R_LINKED_LIBS", cpp_build_config_data.linked_libs())?);
    cmake_vars.push(CMakeVar::new_list("C2R_LINKED_FRAMEWORKS",
                                       cpp_build_config_data.linked_frameworks())?);
    cmake_vars.push(CMakeVar::new("C2R_COMPILER_FLAGS",
                                  cpp_build_config_data.compiler_flags().join(" ")));
    let out_dir = out_dir()?;
    let c_lib_install_dir = out_dir.with_added("c_lib_install");
    let manifest_dir = manifest_dir()?;
    let profile = std::env::var("PROFILE").chain_err(|| "PROFILE env var is missing")?;
    log::status("Building C++ wrapper library");
    CppLibBuilder {
        cmake_source_dir: manifest_dir.with_added("c_lib"),
        build_dir: out_dir.with_added("c_lib_build"),
        install_dir: c_lib_install_dir.clone(),
        num_jobs: std::env::var("NUM_JOBS")
          .ok()
          .and_then(|x| x.parse().ok()),
        pipe_output: false,
        cmake_vars: cmake_vars,
        build_type: match profile.as_str() {
          "debug" => BuildType::Debug,
          "release" => BuildType::Release,
          _ => return Err(format!("unknown value of PROFILE env var: {}", profile).into()),
        },
      }.run()?;
    {
      log::status("Generating ffi.rs file");
      let mut ffi_file = create_file(out_dir.with_added("ffi.rs"))?;
      if !::common::utils::is_msvc() {
        // TODO: make it configurable
        ffi_file.write("#[link(name = \"stdc++\")]\n")?;
      }
      if cpp_build_config_data.library_type() == Some(CppLibraryType::Shared) {
        ffi_file.write(format!("#[link(name = \"{}\")]\n",
                         &build_script_data.cpp_wrapper_lib_name))?;
      } else {
        ffi_file.write(format!("#[link(name = \"{}\", kind = \"static\")]\n",
                         &build_script_data.cpp_wrapper_lib_name))?;
      }
      ffi_file.write(file_to_string(manifest_dir.with_added("src").with_added("ffi.in.rs"))?)?;
    }
    {
      log::status("Requesting type sizes");
      let mut command = Command::new(c_lib_install_dir
                                       .with_added("lib")
                                       .with_added(format!("type_sizes{}", exe_suffix())));
      let mut file = create_file(out_dir.with_added("type_sizes.rs"))?;
      file.write(get_command_output(&mut command)?)?;
    }

    for name in cpp_build_config_data.linked_libs() {
      println!("cargo:rustc-link-lib={}", name);
    }
    for name in cpp_build_config_data.linked_frameworks() {
      println!("cargo:rustc-link-lib=framework={}", name);
    }
    for path in self.cpp_build_paths.lib_paths() {
      println!("cargo:rustc-link-search=native={}", path_to_str(path)?);
    }
    for path in self.cpp_build_paths.framework_paths() {
      println!("cargo:rustc-link-search=framework={}", path_to_str(path)?);
    }
    println!("cargo:rustc-link-search=native={}",
             path_to_str(&c_lib_install_dir.with_added("lib"))?);
    log::status("cpp_to_rust build script finished.");
    Ok(())
  }
  pub fn run(self) -> ! {
    fancy_unwrap(self.run_and_return());
    std::process::exit(0)
  }
}

pub fn run_and_return() -> Result<()> {
  Config::new()?.run_and_return()
}

pub fn run() -> ! {
  let config = fancy_unwrap(Config::new());
  config.run()
}
<|endoftext|>


<commit_before>use syntax::{
    ast::{self, VisibilityOwner},
    ted::{self, Position},
    AstNode, SyntaxKind,
};

use crate::{
    assist_context::{AssistContext, Assists},
    AssistId, AssistKind,
};

// Assist: unmerge_use
//
// Extracts single use item from use list.
//
// ```
// use std::fmt::{Debug, Display$0};
// ```
// ->
// ```
// use std::fmt::{Debug};
// use std::fmt::Display;
// ```
pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update();

    let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
    if tree_list.use_trees().count() < 2 {
        cov_mark::hit!(skip_single_use_item);
        return None;
    }

    let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
    let path = resolve_full_path(&tree)?;

    let old_parent_range = use_.syntax().parent()?.text_range();
    let new_parent = use_.syntax().parent()?;

    let target = tree.syntax().text_range();
    acc.add(
        AssistId("unmerge_use", AssistKind::RefactorRewrite),
        "Unmerge use",
        target,
        |builder| {
            let new_use = ast::make::use_(
                use_.visibility(),
                ast::make::use_tree(
                    path,
                    tree.use_tree_list(),
                    tree.rename(),
                    tree.star_token().is_some(),
                ),
            )
            .clone_for_update();

            tree.remove();
            ted::insert(Position::after(use_.syntax()), new_use.syntax());

            builder.replace(old_parent_range, new_parent.to_string());
        },
    )
}

fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
    let mut paths = tree
        .syntax()
        .ancestors()
        .take_while(|n| n.kind() != SyntaxKind::USE_KW)
        .filter_map(ast::UseTree::cast)
        .filter_map(|t| t.path());

    let mut final_path = paths.next()?;
    for path in paths {
        final_path = ast::make::path_concat(path, final_path)
    }
    Some(final_path)
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn skip_single_use_item() {
        cov_mark::check!(skip_single_use_item);
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::Debug$0;
",
        );
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::{Debug$0};
",
        );
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::Debug as Dbg$0;
",
        );
    }

    #[test]
    fn skip_single_glob_import() {
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::*$0;
",
        );
    }

    #[test]
    fn unmerge_use_item() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, Display$0};
",
            r"
use std::fmt::{Debug};
use std::fmt::Display;
",
        );

        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, format$0, Display};
",
            r"
use std::fmt::{Debug, Display};
use std::fmt::format;
",
        );
    }

    #[test]
    fn unmerge_glob_import() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{*$0, Display};
",
            r"
use std::fmt::{Display};
use std::fmt::*;
",
        );
    }

    #[test]
    fn unmerge_renamed_use_item() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, Display as Disp$0};
",
            r"
use std::fmt::{Debug};
use std::fmt::Display as Disp;
",
        );
    }

    #[test]
    fn unmerge_indented_use_item() {
        check_assist(
            unmerge_use,
            r"
mod format {
    use std::fmt::{Debug, Display$0 as Disp, format};
}
",
            r"
mod format {
    use std::fmt::{Debug, format};
    use std::fmt::Display as Disp;
}
",
        );
    }

    #[test]
    fn unmerge_nested_use_item() {
        check_assist(
            unmerge_use,
            r"
use foo::bar::{baz::{qux$0, foobar}, barbaz};
",
            r"
use foo::bar::{baz::{foobar}, barbaz};
use foo::bar::baz::qux;
",
        );
        check_assist(
            unmerge_use,
            r"
use foo::bar::{baz$0::{qux, foobar}, barbaz};
",
            r"
use foo::bar::{barbaz};
use foo::bar::baz::{qux, foobar};
",
        );
    }

    #[test]
    fn unmerge_use_item_with_visibility() {
        check_assist(
            unmerge_use,
            r"
pub use std::fmt::{Debug, Display$0};
",
            r"
pub use std::fmt::{Debug};
pub use std::fmt::Display;
",
        );
    }
}
<commit_msg>Don't keep a trailing self token in import paths after unmerge_use<commit_after>use syntax::{
    ast::{self, VisibilityOwner},
    ted::{self, Position},
    AstNode, SyntaxKind,
};

use crate::{
    assist_context::{AssistContext, Assists},
    AssistId, AssistKind,
};

// Assist: unmerge_use
//
// Extracts single use item from use list.
//
// ```
// use std::fmt::{Debug, Display$0};
// ```
// ->
// ```
// use std::fmt::{Debug};
// use std::fmt::Display;
// ```
pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update();

    let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
    if tree_list.use_trees().count() < 2 {
        cov_mark::hit!(skip_single_use_item);
        return None;
    }

    let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
    let path = resolve_full_path(&tree)?;

    let old_parent_range = use_.syntax().parent()?.text_range();
    let new_parent = use_.syntax().parent()?;

    let target = tree.syntax().text_range();
    acc.add(
        AssistId("unmerge_use", AssistKind::RefactorRewrite),
        "Unmerge use",
        target,
        |builder| {
            let new_use = ast::make::use_(
                use_.visibility(),
                ast::make::use_tree(
                    path,
                    tree.use_tree_list(),
                    tree.rename(),
                    tree.star_token().is_some(),
                ),
            )
            .clone_for_update();

            tree.remove();
            ted::insert(Position::after(use_.syntax()), new_use.syntax());

            builder.replace(old_parent_range, new_parent.to_string());
        },
    )
}

fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
    let mut paths = tree
        .syntax()
        .ancestors()
        .take_while(|n| n.kind() != SyntaxKind::USE_KW)
        .filter_map(ast::UseTree::cast)
        .filter_map(|t| t.path());

    let mut final_path = paths.next()?;
    for path in paths {
        final_path = ast::make::path_concat(path, final_path)
    }
    if final_path.segment().map_or(false, |it| it.self_token().is_some()) {
        final_path.qualifier()
    } else {
        Some(final_path)
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn skip_single_use_item() {
        cov_mark::check!(skip_single_use_item);
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::Debug$0;
",
        );
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::{Debug$0};
",
        );
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::Debug as Dbg$0;
",
        );
    }

    #[test]
    fn skip_single_glob_import() {
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::*$0;
",
        );
    }

    #[test]
    fn unmerge_use_item() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, Display$0};
",
            r"
use std::fmt::{Debug};
use std::fmt::Display;
",
        );

        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, format$0, Display};
",
            r"
use std::fmt::{Debug, Display};
use std::fmt::format;
",
        );
    }

    #[test]
    fn unmerge_glob_import() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{*$0, Display};
",
            r"
use std::fmt::{Display};
use std::fmt::*;
",
        );
    }

    #[test]
    fn unmerge_renamed_use_item() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, Display as Disp$0};
",
            r"
use std::fmt::{Debug};
use std::fmt::Display as Disp;
",
        );
    }

    #[test]
    fn unmerge_indented_use_item() {
        check_assist(
            unmerge_use,
            r"
mod format {
    use std::fmt::{Debug, Display$0 as Disp, format};
}
",
            r"
mod format {
    use std::fmt::{Debug, format};
    use std::fmt::Display as Disp;
}
",
        );
    }

    #[test]
    fn unmerge_nested_use_item() {
        check_assist(
            unmerge_use,
            r"
use foo::bar::{baz::{qux$0, foobar}, barbaz};
",
            r"
use foo::bar::{baz::{foobar}, barbaz};
use foo::bar::baz::qux;
",
        );
        check_assist(
            unmerge_use,
            r"
use foo::bar::{baz$0::{qux, foobar}, barbaz};
",
            r"
use foo::bar::{barbaz};
use foo::bar::baz::{qux, foobar};
",
        );
    }

    #[test]
    fn unmerge_use_item_with_visibility() {
        check_assist(
            unmerge_use,
            r"
pub use std::fmt::{Debug, Display$0};
",
            r"
pub use std::fmt::{Debug};
pub use std::fmt::Display;
",
        );
    }

    #[test]
    fn unmerge_use_item_on_self() {
        check_assist(
            unmerge_use,
            r"use std::process::{Command, self$0};",
            r"use std::process::{Command};
use std::process;",
        );
    }
}
<|endoftext|>