<commit_before>//! A collection of default help commands for the framework.
//!
//! # Example
//!
//! Using the [`with_embeds`] function to have the framework's help message use
//! embeds:
//!
//! ```rs,no_run
//! use serenity::framework::standard::help_commands;
//! use serenity::Client;
//! use std::env;
//!
//! let mut client = Client::new(&env::var("DISCORD_TOKEN").unwrap());
//! use serenity::framework::StandardFramework;
//!
//! client.with_framework(StandardFramework::new()
//!     .command("help", |c| c.exec_help(help_commands::with_embeds)));
//! ```
//!
//! The same can be accomplished with no embeds by substituting `with_embeds`
//! with the [`plain`] function.
//!
//! [`plain`]: fn.plain.html
//! [`with_embeds`]: fn.with_embeds.html

use client::Context;
use framework::standard::{has_correct_roles, has_correct_permissions};
use model::channel::Message;
use model::id::ChannelId;
use std::collections::HashMap;
use std::hash::BuildHasher;
use std::sync::Arc;
use std::fmt::Write;
use super::command::{InternalCommand};
use super::{Args, CommandGroup, CommandOrAlias, HelpOptions, CommandOptions, CommandError, HelpBehaviour};
use utils::Colour;

fn error_embed(channel_id: &ChannelId, input: &str, colour: Colour) {
    let _ = channel_id.send_message(|m| {
        m.embed(|e| e.colour(colour).description(input))
    });
}

fn remove_aliases(cmds: &HashMap<String, CommandOrAlias>) -> HashMap<&String, &InternalCommand> {
    let mut result = HashMap::new();

    for (n, v) in cmds {
        if let CommandOrAlias::Command(ref cmd) = *v {
            result.insert(n, cmd);
        }
    }

    result
}

/// Checks whether a user is member of required roles
/// and given the required permissions.
pub fn has_all_requirements(cmd: &Arc<CommandOptions>, msg: &Message) -> bool {
    if let Some(guild) = msg.guild() {
        let guild = guild.read();

        if let Some(member) = guild.members.get(&msg.author.id) {

            if let Ok(permissions) = member.permissions() {

                if cmd.allowed_roles.is_empty() {
                    return permissions.administrator() || has_correct_permissions(cmd, msg);
                } else {
                    return permissions.administrator() || (has_correct_roles(cmd, &guild, member) && has_correct_permissions(cmd, msg));
                }
            }
        }
    }
    !cmd.guild_only
}

/// Posts an embed showing each individual command group and its commands.
///
/// # Examples
///
/// Use the command with `exec_help`:
///
/// ```rust
/// # use serenity::prelude::*;
/// # struct Handler;
/// #
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler).unwrap();
/// #
/// use serenity::framework::standard::{StandardFramework, help_commands};
///
/// client.with_framework(StandardFramework::new()
///     .help(help_commands::with_embeds));
/// ```
pub fn with_embeds<H: BuildHasher>(
    _: &mut Context,
    msg: &Message,
    help_options: &HelpOptions,
    groups: HashMap<String, Arc<CommandGroup>, H>,
    args: &Args
) -> Result<(), CommandError> {
    if !args.is_empty() {
        let name = args.full();

        for (group_name, group) in groups {
            let mut found: Option<(&String, &InternalCommand)> = None;

            for (command_name, command) in &group.commands {
                let with_prefix = if let Some(ref prefix) = group.prefix {
                    format!("{} {}", prefix, command_name)
                } else {
                    command_name.to_string()
                };

                if name == with_prefix || name == *command_name {
                    match *command {
                        CommandOrAlias::Command(ref cmd) => {
                            if has_all_requirements(&cmd.options(), msg) {
                                found = Some((command_name, cmd));
                            } else {
                                break;
                            }
                        },
                        CommandOrAlias::Alias(ref name) => {
                            let actual_command = &group.commands[name];

                            match *actual_command {
                                CommandOrAlias::Command(ref cmd) => {
                                    if has_all_requirements(&cmd.options(), msg) {
                                        found = Some((name, cmd));
                                    } else {
                                        break;
                                    }
                                },

                                CommandOrAlias::Alias(ref name) => {
                                    let _ = msg.channel_id.say(help_options.suggestion_text.replace("{}", name));
                                    return Ok(());
                                },
                            }
                        },
                    }
                }
            }

            if let Some((command_name, command)) = found {
                let command = command.options();
                if !command.help_available {
                    error_embed(&msg.channel_id, &help_options.no_help_available_text, help_options.embed_error_colour);

                    return Ok(());
                }

                let _ = msg.channel_id.send_message(|m| {
                    m.embed(|e| {
                        let mut embed = e.colour(help_options.embed_success_colour).title(command_name.clone());

                        if let Some(ref desc) = command.desc {
                            embed = embed.description(desc);
                        }

                        if let Some(ref usage) = command.usage {
                            let value = format!("`{} {}`", command_name.clone(), usage);

                            embed = embed.field(&help_options.usage_label, value, true);
                        }

                        if let Some(ref example) = command.example {
                            let value = format!("`{} {}`", command_name.clone(), example);

                            embed = embed.field(&help_options.usage_sample_label, value, true);
                        }

                        if group_name != "Ungrouped" {
                            embed = embed.field(&help_options.grouped_label, group_name, true);
                        }

                        if !command.aliases.is_empty() {
                            let aliases = command.aliases.join(", ");

                            embed = embed.field(&help_options.aliases_label, aliases, true);
                        }

                        let available = if command.dm_only {
                            &help_options.dm_only_text
                        } else if command.guild_only {
                            &help_options.guild_only_text
                        } else {
                            &help_options.dm_and_guild_text
                        };

                        embed = embed.field(&help_options.available_text, available, true);

                        embed
                    })
                });

                return Ok(());
            }
        }

        let error_msg = help_options.command_not_found_text.replace("{}", name);
        error_embed(&msg.channel_id, &error_msg, help_options.embed_error_colour);

        return Ok(());
    }

    let _ = msg.channel_id.send_message(|m| {
        m.embed(|mut e| {

            if let Some(striked_command_text) = help_options.striked_commands_tip.clone() {
                e = e.colour(help_options.embed_success_colour).description(
                    format!("{}\n{}", &help_options.individual_command_tip, &striked_command_text),
                );
            } else {
                e = e.colour(help_options.embed_success_colour).description(
                    &help_options.individual_command_tip,
                );
            }

            let mut group_names = groups.keys().collect::<Vec<_>>();
            group_names.sort();

            for group_name in group_names {
                let group = &groups[group_name];
                let mut desc = String::new();

                if let Some(ref x) = group.prefix {
                    let _ = write!(desc, "{}: `{}`\n", &help_options.group_prefix, x);
                }

                let mut has_commands = false;

                let commands = remove_aliases(&group.commands);
                let mut command_names = commands.keys().collect::<Vec<_>>();
                command_names.sort();

                for name in command_names {
                    let cmd = &commands[name];
                    let cmd = cmd.options();

                    if !cmd.dm_only && !cmd.guild_only || cmd.dm_only && msg.is_private() || cmd.guild_only && !msg.is_private() {
                        if cmd.help_available && has_correct_permissions(&cmd, msg) {
                            let _ = write!(desc, "`{}`\n", name);
                            has_commands = true;
                        } else {
                            match help_options.lacking_permissions {
                                HelpBehaviour::Strike => {
                                    let name = format!("~~`{}`~~", &name);
                                    let _ = write!(desc, "{}\n", name);
                                    has_commands = true;
                                },
                                HelpBehaviour::Nothing => {
                                    let _ = write!(desc, "`{}`\n", name);
                                    has_commands = true;
                                },
                                HelpBehaviour::Hide => {
                                    continue;
                                },
                            }
                        }
                    } else {
                        match help_options.wrong_channel {
                            HelpBehaviour::Strike => {
                                let name = format!("~~`{}`~~", &name);
                                let _ = write!(desc, "{}\n", name);
                                has_commands = true;
                            },
                            HelpBehaviour::Nothing => {
                                let _ = write!(desc, "`{}`\n", name);
                                has_commands = true;
                            },
                            HelpBehaviour::Hide => {
                                continue;
                            },
                        }
                    }
                }

                if has_commands {
                    e = e.field(&group_name[..], &desc[..], true);
                }
            }
            e
        })
    });

    Ok(())
}

/// Posts formatted text displaying each individual command group and its commands.
///
/// # Examples
///
/// Use the command with `exec_help`:
///
/// ```rust
/// # use serenity::prelude::*;
/// # struct Handler;
/// #
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler).unwrap();
/// #
/// use serenity::framework::standard::{StandardFramework, help_commands};
///
/// client.with_framework(StandardFramework::new()
///     .help(help_commands::plain));
/// ```
pub fn plain<H: BuildHasher>(
    _: &mut Context,
    msg: &Message,
    help_options: &HelpOptions,
    groups: HashMap<String, Arc<CommandGroup>, H>,
    args: &Args
) -> Result<(), CommandError> {
    if !args.is_empty() {
        let name = args.full();

        for (group_name, group) in groups {
            let mut found: Option<(&String, &InternalCommand)> = None;

            for (command_name, command) in &group.commands {
                let with_prefix = if let Some(ref prefix) = group.prefix {
                    format!("{} {}", prefix, command_name)
                } else {
                    command_name.to_string()
                };

                if name == with_prefix || name == *command_name {
                    match *command {
                        CommandOrAlias::Command(ref cmd) => {
                            if has_all_requirements(&cmd.options(), msg) {
                                found = Some((command_name, cmd));
                            }
                            else {
                                break;
                            }
                        },
                        CommandOrAlias::Alias(ref name) => {
                            let actual_command = &group.commands[name];

                            match *actual_command {
                                CommandOrAlias::Command(ref cmd) => {
                                    if has_all_requirements(&cmd.options(), msg) {
                                        found = Some((name, cmd));
                                    }
                                    else {
                                        break;
                                    }
                                },

                                CommandOrAlias::Alias(ref name) => {
                                    let _ = msg.channel_id.say(help_options.suggestion_text.replace("{}", name));
                                    return Ok(());
                                },
                            }
                        },
                    }
                }
            }

            if let Some((command_name, command)) = found {
                let command = command.options();

                if !command.help_available {
                    let _ = msg.channel_id.say(&help_options.no_help_available_text);
                    return Ok(());
                }

                let mut result = format!("**{}**\n", command_name);

                if !command.aliases.is_empty() {
                    let aliases = command.aliases.join("`, `");
                    let _ = write!(result, "**{}:** `{}`\n", help_options.aliases_label, aliases);
                }

                if let Some(ref desc) = command.desc {
                    let _ = write!(result, "**{}:** {}\n", help_options.description_label, desc);
                }

                if let Some(ref usage) = command.usage {
                    let _ = write!(result, "**{}:** `{} {}`\n", help_options.usage_label, command_name, usage);
                }

                if let Some(ref example) = command.example {
                    let _ = write!(result, "**{}:** `{} {}`\n", help_options.usage_sample_label, command_name, example);
                }

                if group_name != "Ungrouped" {
                    let _ = write!(result, "**{}:** {}\n", help_options.grouped_label, group_name);
                }

                let only = if command.dm_only {
                    &help_options.dm_only_text
                } else if command.guild_only {
                    &help_options.guild_only_text
                } else {
                    &help_options.dm_and_guild_text
                };

                result.push_str(&format!("**{}:** ", &help_options.available_text));
                result.push_str(only);
                result.push_str(".\n");

                let _ = msg.channel_id.say(&result);

                return Ok(());
            }
        }

        let _ = msg.channel_id
            .say(&help_options.suggestion_text.replace("{}", name));

        return Ok(());
    }

    let mut result = format!("**Commands**\n{}\n\n", help_options.individual_command_tip)
        .to_string();

    let mut group_names = groups.keys().collect::<Vec<_>>();
    group_names.sort();

    for group_name in group_names {
        let group = &groups[group_name];
        let mut group_help = String::new();

        let commands = remove_aliases(&group.commands);
        let mut command_names = commands.keys().collect::<Vec<_>>();
        command_names.sort();

        for name in command_names {
            let cmd = &commands[name];
            let cmd = cmd.options();

            if cmd.help_available && has_all_requirements(&cmd, msg) {
                let _ = write!(group_help, "`{}` ", name);
            }
        }

        if !group_help.is_empty() {
            let _ = write!(result, "**{}:** ", group_name);

            if let Some(ref x) = group.prefix {
                let _ = write!(result, "({}: `{}`): ", help_options.group_prefix, x);
            }

            result.push_str(&group_help);
            result.push('\n');
        }
    }

    let _ = msg.channel_id.say(&result);

    Ok(())
}
<commit_msg>Fix help-commands' `plain`<commit_after>//! A collection of default help commands for the framework.
//!
//! # Example
//!
//! Using the [`with_embeds`] function to have the framework's help message use
//! embeds:
//!
//! ```rs,no_run
//! use serenity::framework::standard::help_commands;
//! use serenity::Client;
//! use std::env;
//!
//! let mut client = Client::new(&env::var("DISCORD_TOKEN").unwrap());
//! use serenity::framework::StandardFramework;
//!
//! client.with_framework(StandardFramework::new()
//!     .command("help", |c| c.exec_help(help_commands::with_embeds)));
//! ```
//!
//! The same can be accomplished with no embeds by substituting `with_embeds`
//! with the [`plain`] function.
//!
//! [`plain`]: fn.plain.html
//! [`with_embeds`]: fn.with_embeds.html

use client::Context;
use framework::standard::{has_correct_roles, has_correct_permissions};
use model::channel::Message;
use model::id::ChannelId;
use std::collections::HashMap;
use std::hash::BuildHasher;
use std::sync::Arc;
use std::fmt::Write;
use super::command::{InternalCommand};
use super::{Args, CommandGroup, CommandOrAlias, HelpOptions, CommandOptions, CommandError, HelpBehaviour};
use utils::Colour;

fn error_embed(channel_id: &ChannelId, input: &str, colour: Colour) {
    let _ = channel_id.send_message(|m| {
        m.embed(|e| e.colour(colour).description(input))
    });
}

fn remove_aliases(cmds: &HashMap<String, CommandOrAlias>) -> HashMap<&String, &InternalCommand> {
    let mut result = HashMap::new();

    for (n, v) in cmds {
        if let CommandOrAlias::Command(ref cmd) = *v {
            result.insert(n, cmd);
        }
    }

    result
}

/// Checks whether a user is member of required roles
/// and given the required permissions.
pub fn has_all_requirements(cmd: &Arc<CommandOptions>, msg: &Message) -> bool {
    if let Some(guild) = msg.guild() {
        let guild = guild.read();

        if let Some(member) = guild.members.get(&msg.author.id) {

            if let Ok(permissions) = member.permissions() {

                if cmd.allowed_roles.is_empty() {
                    return permissions.administrator() || has_correct_permissions(cmd, msg);
                } else {
                    return permissions.administrator() || (has_correct_roles(cmd, &guild, member) && has_correct_permissions(cmd, msg));
                }
            }
        }
    }
    !cmd.guild_only
}

/// Posts an embed showing each individual command group and its commands.
///
/// # Examples
///
/// Use the command with `exec_help`:
///
/// ```rust
/// # use serenity::prelude::*;
/// # struct Handler;
/// #
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler).unwrap();
/// #
/// use serenity::framework::standard::{StandardFramework, help_commands};
///
/// client.with_framework(StandardFramework::new()
///     .help(help_commands::with_embeds));
/// ```
pub fn with_embeds<H: BuildHasher>(
    _: &mut Context,
    msg: &Message,
    help_options: &HelpOptions,
    groups: HashMap<String, Arc<CommandGroup>, H>,
    args: &Args
) -> Result<(), CommandError> {
    if !args.is_empty() {
        let name = args.full();

        for (group_name, group) in groups {
            let mut found: Option<(&String, &InternalCommand)> = None;

            for (command_name, command) in &group.commands {
                let with_prefix = if let Some(ref prefix) = group.prefix {
                    format!("{} {}", prefix, command_name)
                } else {
                    command_name.to_string()
                };

                if name == with_prefix || name == *command_name {
                    match *command {
                        CommandOrAlias::Command(ref cmd) => {
                            if has_all_requirements(&cmd.options(), msg) {
                                found = Some((command_name, cmd));
                            } else {
                                break;
                            }
                        },
                        CommandOrAlias::Alias(ref name) => {
                            let actual_command = &group.commands[name];

                            match *actual_command {
                                CommandOrAlias::Command(ref cmd) => {
                                    if has_all_requirements(&cmd.options(), msg) {
                                        found = Some((name, cmd));
                                    } else {
                                        break;
                                    }
                                },

                                CommandOrAlias::Alias(ref name) => {
                                    let _ = msg.channel_id.say(help_options.suggestion_text.replace("{}", name));
                                    return Ok(());
                                },
                            }
                        },
                    }
                }
            }

            if let Some((command_name, command)) = found {
                let command = command.options();
                if !command.help_available {
                    error_embed(&msg.channel_id, &help_options.no_help_available_text, help_options.embed_error_colour);

                    return Ok(());
                }

                let _ = msg.channel_id.send_message(|m| {
                    m.embed(|e| {
                        let mut embed = e.colour(help_options.embed_success_colour).title(command_name.clone());

                        if let Some(ref desc) = command.desc {
                            embed = embed.description(desc);
                        }

                        if let Some(ref usage) = command.usage {
                            let value = format!("`{} {}`", command_name.clone(), usage);

                            embed = embed.field(&help_options.usage_label, value, true);
                        }

                        if let Some(ref example) = command.example {
                            let value = format!("`{} {}`", command_name.clone(), example);

                            embed = embed.field(&help_options.usage_sample_label, value, true);
                        }

                        if group_name != "Ungrouped" {
                            embed = embed.field(&help_options.grouped_label, group_name, true);
                        }

                        if !command.aliases.is_empty() {
                            let aliases = command.aliases.join(", ");

                            embed = embed.field(&help_options.aliases_label, aliases, true);
                        }

                        let available = if command.dm_only {
                            &help_options.dm_only_text
                        } else if command.guild_only {
                            &help_options.guild_only_text
                        } else {
                            &help_options.dm_and_guild_text
                        };

                        embed = embed.field(&help_options.available_text, available, true);

                        embed
                    })
                });

                return Ok(());
            }
        }

        let error_msg = help_options.command_not_found_text.replace("{}", name);
        error_embed(&msg.channel_id, &error_msg, help_options.embed_error_colour);

        return Ok(());
    }

    let _ = msg.channel_id.send_message(|m| {
        m.embed(|mut e| {

            if let Some(striked_command_text) = help_options.striked_commands_tip.clone() {
                e = e.colour(help_options.embed_success_colour).description(
                    format!("{}\n{}", &help_options.individual_command_tip, &striked_command_text),
                );
            } else {
                e = e.colour(help_options.embed_success_colour).description(
                    &help_options.individual_command_tip,
                );
            }

            let mut group_names = groups.keys().collect::<Vec<_>>();
            group_names.sort();

            for group_name in group_names {
                let group = &groups[group_name];
                let mut desc = String::new();

                if let Some(ref x) = group.prefix {
                    let _ = write!(desc, "{}: `{}`\n", &help_options.group_prefix, x);
                }

                let mut has_commands = false;

                let commands = remove_aliases(&group.commands);
                let mut command_names = commands.keys().collect::<Vec<_>>();
                command_names.sort();

                for name in command_names {
                    let cmd = &commands[name];
                    let cmd = cmd.options();

                    if !cmd.dm_only && !cmd.guild_only || cmd.dm_only && msg.is_private() || cmd.guild_only && !msg.is_private() {
                        if cmd.help_available && has_correct_permissions(&cmd, msg) {
                            let _ = write!(desc, "`{}`\n", name);
                            has_commands = true;
                        } else {
                            match help_options.lacking_permissions {
                                HelpBehaviour::Strike => {
                                    let name = format!("~~`{}`~~", &name);
                                    let _ = write!(desc, "{}\n", name);
                                    has_commands = true;
                                },
                                HelpBehaviour::Nothing => {
                                    let _ = write!(desc, "`{}`\n", name);
                                    has_commands = true;
                                },
                                HelpBehaviour::Hide => {
                                    continue;
                                },
                            }
                        }
                    } else {
                        match help_options.wrong_channel {
                            HelpBehaviour::Strike => {
                                let name = format!("~~`{}`~~", &name);
                                let _ = write!(desc, "{}\n", name);
                                has_commands = true;
                            },
                            HelpBehaviour::Nothing => {
                                let _ = write!(desc, "`{}`\n", name);
                                has_commands = true;
                            },
                            HelpBehaviour::Hide => {
                                continue;
                            },
                        }
                    }
                }

                if has_commands {
                    e = e.field(&group_name[..], &desc[..], true);
                }
            }
            e
        })
    });

    Ok(())
}

/// Posts formatted text displaying each individual command group and its commands.
///
/// # Examples
///
/// Use the command with `exec_help`:
///
/// ```rust
/// # use serenity::prelude::*;
/// # struct Handler;
/// #
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler).unwrap();
/// #
/// use serenity::framework::standard::{StandardFramework, help_commands};
///
/// client.with_framework(StandardFramework::new()
///     .help(help_commands::plain));
/// ```
pub fn plain<H: BuildHasher>(
    _: &mut Context,
    msg: &Message,
    help_options: &HelpOptions,
    groups: HashMap<String, Arc<CommandGroup>, H>,
    args: &Args
) -> Result<(), CommandError> {
    if !args.is_empty() {
        let name = args.full();

        for (group_name, group) in groups {
            let mut found: Option<(&String, &InternalCommand)> = None;

            for (command_name, command) in &group.commands {
                let with_prefix = if let Some(ref prefix) = group.prefix {
                    format!("{} {}", prefix, command_name)
                } else {
                    command_name.to_string()
                };

                if name == with_prefix || name == *command_name {
                    match *command {
                        CommandOrAlias::Command(ref cmd) => {
                            if has_all_requirements(&cmd.options(), msg) {
                                found = Some((command_name, cmd));
                            }
                            else {
                                break;
                            }
                        },
                        CommandOrAlias::Alias(ref name) => {
                            let actual_command = &group.commands[name];

                            match *actual_command {
                                CommandOrAlias::Command(ref cmd) => {
                                    if has_all_requirements(&cmd.options(), msg) {
                                        found = Some((name, cmd));
                                    }
                                    else {
                                        break;
                                    }
                                },

                                CommandOrAlias::Alias(ref name) => {
                                    let _ = msg.channel_id.say(help_options.suggestion_text.replace("{}", name));
                                    return Ok(());
                                },
                            }
                        },
                    }
                }
            }

            if let Some((command_name, command)) = found {
                let command = command.options();

                if !command.help_available {
                    let _ = msg.channel_id.say(&help_options.no_help_available_text);
                    return Ok(());
                }

                let mut result = format!("**{}**\n", command_name);

                if !command.aliases.is_empty() {
                    let aliases = command.aliases.join("`, `");
                    let _ = write!(result, "**{}:** `{}`\n", help_options.aliases_label, aliases);
                }

                if let Some(ref desc) = command.desc {
                    let _ = write!(result, "**{}:** {}\n", help_options.description_label, desc);
                }

                if let Some(ref usage) = command.usage {
                    let _ = write!(result, "**{}:** `{} {}`\n", help_options.usage_label, command_name, usage);
                }

                if let Some(ref example) = command.example {
                    let _ = write!(result, "**{}:** `{} {}`\n", help_options.usage_sample_label, command_name, example);
                }

                if group_name != "Ungrouped" {
                    let _ = write!(result, "**{}:** {}\n", help_options.grouped_label, group_name);
                }

                let only = if command.dm_only {
                    &help_options.dm_only_text
                } else if command.guild_only {
                    &help_options.guild_only_text
                } else {
                    &help_options.dm_and_guild_text
                };

                result.push_str(&format!("**{}:** ", &help_options.available_text));
                result.push_str(only);
                result.push_str(".\n");

                let _ = msg.channel_id.say(&result);

                return Ok(());
            }
        }

        let _ = msg.channel_id
            .say(&help_options.suggestion_text.replace("{}", name));

        return Ok(());
    }

    let mut result = "**Commands**\n".to_string();

    if let Some(striked_command_text) = help_options.striked_commands_tip.clone() {
        let _ = write!(result, "{}\n{}\n\n", &help_options.individual_command_tip, &striked_command_text);
    } else {
        let _ = write!(result, "{}\n\n", &help_options.individual_command_tip);
    }

    let mut group_names = groups.keys().collect::<Vec<_>>();
    group_names.sort();

    for group_name in group_names {
        let group = &groups[group_name];
        let mut group_help = String::new();

        let commands = remove_aliases(&group.commands);
        let mut command_names = commands.keys().collect::<Vec<_>>();
        command_names.sort();

        for name in command_names {
            let cmd = &commands[name];
            let cmd = cmd.options();

            if !cmd.dm_only && !cmd.guild_only || cmd.dm_only && msg.is_private() || cmd.guild_only && !msg.is_private() {
                if cmd.help_available && has_correct_permissions(&cmd, msg) {
                    let _ = write!(group_help, "`{}` ", name);
                } else {
                    match help_options.lacking_permissions {
                        HelpBehaviour::Strike => {
                            let name = format!("~~`{}`~~", &name);
                            let _ = write!(group_help, "{} ", name);
                        },
                        HelpBehaviour::Nothing => {
                            let _ = write!(group_help, "`{}` ", name);
                        },
                        HelpBehaviour::Hide => {
                            continue;
                        },
                    }
                }
            } else {
                match help_options.wrong_channel {
                    HelpBehaviour::Strike => {
                        let name = format!("~~`{}`~~", &name);
                        let _ = write!(group_help, "{} ", name);
                    },
                    HelpBehaviour::Nothing => {
                        let _ = write!(group_help, "`{}` ", name);
                    },
                    HelpBehaviour::Hide => {
                        continue;
                    },
                }
            }
        }

        if !group_help.is_empty() {
            let _ = write!(result, "**{}:** ", group_name);

            if let Some(ref x) = group.prefix {
                let _ = write!(result, "({}: `{}`): ", help_options.group_prefix, x);
            }

            result.push_str(&group_help);
            result.push('\n');
        }
    }

    let _ = msg.channel_id.say(&result);

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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(bad_style)]

extern crate "rust-netmap" as netmap;
extern crate libc;

use libc::{c_void, size_t, c_int, c_ulong, c_short};
use self::netmap::netmap_user::{nm_open, nm_inject, nm_close, nm_nextpkt, nm_desc, nm_pkthdr,
                                NETMAP_FD};

use std::ffi::CString;
use std::io::{IoResult, IoError};
use std::mem;
use std::ptr;
use std::raw;
use std::sync::Arc;

use datalink::DataLinkChannelType;
use packet::Packet;
use packet::ethernet::{EthernetHeader, MutableEthernetHeader};
use util::{NetworkInterface};

#[cfg(target_os = "linux")]
#[repr(C)]
struct pollfd {
    fd: c_int,
    events: c_short,
    revents: c_short
}

#[cfg(target_os = "linux")]
const POLLIN: c_short = 0x0001;

type nfds_t = c_ulong;

extern {
    fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int;
}

struct NmDesc {
    desc: *mut nm_desc,
}

impl NmDesc {
    fn new(iface: &NetworkInterface) -> IoResult<NmDesc> {
        let ifname = CString::from_slice(("netmap:".to_string() + iface.name.as_slice()).as_bytes());
        let desc = unsafe {
            nm_open(ifname.as_ptr(), ptr::null(), 0, ptr::null())
        };

        if desc.is_null() {
            Err(IoError::last_error())
        } else {
            Ok(NmDesc {
                desc: desc
            })
        }
    }
}

impl Drop for NmDesc {
    fn drop(&mut self) {
        unsafe {
            nm_close(self.desc);
        }
    }
}

pub struct DataLinkSenderImpl {
    desc: Arc<NmDesc>
}

impl DataLinkSenderImpl {
    // FIXME This is incredibly inefficient
    pub fn build_and_send<F>(&mut self, num_packets: usize, packet_size: usize,
                          func: &mut F) -> Option<IoResult<()>>
        where F : FnMut(MutableEthernetHeader)
    {
        for _ in range(0, num_packets) {
            let mut vec: Vec<u8> = Vec::with_capacity(packet_size);
            {
                let meh = MutableEthernetHeader::new(vec.as_mut_slice());
                func(meh);
            }

            if let None = self.send_to(EthernetHeader::new(vec.as_slice()), None) {
                // FIXME This is wrong
                return None;
            }
        }

        Some(Ok(()))
    }

    pub fn send_to(&mut self, packet: EthernetHeader, _dst: Option<NetworkInterface>)
        -> Option<IoResult<()>> {
        if unsafe {
               nm_inject(self.desc.desc,
                         packet.packet().as_ptr() as *const c_void,
                         packet.packet().len() as size_t)
           } > 0 {
            Some(Ok(()))
        } else {
            // FIXME This is wrong
            None
        }
    }
}

pub struct DataLinkReceiverImpl {
    desc: Arc<NmDesc>,
}

impl DataLinkReceiverImpl {
    // FIXME Layer 3
    pub fn iter<'a>(&'a mut self) -> DataLinkChannelIteratorImpl<'a> {
        DataLinkChannelIteratorImpl {
            pc: self,
        }
    }
}

pub fn datalink_channel(network_interface: &NetworkInterface,
                        _write_buffer_size: usize,
                        _read_buffer_size: usize,
                        _channel_type: DataLinkChannelType)
    -> IoResult<(DataLinkSenderImpl, DataLinkReceiverImpl)> {
    // FIXME probably want one for each of send/recv
    let desc = NmDesc::new(network_interface);
    match desc {
        Ok(desc) => {
            let arc = Arc::new(desc);

            Ok((DataLinkSenderImpl { desc: arc.clone() },
                DataLinkReceiverImpl { desc: arc }))
        },
        Err(e) => Err(e)
    }
}

pub struct DataLinkChannelIteratorImpl<'a> {
    pc: &'a mut DataLinkReceiverImpl,
}

impl<'a> DataLinkChannelIteratorImpl<'a> {
    pub fn next<'c>(&'c mut self) -> IoResult<EthernetHeader<'c>> {
        let mut fds = pollfd {
            fd: unsafe { NETMAP_FD(self.pc.desc.desc) },
            events: POLLIN,
            revents: 0,
        };
        // FIXME Don't do this with each call
        // FIXME Check error code
        // FIXME epoll/kqueue
        unsafe { poll(&mut fds, 1, -1) };
        let mut h: nm_pkthdr = unsafe { mem::zeroed() };
        let buf = unsafe { nm_nextpkt(self.pc.desc.desc, &mut h) };
        if buf.is_null() {
            // FIXME Doesn't mean there's an error
            return Err(IoError::last_error());
        }
        Ok(EthernetHeader::new( unsafe {
            mem::transmute(raw::Slice { data: buf, len: h.len as usize })
        }))
    }
}

<commit_msg>Need to poll to write as well as send.<commit_after>// Copyright (c) 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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(bad_style)]

extern crate "rust-netmap" as netmap;
extern crate libc;

use libc::{c_void, size_t, c_int, c_ulong, c_short};
use self::netmap::netmap_user::{nm_open, nm_inject, nm_close, nm_nextpkt, nm_desc, nm_pkthdr,
                                NETMAP_FD};

use std::ffi::CString;
use std::io::{IoResult, IoError};
use std::mem;
use std::ptr;
use std::raw;
use std::sync::Arc;

use datalink::DataLinkChannelType;
use packet::Packet;
use packet::ethernet::{EthernetHeader, MutableEthernetHeader};
use util::{NetworkInterface};

#[cfg(target_os = "linux")]
#[repr(C)]
struct pollfd {
    fd: c_int,
    events: c_short,
    revents: c_short
}

#[cfg(target_os = "linux")]
const POLLIN: c_short = 0x0001;
#[cfg(target_os = "linux")]
const POLLOUT: c_short = 0x0004;

type nfds_t = c_ulong;

extern {
    fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int;
}

struct NmDesc {
    desc: *mut nm_desc,
}

impl NmDesc {
    fn new(iface: &NetworkInterface) -> IoResult<NmDesc> {
        let ifname = CString::from_slice(("netmap:".to_string() + iface.name.as_slice()).as_bytes());
        let desc = unsafe {
            nm_open(ifname.as_ptr(), ptr::null(), 0, ptr::null())
        };

        if desc.is_null() {
            Err(IoError::last_error())
        } else {
            Ok(NmDesc {
                desc: desc
            })
        }
    }
}

impl Drop for NmDesc {
    fn drop(&mut self) {
        unsafe {
            nm_close(self.desc);
        }
    }
}

pub struct DataLinkSenderImpl {
    desc: Arc<NmDesc>
}

impl DataLinkSenderImpl {
    // FIXME This is incredibly inefficient
    pub fn build_and_send<F>(&mut self, num_packets: usize, packet_size: usize,
                          func: &mut F) -> Option<IoResult<()>>
        where F : FnMut(MutableEthernetHeader)
    {
        for _ in range(0, num_packets) {
            let mut vec: Vec<u8> = Vec::with_capacity(packet_size);
            {
                let meh = MutableEthernetHeader::new(vec.as_mut_slice());
                func(meh);
            }

            if let None = self.send_to(EthernetHeader::new(vec.as_slice()), None) {
                // FIXME This is wrong
                return None;
            }
        }

        Some(Ok(()))
    }

    pub fn send_to(&mut self, packet: EthernetHeader, _dst: Option<NetworkInterface>)
        -> Option<IoResult<()>> {
        let mut fds = pollfd {
            fd: unsafe { NETMAP_FD(self.desc.desc) },
            events: POLLOUT,
            revents: 0,
        };
        unsafe { poll(&mut fds, 1, -1) };
        if unsafe {

               nm_inject(self.desc.desc,
                         packet.packet().as_ptr() as *const c_void,
                         packet.packet().len() as size_t)
           } > 0 {
            Some(Ok(()))
        } else {
            // FIXME This is wrong
            None
        }
    }
}

pub struct DataLinkReceiverImpl {
    desc: Arc<NmDesc>,
}

impl DataLinkReceiverImpl {
    // FIXME Layer 3
    pub fn iter<'a>(&'a mut self) -> DataLinkChannelIteratorImpl<'a> {
        DataLinkChannelIteratorImpl {
            pc: self,
        }
    }
}

pub fn datalink_channel(network_interface: &NetworkInterface,
                        _write_buffer_size: usize,
                        _read_buffer_size: usize,
                        _channel_type: DataLinkChannelType)
    -> IoResult<(DataLinkSenderImpl, DataLinkReceiverImpl)> {
    // FIXME probably want one for each of send/recv
    let desc = NmDesc::new(network_interface);
    match desc {
        Ok(desc) => {
            let arc = Arc::new(desc);

            Ok((DataLinkSenderImpl { desc: arc.clone() },
                DataLinkReceiverImpl { desc: arc }))
        },
        Err(e) => Err(e)
    }
}

pub struct DataLinkChannelIteratorImpl<'a> {
    pc: &'a mut DataLinkReceiverImpl,
}

impl<'a> DataLinkChannelIteratorImpl<'a> {
    pub fn next<'c>(&'c mut self) -> IoResult<EthernetHeader<'c>> {
        let mut fds = pollfd {
            fd: unsafe { NETMAP_FD(self.pc.desc.desc) },
            events: POLLIN,
            revents: 0,
        };
        // FIXME Don't do this with each call
        // FIXME Check error code
        // FIXME epoll/kqueue
        unsafe { poll(&mut fds, 1, -1) };
        let mut h: nm_pkthdr = unsafe { mem::zeroed() };
        let buf = unsafe { nm_nextpkt(self.pc.desc.desc, &mut h) };
        if buf.is_null() {
            // FIXME Doesn't mean there's an error
            return Err(IoError::last_error());
        }
        Ok(EthernetHeader::new( unsafe {
            mem::transmute(raw::Slice { data: buf, len: h.len as usize })
        }))
    }
}

<|endoftext|>


<commit_before>extern crate itertools;
use self::itertools::Itertools;
extern crate crossbeam;
use std;

#[derive(Debug, Copy, Clone)]
pub struct Endian {
  big: bool,
}

impl Endian {
  pub fn ru32(&self, buf: &[u8], pos: usize) -> u32 {
    if self.big {
      BEu32(buf,pos)
    } else {
      LEu32(buf,pos)
    }
  }

  pub fn ru16(&self, buf: &[u8], pos: usize) -> u16 {
    if self.big {
      BEu16(buf,pos)
    } else {
      LEu16(buf,pos)
    }
  }
}

pub static BIG_ENDIAN: Endian = Endian{big: true};
pub static LITTLE_ENDIAN: Endian = Endian{big: false};

#[allow(non_snake_case)] pub fn BEu32(buf: &[u8], pos: usize) -> u32 {
  (buf[pos] as u32) << 24 |
  (buf[pos+1] as u32) << 16 |
  (buf[pos+2] as u32) << 8 |
  (buf[pos+3] as u32)
}

#[allow(non_snake_case)] pub fn LEu32(buf: &[u8], pos: usize) -> u32 {
  (buf[pos] as u32) |
  (buf[pos+1] as u32) << 8 |
  (buf[pos+2] as u32) << 16 |
  (buf[pos+3] as u32) << 24
}

#[allow(non_snake_case)] pub fn BEu16(buf: &[u8], pos: usize) -> u16 {
  (buf[pos] as u16) << 8 | (buf[pos+1] as u16)
}

#[allow(non_snake_case)] pub fn LEu16(buf: &[u8], pos: usize) -> u16 {
  (buf[pos] as u16) | (buf[pos+1] as u16) << 8
}

pub fn decode_12be(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
  decode_threaded(width, height, &(|out: &mut [u16], start, width, height| {
    let inb = &buf[((start*width*12/8) as usize)..];
    let mut pos: usize = 0;

    for row in 0..height {
      for col in (0..width).step(2) {
        let g1: u16 = inb[pos] as u16;
        let g2: u16 = inb[pos+1] as u16;
        let g3: u16 = inb[pos+2] as u16;
        pos += 3;

        out[width*row+col]   = (g1 << 4) | (g2 >> 4);
        out[width*row+col+1] = ((g2 & 0x0f) << 8) | g3;
      }
    }
  }))
}

pub fn decode_12le(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
  decode_threaded(width, height, &(|out: &mut [u16], start, width, height| {
    let inb = &buf[((start*width*12/8) as usize)..];
    let mut pos: usize = 0;

    for row in 0..height {
      for col in (0..width).step(2) {
        let g1: u16 = inb[pos] as u16;
        let g2: u16 = inb[pos+1] as u16;
        let g3: u16 = inb[pos+2] as u16;
        pos += 3;

        out[width*row+col]   = ((g2 & 0x0f) << 8) | g1;
        out[width*row+col+1] = (g3 << 4) | (g2 >> 4);
      }
    }
  }))
}

pub fn decode_12be_unpacked(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
  decode_threaded(width, height, &(|out: &mut [u16], start, width, height| {
    let inb = &buf[((start*width*2) as usize)..];
    let mut pos: usize = 0;

    for row in 0..height {
      for col in 0..width {
        let g1: u16 = inb[pos] as u16;
        let g2: u16 = inb[pos+1] as u16;
        pos += 2;

        out[width*row+col] = ((g1 & 0x0f) << 8) | g2;
      }
    }
  }))
}

pub fn decode_16le(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
  decode_threaded(width, height, &(|out: &mut [u16], start, width, height| {
    let inb = &buf[((start*width*2) as usize)..];
    let mut pos: usize = 0;

    for row in 0..height {
      for col in 0..width {
        let g1: u16 = inb[pos] as u16;
        let g2: u16 = inb[pos+1] as u16;
        pos += 2;

        out[width*row+col] = (g2 << 8) | g1;
      }
    }
  }))
}

pub fn decode_threaded<F>(width: usize, height: usize, closure: &F) -> Vec<u16>
  where F : Fn(&mut [u16], usize, usize, usize)+std::marker::Sync {
  let mut out: Vec<u16> = vec![0; (width*height) as usize];

  // Default to 4 threads as that should be close to the ideal speedup on most
  // machines. In the future we need a way to have this be a parameter or even
  // to set it dynamically based on how loaded the machine is.
  let threads = 4;

  // If we're only using one thread do it all sequentially and be done with it
  if threads < 2 || height < threads {
    closure(&mut out, 0, width, height);
    return out
  }

  let mut split = height/threads;
  if split*threads < height { // Make sure the last split is always the smallest
    split += 1;
  }

  crossbeam::scope(|scope| {
    let mut handles = Vec::new();
    for (i,out_part) in (&mut out[..]).chunks_mut(split*width).enumerate() {
      let start = split*(i);
      let tall = out_part.len()/width;
      let handle = scope.spawn(move || {
        closure(out_part, start, width, tall);
      });
      handles.push(handle);
    }

    for h in handles { h.join() };
  });

  out
}

#[derive(Debug, Clone)]
pub struct LookupTable {
  table: Vec<(u16, u16, u16)>,
}

impl LookupTable {
  pub fn new(table: &[u16]) -> LookupTable {
    let mut tbl = vec![(0,0,0); table.len()];
    for i in 0..table.len() {
      let center = table[i];
      let lower = if i > 0 {table[i-1]} else {center};
      let upper = if i < (table.len()-1) {table[i+1]} else {center};
      let base = center - ((upper - lower + 2) / 4);
      let delta = upper - lower;
      tbl[i] = (center, base, delta);
    }
    LookupTable {
      table: tbl,
    }
  }

//  pub fn lookup(&self, value: u16) -> u16 {
//    let (val, _, _) = self.table[value as usize];
//    val
//  }

  pub fn dither(&self, value: u16, rand: &mut u32) -> u16 {
    let (_, sbase, sdelta) = self.table[value as usize];
    let base = sbase as u32;
    let delta = sdelta as u32;
    let pixel = base + ((delta * (*rand & 2047) + 1024) >> 12);
    *rand = 15700 * (*rand & 65535) + (*rand >> 16);
    pixel as u16
  }
}

pub struct BitPump<'a> {
  buffer: &'a [u8],
  pos: usize,
  bits: u64,
  nbits: u32,
}

impl<'a> BitPump<'a> {
  pub fn new(src: &'a [u8]) -> BitPump {
    BitPump {
      buffer: src,
      pos: 0,
      bits: 0,
      nbits: 0,
    }
  }

  fn fill_bits(&mut self) {
    let inbits: u64 = LEu32(self.buffer, self.pos) as u64;
    self.pos += 4;
    self.bits = ((inbits << 32) | (self.bits << (32-self.nbits))) >> (32-self.nbits);
    self.nbits += 32;
  }

  pub fn peek_bits(&mut self, num: u32) -> u32 {
    if num > self.nbits {
      self.fill_bits();
    }
    (self.bits & (0x0ffffffffu64 >> (32-num))) as u32
  }

  pub fn get_bits(&mut self, num: u32) -> u32 {
    let val = self.peek_bits(num);
    self.bits = self.bits >> num;
    self.nbits -= num;
    val
  }
}
<commit_msg>Convert basic decoders to iterators<commit_after>extern crate crossbeam;
use std;

#[derive(Debug, Copy, Clone)]
pub struct Endian {
  big: bool,
}

impl Endian {
  pub fn ru32(&self, buf: &[u8], pos: usize) -> u32 {
    if self.big {
      BEu32(buf,pos)
    } else {
      LEu32(buf,pos)
    }
  }

  pub fn ru16(&self, buf: &[u8], pos: usize) -> u16 {
    if self.big {
      BEu16(buf,pos)
    } else {
      LEu16(buf,pos)
    }
  }
}

pub static BIG_ENDIAN: Endian = Endian{big: true};
pub static LITTLE_ENDIAN: Endian = Endian{big: false};

#[allow(non_snake_case)] pub fn BEu32(buf: &[u8], pos: usize) -> u32 {
  (buf[pos] as u32) << 24 |
  (buf[pos+1] as u32) << 16 |
  (buf[pos+2] as u32) << 8 |
  (buf[pos+3] as u32)
}

#[allow(non_snake_case)] pub fn LEu32(buf: &[u8], pos: usize) -> u32 {
  (buf[pos] as u32) |
  (buf[pos+1] as u32) << 8 |
  (buf[pos+2] as u32) << 16 |
  (buf[pos+3] as u32) << 24
}

#[allow(non_snake_case)] pub fn BEu16(buf: &[u8], pos: usize) -> u16 {
  (buf[pos] as u16) << 8 | (buf[pos+1] as u16)
}

#[allow(non_snake_case)] pub fn LEu16(buf: &[u8], pos: usize) -> u16 {
  (buf[pos] as u16) | (buf[pos+1] as u16) << 8
}

pub fn decode_12be(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
  decode_threaded(width, height, &(|out: &mut [u16], start, width, _| {
    let inb = &buf[((start*width*12/8) as usize)..];

    for (o, i) in out.chunks_mut(2).zip(inb.chunks(3)) {
      let g1: u16 = i[0] as u16;
      let g2: u16 = i[1] as u16;
      let g3: u16 = i[2] as u16;

      o[0] = (g1 << 4) | (g2 >> 4);
      o[1] = ((g2 & 0x0f) << 8) | g3;
    }
  }))
}

pub fn decode_12le(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
  decode_threaded(width, height, &(|out: &mut [u16], start, width, _| {
    let inb = &buf[((start*width*12/8) as usize)..];

    for (o, i) in out.chunks_mut(2).zip(inb.chunks(3)) {
      let g1: u16 = i[0] as u16;
      let g2: u16 = i[1] as u16;
      let g3: u16 = i[2] as u16;

      o[0] = ((g2 & 0x0f) << 8) | g1;
      o[1] = (g3 << 4) | (g2 >> 4);
    }
  }))
}

pub fn decode_12be_unpacked(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
  decode_threaded(width, height, &(|out: &mut [u16], start, width, _| {
    let inb = &buf[((start*width*2) as usize)..];

    for (o, i) in out.chunks_mut(2).zip(inb.chunks(2)) {
      let g1: u16 = i[0] as u16;
      let g2: u16 = i[1] as u16;

      o[0] = ((g1 & 0x0f) << 8) | g2;
    }
  }))
}

pub fn decode_16le(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
  decode_threaded(width, height, &(|out: &mut [u16], start, width, _| {
    let inb = &buf[((start*width*2) as usize)..];

    for (o, i) in out.chunks_mut(2).zip(inb.chunks(2)) {
      let g1: u16 = i[0] as u16;
      let g2: u16 = i[1] as u16;

      o[0] = (g2 << 8) | g1;
    }
  }))
}

pub fn decode_threaded<F>(width: usize, height: usize, closure: &F) -> Vec<u16>
  where F : Fn(&mut [u16], usize, usize, usize)+std::marker::Sync {
  let mut out: Vec<u16> = vec![0; (width*height) as usize];

  // Default to 4 threads as that should be close to the ideal speedup on most
  // machines. In the future we need a way to have this be a parameter or even
  // to set it dynamically based on how loaded the machine is.
  let threads = 4;

  // If we're only using one thread do it all sequentially and be done with it
  if threads < 2 || height < threads {
    closure(&mut out, 0, width, height);
    return out
  }

  let mut split = height/threads;
  if split*threads < height { // Make sure the last split is always the smallest
    split += 1;
  }

  crossbeam::scope(|scope| {
    let mut handles = Vec::new();
    for (i,out_part) in (&mut out[..]).chunks_mut(split*width).enumerate() {
      let start = split*(i);
      let tall = out_part.len()/width;
      let handle = scope.spawn(move || {
        closure(out_part, start, width, tall);
      });
      handles.push(handle);
    }

    for h in handles { h.join() };
  });

  out
}

#[derive(Debug, Clone)]
pub struct LookupTable {
  table: Vec<(u16, u16, u16)>,
}

impl LookupTable {
  pub fn new(table: &[u16]) -> LookupTable {
    let mut tbl = vec![(0,0,0); table.len()];
    for i in 0..table.len() {
      let center = table[i];
      let lower = if i > 0 {table[i-1]} else {center};
      let upper = if i < (table.len()-1) {table[i+1]} else {center};
      let base = center - ((upper - lower + 2) / 4);
      let delta = upper - lower;
      tbl[i] = (center, base, delta);
    }
    LookupTable {
      table: tbl,
    }
  }

//  pub fn lookup(&self, value: u16) -> u16 {
//    let (val, _, _) = self.table[value as usize];
//    val
//  }

  pub fn dither(&self, value: u16, rand: &mut u32) -> u16 {
    let (_, sbase, sdelta) = self.table[value as usize];
    let base = sbase as u32;
    let delta = sdelta as u32;
    let pixel = base + ((delta * (*rand & 2047) + 1024) >> 12);
    *rand = 15700 * (*rand & 65535) + (*rand >> 16);
    pixel as u16
  }
}

pub struct BitPump<'a> {
  buffer: &'a [u8],
  pos: usize,
  bits: u64,
  nbits: u32,
}

impl<'a> BitPump<'a> {
  pub fn new(src: &'a [u8]) -> BitPump {
    BitPump {
      buffer: src,
      pos: 0,
      bits: 0,
      nbits: 0,
    }
  }

  fn fill_bits(&mut self) {
    let inbits: u64 = LEu32(self.buffer, self.pos) as u64;
    self.pos += 4;
    self.bits = ((inbits << 32) | (self.bits << (32-self.nbits))) >> (32-self.nbits);
    self.nbits += 32;
  }

  pub fn peek_bits(&mut self, num: u32) -> u32 {
    if num > self.nbits {
      self.fill_bits();
    }
    (self.bits & (0x0ffffffffu64 >> (32-num))) as u32
  }

  pub fn get_bits(&mut self, num: u32) -> u32 {
    let val = self.peek_bits(num);
    self.bits = self.bits >> num;
    self.nbits -= num;
    val
  }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::io;
use std::fmt;

/// General IO error with an optional path to the offending file.
#[derive(Debug)]
pub struct IOError {
    path: Option<PathBuf>,
    err: io::Error,
}

impl fmt::Display for IOError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.path {
            Some(ref path) => write!(f, "io error occurred on path '{:?}': '{}'", path, self.err),
            None => write!(f, "io error occurred: '{}'", self.err),
        }
    }
}

impl IOError {
    pub(crate) fn with_path(
                            path: PathBuf,
                            err: io::Error)
                            -> Self {
        IOError {
            path: Some(path),
            err: err,
        }
    }
}

impl From<io::Error> for IOError {
    fn from(err: io::Error) -> IOError {
        IOError {
            path: None,
            err: err,
        }
    }
}

/// Error that may occur when opening a directory
#[derive(Debug)]
pub enum OpenDirectoryError {
    /// The underlying directory does not exists.
    DoesNotExist(PathBuf),
    /// The path exists but is not a directory.
    NotADirectory(PathBuf),
}

/// Error that may occur when starting to write in a file
#[derive(Debug)]
pub enum OpenWriteError {
    /// Our directory is WORM, writing an existing file is forbidden.
    /// Checkout the `Directory` documentation.
    FileAlreadyExists(PathBuf),
    /// Any kind of IO error that happens when
    /// writing in the underlying IO device.
    IOError(IOError),
}

impl From<IOError> for OpenWriteError {
    fn from(err: IOError) -> OpenWriteError {
        OpenWriteError::IOError(err)
    }
}

/// Error that may occur when accessing a file read
#[derive(Debug)]
pub enum OpenReadError {
    /// The file does not exists.
    FileDoesNotExist(PathBuf),
    /// Any kind of IO error that happens when
    /// interacting with the underlying IO device.
    IOError(IOError),
}

impl From<IOError> for OpenReadError {
    fn from(err: IOError) -> OpenReadError {
        OpenReadError::IOError(err)
    }
}

/// Error that may occur when trying to delete a file
#[derive(Debug)]
pub enum DeleteError {
    /// The file does not exists.
    FileDoesNotExist(PathBuf),
    /// Any kind of IO error that happens when
    /// interacting with the underlying IO device.
    IOError(IOError),
    /// The file may not be deleted because it is
    /// protected.
    FileProtected(PathBuf),
}

impl From<IOError> for DeleteError {
    fn from(err: IOError) -> DeleteError {
        DeleteError::IOError(err)
    }
}
<commit_msg>impl std error for directory errors<commit_after>use std::error::Error as StdError;
use std::path::PathBuf;
use std::io;
use std::fmt;

/// General IO error with an optional path to the offending file.
#[derive(Debug)]
pub struct IOError {
    path: Option<PathBuf>,
    err: io::Error,
}

impl fmt::Display for IOError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.path {
            Some(ref path) => write!(f, "io error occurred on path '{:?}': '{}'", path, self.err),
            None => write!(f, "io error occurred: '{}'", self.err),
        }
    }
}

impl StdError for IOError {
    fn description(&self) -> &str {
        "io error occurred"
    }

    fn cause(&self) -> Option<&StdError> {
        Some(&self.err)
    }
}

impl IOError {
    pub(crate) fn with_path(
                            path: PathBuf,
                            err: io::Error)
                            -> Self {
        IOError {
            path: Some(path),
            err: err,
        }
    }
}

impl From<io::Error> for IOError {
    fn from(err: io::Error) -> IOError {
        IOError {
            path: None,
            err: err,
        }
    }
}

/// Error that may occur when opening a directory
#[derive(Debug)]
pub enum OpenDirectoryError {
    /// The underlying directory does not exists.
    DoesNotExist(PathBuf),
    /// The path exists but is not a directory.
    NotADirectory(PathBuf),
}

impl fmt::Display for OpenDirectoryError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpenDirectoryError::DoesNotExist(ref path) => write!(f, "the underlying directory '{:?}' does not exist", path),
            OpenDirectoryError::NotADirectory(ref path) => write!(f, "the path '{:?}' exists but is not a directory", path)
        }
    }
}

impl StdError for OpenDirectoryError {
    fn description(&self) -> &str {
        "error occurred while opening a directory"
    }

    fn cause(&self) -> Option<&StdError> {
        None
    }
}

/// Error that may occur when starting to write in a file
#[derive(Debug)]
pub enum OpenWriteError {
    /// Our directory is WORM, writing an existing file is forbidden.
    /// Checkout the `Directory` documentation.
    FileAlreadyExists(PathBuf),
    /// Any kind of IO error that happens when
    /// writing in the underlying IO device.
    IOError(IOError),
}

impl From<IOError> for OpenWriteError {
    fn from(err: IOError) -> OpenWriteError {
        OpenWriteError::IOError(err)
    }
}

impl fmt::Display for OpenWriteError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpenWriteError::FileAlreadyExists(ref path) => write!(f, "the file '{:?}' already exists", path),
            OpenWriteError::IOError(ref err) => write!(f, "an io error occurred while opening a file for writing: '{}'", err)
        }
    }
}

impl StdError for OpenWriteError {
    fn description(&self) -> &str {
        "error occurred while opening a file for writing"
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            OpenWriteError::FileAlreadyExists(_) => None,
            OpenWriteError::IOError(ref err) => Some(err)
        }
    }
}

/// Error that may occur when accessing a file read
#[derive(Debug)]
pub enum OpenReadError {
    /// The file does not exists.
    FileDoesNotExist(PathBuf),
    /// Any kind of IO error that happens when
    /// interacting with the underlying IO device.
    IOError(IOError),
}

impl From<IOError> for OpenReadError {
    fn from(err: IOError) -> OpenReadError {
        OpenReadError::IOError(err)
    }
}

impl fmt::Display for OpenReadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpenReadError::FileDoesNotExist(ref path) => write!(f, "the file '{:?}' does not exist", path),
            OpenReadError::IOError(ref err) => write!(f, "an io error occurred while opening a file for reading: '{}'", err)
        }
    }
}

impl StdError for OpenReadError {
    fn description(&self) -> &str {
        "error occurred while opening a file for reading"
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            OpenReadError::FileDoesNotExist(_) => None,
            OpenReadError::IOError(ref err) => Some(err)
        }
    }
}

/// Error that may occur when trying to delete a file
#[derive(Debug)]
pub enum DeleteError {
    /// The file does not exists.
    FileDoesNotExist(PathBuf),
    /// Any kind of IO error that happens when
    /// interacting with the underlying IO device.
    IOError(IOError),
    /// The file may not be deleted because it is
    /// protected.
    FileProtected(PathBuf),
}

impl From<IOError> for DeleteError {
    fn from(err: IOError) -> DeleteError {
        DeleteError::IOError(err)
    }
}

impl fmt::Display for DeleteError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DeleteError::FileDoesNotExist(ref path) => write!(f, "the file '{:?}' does not exist", path),
            DeleteError::FileProtected(ref path) => write!(f, "the file '{:?}' is protected and can't be deleted", path),
            DeleteError::IOError(ref err) => write!(f, "an io error occurred while opening a file for reading: '{}'", err)
        }
    }
}

impl StdError for DeleteError {
    fn description(&self) -> &str {
        "error occurred while opening a file for reading"
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            DeleteError::FileDoesNotExist(_) => None,
            DeleteError::FileProtected(ref path) => None,
            DeleteError::IOError(ref err) => Some(err)
        }
    }
}<|endoftext|>


<commit_before>// TODO: COPYRIGHT, USE & AUTHORS
use super::ga_core::GASolution;
use super::ga_population::{GAPopulation, GAPopulationSortBasis};
use super::ga_random;

/// Selector Trait
///
/// Interface to Selection Schemes
pub trait GASelector<'a, T: GASolution>
{
    /// Assign the population on which to operate
    fn assign(&mut self, population: &'a mut GAPopulation<T>);
    /// Update internal state.
    /// Some selectors implement an empty update().
    fn update(&mut self) {}

    fn select(&mut self) -> &T;
}

// GASolution-s live as long as the population. Lifetime 'a is bound to the
// population borrowed by the 'population' member, as well as to the enclosed
// GASolution-s, because they share the same memory.
pub struct GARankSelector<'a, T: 'a + GASolution>
{
    // Q: How to make this member common to all GASelectors?
    // Q: Will 'mut' make things more complex? When the rank selector is in
    //    scope and borrowing the population, no other objects will be able
    //    to borrow it, not even in non-mut mode according to the rules.
    // Selectors modify populations (they sort them, for instance), so the
    // reference must be 'mut'.
    // TODO: Implement new() function and drop 'pub' from 'population'.
    pub population: &'a mut GAPopulation<T>,

    pop_sort_basis: GAPopulationSortBasis
}

impl<'a, T: GASolution> GARankSelector<'a, T>
{
    pub fn new(p: &'a mut GAPopulation<T>, sort_basis: GAPopulationSortBasis) -> GARankSelector<'a, T>
    {
        GARankSelector
        {
            population: p,
            pop_sort_basis: sort_basis
        }
    }
}

// TODO: DOC.
impl<'a, T: GASolution> GASelector<'a, T> for GARankSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;
    }

    fn select(&mut self) -> &T
    {
        // Number of individuals that share best score/fitness.
        let mut best_count;

        // Q: sort_int() is pub, but is it meant to be called outside of
        // ga_populations? Ideally, pop_sort_basis would be passed to sort().
        self.population.sort();

        match self.pop_sort_basis
        {
            GAPopulationSortBasis::Raw
            =>  {
                    // Currently, individual(i, sort_basis) returns the ith-best
                    // individual, sort_basis-ordered.
                    // Q: Should individual() (ith_best()) return an optional or
                    //    does it guarantee that it will always return something valid?
                    //    What if the population is still empty?
                    let best_score: f32 = self.population.individual(0, GAPopulationSortBasis::Raw).score();

                    best_count = 1;

                    // Skip 0th best.
                    for i in 1..self.population.size()
                    {
                        if self.population.individual(i, GAPopulationSortBasis::Raw).score()  != best_score
                        {
                            break;
                        }

                        best_count = best_count + 1;
                    }

                    // Select any individual from those that share best score.
                    self.population.individual(ga_random::ga_random_range(0, best_count),
                                               GAPopulationSortBasis::Raw)
                }

            GAPopulationSortBasis::Scaled
            =>  {
                    let best_fitness: f32 = self.population.individual(0, GAPopulationSortBasis::Scaled).fitness();

                    best_count = 1;

                    for i in 1..self.population.size()
                    {
                        if self.population.individual(i, GAPopulationSortBasis::Scaled).fitness() != best_fitness
                        {
                            break;
                        }

                        best_count = best_count + 1;
                    }

                    // Select any individual from those that share best fitness.
                    self.population.individual(ga_random::ga_random_range(0, best_count),
                                               GAPopulationSortBasis::Scaled)
                }
        }
    }
}

pub struct GAUniformSelector<'a, T: 'a + GASolution>
{
    population: &'a mut GAPopulation<T>
}

impl<'a, T: GASolution> GAUniformSelector<'a, T>
{
    pub fn new(p: &'a mut GAPopulation<T>) -> GAUniformSelector<'a, T>
    {
        GAUniformSelector
        {
            population: p
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GAUniformSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;
    }

    // Select any individual at random.
    fn select(&mut self) -> &T
    {
        // Need to sort first, because GAPopulation.individual() draws individuals
        // from the sorted lists.
        // TODO: GAPopulation should implement a method for selecting individuals
        // from the unsorted vector; GAUniformSelector would use it, because it
        // doesn't care about the order.
        self.population.sort();

        // Since selection is at random, it doesn't matter where the individual
        // is drawn from, the Raw/score-sorted or the Scaled/fitness-sorted list.
        self.population.individual(
            ga_random::ga_random_range(0, self.population.size()),
            GAPopulationSortBasis::Raw)
    }
}
<commit_msg>Add GAScoreTypeBasedSelection to GARankSelector.<commit_after>// TODO: COPYRIGHT, USE & AUTHORS
use super::ga_core::GASolution;
use super::ga_population::{GAPopulation, GAPopulationSortBasis};
use super::ga_random;

/// Selector Trait
///
/// Interface to Selection Schemes
pub trait GASelector<'a, T: GASolution>
{
    /// Assign the population on which to operate
    fn assign(&mut self, population: &'a mut GAPopulation<T>);
    /// Update internal state.
    /// Some selectors implement an empty update().
    fn update(&mut self) {}

    fn select(&mut self) -> &T;
}

pub trait GAScoreTypeBasedSelection<T: GASolution>
{
    fn score(&self, individual: &T) -> f32;

    fn population_sort_basis(&self) -> GAPopulationSortBasis;
}

pub struct GARawScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GARawScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.score()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Raw
    }
}

pub struct GAScaledScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GAScaledScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.fitness()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Scaled
    }
}

// GASolution-s live as long as the population. Lifetime 'a is bound to the
// population borrowed by the 'population' member, as well as to the enclosed
// GASolution-s, because they share the same memory.
pub struct GARankSelector<'a, T: 'a + GASolution>
{
    // Q: How to make this member common to all GASelectors?
    // Q: Will 'mut' make things more complex? When the rank selector is in
    //    scope and borrowing the population, no other objects will be able
    //    to borrow it, not even in non-mut mode according to the rules.
    // Selectors modify populations (they sort them, for instance), so the
    // reference must be 'mut'.
    population: &'a mut GAPopulation<T>,

    // TODO: Check correct lifetime.
    score_type_selection: &'a GAScoreTypeBasedSelection<T>
}

impl<'a, T: GASolution> GARankSelector<'a, T>
{
    pub fn new(p: &'a mut GAPopulation<T>, s: &'a GAScoreTypeBasedSelection<T>) -> GARankSelector<'a, T>
    {
        GARankSelector
        {
            population: p,
            score_type_selection: s
        }
    }
}

// TODO: DOC.
impl<'a, T: GASolution> GASelector<'a, T> for GARankSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;
    }

    fn select(&mut self) -> &T
    {
        // TODO: Confirm assumption that population has 1 individual at least.
        // Number of individuals that share best score.
        let mut best_count = 1;

        self.population.sort();

        // TODO: Use best() when implemented.
        // Q: Should individual() (ith_best()) return an optional or
        //    does it guarantee that it will always return something valid?
        //    What if the population is still empty?
        let best_score: f32 = self.score_type_selection.score(self.population.individual(0, self.score_type_selection.population_sort_basis()));

        // Skip 0th best.
        for i in 1..self.population.size()
        {
            if self.score_type_selection.score(self.population.individual(i, self.score_type_selection.population_sort_basis())) != best_score
            {
                break;
            }

            best_count = best_count + 1;
        }

        // Select any individual from those that share best score.
        self.population.individual(ga_random::ga_random_range(0, best_count), self.score_type_selection.population_sort_basis())
    }
}

pub struct GAUniformSelector<'a, T: 'a + GASolution>
{
    population: &'a mut GAPopulation<T>
}

impl<'a, T: GASolution> GAUniformSelector<'a, T>
{
    pub fn new(p: &'a mut GAPopulation<T>) -> GAUniformSelector<'a, T>
    {
        GAUniformSelector
        {
            population: p
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GAUniformSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;
    }

    // Select any individual at random.
    fn select(&mut self) -> &T
    {
        // Need to sort first, because GAPopulation.individual() draws individuals
        // from the sorted lists.
        // TODO: GAPopulation should implement a method for selecting individuals
        // from the unsorted vector; GAUniformSelector would use it, because it
        // doesn't care about the order.
        self.population.sort();

        // Since selection is at random, it doesn't matter where the individual
        // is drawn from, the Raw/score-sorted or the Scaled/fitness-sorted list.
        self.population.individual(
            ga_random::ga_random_range(0, self.population.size()),
            GAPopulationSortBasis::Raw)
    }
}

//pub struct GARouletteWheelSelector<'a, T: 'a + GASolution>
//{
//    population: &'a mut GAPopulation<T>,
//
//    pop_sort_basis: GAPopulationSortBasis,
//
//    wheel_proportions: Vec<f32>,
//
//    wheel_is_dirty: bool
//}
//
//impl<'a, T: GASolution> GASelector<'a, T> for GARouletteWheelSelector<'a, T>
//{
//    fn assign(&mut self, population: &'a mut GAPopulation<T>)
//    {
//        self.population = population;
//
//        if self.population.size() != self.wheel_proportions.len()
//        {
//            self.wheel_proportions.resize(self.population.size(), 0.0);
//        }
//
//        self.wheel_is_dirty = true;
//    }
//
//    fn select(&mut self) -> &T
//    {
//        // Dummy.
//        self.population.individual(0, GAPopulationSortBasis::Raw)
//    }
//
//    fn update(&mut self)
//    {
//        // TODO: Replace with cached stats when implemented.
//        // TODO: Replace with best() and worst() once there is one for Raw and one for Scaled.
//        let max =  match self.pop_sort_basis
//                   {
//                        GAPopulationSortBasis::Raw    => self.population.individual(0, GAPopulationSortBasis::Raw).score(),
//                        GAPopulationSortBasis::Scaled => self.population.individual(0, GAPopulationSortBasis::Scaled).fitness()
//                   };
//
//        let min =  match self.pop_sort_basis
//                   {
//                        GAPopulationSortBasis::Raw    => self.population.individual(self.population.size()-1, GAPopulationSortBasis::Raw).score(),
//                        GAPopulationSortBasis::Scaled => self.population.individual(self.population.size()-1, GAPopulationSortBasis::Scaled).fitness()
//                   };
//    }
//}
<|endoftext|>