<commit_before>use client::Context;
use model::{
    channel::{
        Message,
        Channel,
    },
    Permissions
};
use std::{
    collections::HashMap,
    fmt,
    fmt::{Debug, Formatter},
    sync::Arc
};
use utils::Colour;
use super::{Args, Configuration, HelpBehaviour};

type CheckFunction = Fn(&mut Context, &Message, &mut Args, &CommandOptions) -> bool
                     + Send
                     + Sync
                     + 'static;

pub struct Check(pub(crate) Box<CheckFunction>);

impl Check {
    pub(crate) fn new<F: Send + Sync + 'static>(f: F) -> Self
        where F: Fn(&mut Context, &Message, &mut Args, &CommandOptions) -> bool
    {
        Check(Box::new(f))
    }
}

impl Debug for Check {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_tuple("Check")
            .field(&"<fn>")
            .finish()
    }
}

pub type HelpFunction = fn(&mut Context, &Message, &HelpOptions, HashMap<String, Arc<CommandGroup>>, &Args)
                   -> Result<(), Error>;

pub struct Help(pub HelpFunction, pub Arc<HelpOptions>);

impl Debug for Help {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Help")
            .field("options", &self.1)
            .finish()
    }
}

impl HelpCommand for Help {
    fn execute(&self, c: &mut Context, m: &Message, ho: &HelpOptions,hm: HashMap<String, Arc<CommandGroup>>, a: &Args) -> Result<(), Error> {
        (self.0)(c, m, ho, hm, a)
    }
}

pub type BeforeHook = Fn(&mut Context, &Message, &str) -> bool + Send + Sync + 'static;
pub type AfterHook = Fn(&mut Context, &Message, &str, Result<(), Error>) + Send + Sync + 'static;
pub type UnrecognisedCommandHook = Fn(&mut Context, &Message, &str) + Send + Sync + 'static;
pub(crate) type InternalCommand = Arc<Command>;
pub type PrefixCheck = Fn(&mut Context, &Message) -> Option<String> + Send + Sync + 'static;

pub enum CommandOrAlias {
    Alias(String),
    Command(InternalCommand),
}

impl fmt::Debug for CommandOrAlias {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CommandOrAlias::Alias(ref s) => f.debug_tuple("CommandOrAlias::Alias").field(&s).finish(),
            CommandOrAlias::Command(ref arc) => f.debug_tuple("CommandOrAlias::Command").field(&arc.options()).finish(),
        }
    }
}

/// An error from a command.
#[derive(Clone, Debug)]
pub struct Error(pub String);

// TODO: Have seperate `From<(&)String>` and `From<&str>` impls via specialization
impl<D: fmt::Display> From<D> for Error {
    fn from(d: D) -> Self {
        Error(d.to_string())
    }
}

#[derive(Debug)]
pub struct CommandGroup {
    pub prefixes: Option<Vec<String>>,
    pub commands: HashMap<String, CommandOrAlias>,
    /// Some fields taken from Command
    pub bucket: Option<String>,
    pub required_permissions: Permissions,
    pub allowed_roles: Vec<String>,
    pub help_available: bool,
    pub dm_only: bool,
    pub guild_only: bool,
    pub owners_only: bool,
    pub help: Option<Arc<Help>>,
    /// A set of checks to be called prior to executing the command-group. The checks
    /// will short-circuit on the first check that returns `false`.
    pub checks: Vec<Check>,
    pub default_command: Option<CommandOrAlias>,
}

impl Default for CommandGroup {
    fn default() -> CommandGroup {
        CommandGroup {
            prefixes: None,
            commands: HashMap::new(),
            bucket: None,
            required_permissions: Permissions::empty(),
            dm_only: false,
            guild_only: false,
            help_available: true,
            owners_only: false,
            allowed_roles: Vec::new(),
            help: None,
            checks: Vec::new(),
            default_command: None,
        }
    }
}

#[derive(Debug)]
pub struct CommandOptions {
    /// A set of checks to be called prior to executing the command. The checks
    /// will short-circuit on the first check that returns `false`.
    pub checks: Vec<Check>,
    /// Ratelimit bucket.
    pub bucket: Option<String>,
    /// Command description, used by other commands.
    pub desc: Option<String>,
    /// Example arguments, used by other commands.
    pub example: Option<String>,
    /// Command usage schema, used by other commands.
    pub usage: Option<String>,
    /// Minumum amount of arguments that should be passed.
    pub min_args: Option<i32>,
    /// Maximum amount of arguments that can be passed.
    pub max_args: Option<i32>,
    /// Permissions required to use this command.
    pub required_permissions: Permissions,
    /// Roles allowed to use this command.
    pub allowed_roles: Vec<String>,
    /// Whether command should be displayed in help list or not, used by other commands.
    pub help_available: bool,
    /// Whether command can be used only privately or not.
    pub dm_only: bool,
    /// Whether command can be used only in guilds or not.
    pub guild_only: bool,
    /// Whether command can only be used by owners or not.
    pub owners_only: bool,
    /// Other names that can be used to call this command instead.
    pub aliases: Vec<String>,
}

#[derive(Debug)]
pub struct HelpOptions {
    /// Suggests a command's name.
    pub suggestion_text: String,
    /// If no help is available, this text will be displayed.
    pub no_help_available_text: String,
    /// How to use a command, `{usage_label}: {command_name} {args}`
    pub usage_label: String,
    /// Actual sample label, `{usage_sample_label}: {command_name} {args}`
    pub usage_sample_label: String,
    /// Text labeling ungrouped commands, `{ungrouped_label}: ...`
    pub ungrouped_label: String,
    /// Text labeling the start of the description.
    pub description_label: String,
    /// Text labeling grouped commands, `{grouped_label} {group_name}: ...`
    pub grouped_label: String,
    /// Text labeling a command's alternative names (aliases).
    pub aliases_label: String,
    /// Text specifying that a command is only usable in a guild.
    pub guild_only_text: String,
    /// Text specifying that a command is only usable in via DM.
    pub dm_only_text: String,
    /// Text specifying that a command can be used via DM and in guilds.
    pub dm_and_guild_text: String,
    /// Text expressing that a command is available.
    pub available_text: String,
    /// Error-message once a command could not be found.
    /// Output-example (without whitespace between both substitutions: `{command_not_found_text}{command_name}`
    /// `{command_name}` describes user's input as in: `{prefix}help {command_name}`.
    pub command_not_found_text: String,
    /// Explains the user on how to use access a single command's details.
    pub individual_command_tip: String,
    /// Explains reasoning behind strikethrough-commands, see fields requiring `HelpBehaviour` for further information.
    /// If `HelpBehaviour::Strike` is unused, this field will evaluate to `None` during creation
    /// inside of `CreateHelpCommand`.
    ///
    /// **Note**: Text is only used in direct messages.
    pub striked_commands_tip_in_dm: Option<String>,
    /// Explains reasoning behind strikethrough-commands, see fields requiring `HelpBehaviour` for further information.
    /// If `HelpBehaviour::Strike` is unused, this field will evaluate to `None` during creation
    /// inside of `CreateHelpCommand`.
    ///
    /// **Note**: Text is only used in guilds.
    pub striked_commands_tip_in_guild: Option<String>,
    /// Announcing a group's prefix as in: {group_prefix} {prefix}.
    pub group_prefix: String,
    /// If a user lacks required roles, this will treat how these commands will be displayed.
    pub lacking_role: HelpBehaviour,
    /// If a user lacks permissions, this will treat how these commands will be displayed.
    pub lacking_permissions: HelpBehaviour,
    /// If a user is using the help-command in a channel where a command is not available,
    /// this behaviour will be executed.
    pub wrong_channel: HelpBehaviour,
    /// Colour help-embed will use upon encountering an error.
    pub embed_error_colour: Colour,
    /// Colour help-embed will use if no error occured.
    pub embed_success_colour: Colour,
}

pub trait HelpCommand: Send + Sync + 'static {
    fn execute(&self, &mut Context, &Message, &HelpOptions, HashMap<String, Arc<CommandGroup>>, &Args) -> Result<(), Error>;

    fn options(&self) -> Arc<CommandOptions> {
        Arc::clone(&DEFAULT_OPTIONS)
    }
}

impl HelpCommand for Arc<HelpCommand> {
    fn execute(&self, c: &mut Context, m: &Message, ho: &HelpOptions, hm: HashMap<String, Arc<CommandGroup>>, a: &Args) -> Result<(), Error> {
        (**self).execute(c, m, ho, hm, a)
    }
}

impl Default for HelpOptions {
    fn default() -> HelpOptions {
        HelpOptions {
            suggestion_text: "Did you mean {}?".to_string(),
            no_help_available_text: "**Error**: No help available.".to_string(),
            usage_label: "Usage".to_string(),
            usage_sample_label: "Sample usage".to_string(),
            ungrouped_label: "Ungrouped".to_string(),
            grouped_label: "Group".to_string(),
            aliases_label: "Aliases".to_string(),
            description_label: "Description".to_string(),
            guild_only_text: "Only in guilds".to_string(),
            dm_only_text: "Only in DM".to_string(),
            dm_and_guild_text: "In DM and guilds".to_string(),
            available_text: "Available".to_string(),
            command_not_found_text: "**Error**: Command `{}` not found.".to_string(),
            individual_command_tip: "To get help with an individual command, pass its \
                 name as an argument to this command.".to_string(),
            group_prefix: "Prefix".to_string(),
            striked_commands_tip_in_dm: Some(String::new()),
            striked_commands_tip_in_guild: Some(String::new()),
            lacking_role: HelpBehaviour::Strike,
            lacking_permissions: HelpBehaviour::Strike,
            wrong_channel: HelpBehaviour::Strike,
            embed_error_colour: Colour::DARK_RED,
            embed_success_colour: Colour::ROSEWATER,
        }
    }
}

lazy_static! {
    static ref DEFAULT_OPTIONS: Arc<CommandOptions> = Arc::new(CommandOptions::default());
}

/// A framework command.
pub trait Command: Send + Sync + 'static {
    fn execute(&self, &mut Context, &Message, Args) -> Result<(), Error>;

    fn options(&self) -> Arc<CommandOptions> {
        Arc::clone(&DEFAULT_OPTIONS)
    }

    /// Called when the command gets registered.
    fn init(&self) {}

    /// "before" middleware. Is called alongside the global middleware in the framework.
    fn before(&self, &mut Context, &Message) -> bool { true }

    /// "after" middleware. Is called alongside the global middleware in the framework.
    fn after(&self, &mut Context, &Message, &Result<(), Error>) { }
}

impl Command for Arc<Command> {
    fn execute(&self, c: &mut Context, m: &Message, a: Args) -> Result<(), Error> {
        (**self).execute(c, m, a)
    }

    fn options(&self) -> Arc<CommandOptions> {
        (**self).options()
    }

    fn init(&self) {
        (**self).init()
    }

    fn before(&self, c: &mut Context, m: &Message) -> bool {
        (**self).before(c, m)
    }

    fn after(&self, c: &mut Context, m: &Message, res: &Result<(), Error>) {
        (**self).after(c, m, res)
    }
}

impl<F> Command for F where F: Fn(&mut Context, &Message, Args) -> Result<(), Error>
    + Send
    + Sync
    + ?Sized
    + 'static {
    fn execute(&self, c: &mut Context, m: &Message, a: Args) -> Result<(), Error> {
        (*self)(c, m, a)
    }
}

impl Default for CommandOptions {
    fn default() -> CommandOptions {
        CommandOptions {
            aliases: Vec::new(),
            checks: Vec::default(),
            desc: None,
            usage: None,
            example: None,
            min_args: None,
            bucket: None,
            max_args: None,
            required_permissions: Permissions::empty(),
            dm_only: false,
            guild_only: false,
            help_available: true,
            owners_only: false,
            allowed_roles: Vec::new(),
        }
    }
}

pub fn positions(ctx: &mut Context, msg: &Message, conf: &Configuration) -> Option<Vec<usize>> {
    if !conf.prefixes.is_empty() || conf.dynamic_prefix.is_some() {
        // Find out if they were mentioned. If not, determine if the prefix
        // was used. If not, return None.
        let mut positions: Vec<usize> = vec![];

        if let Some(mention_end) = find_mention_end(&msg.content, conf) {
            positions.push(mention_end);
            return Some(positions);
        }

        // Dynamic prefixes, if present and suitable, always have a higher priority.
        if let Some(x) = conf.dynamic_prefix.as_ref().and_then(|f| f(ctx, msg)) {
            if msg.content.starts_with(&x) {
                positions.push(x.chars().count());
            }
        } else {
            for n in &conf.prefixes {
                if msg.content.starts_with(n) {
                    positions.push(n.chars().count());
                }
            }
        }

        #[cfg(feature = "cache")]
        {
            let private = match msg.channel() {
                Some(Channel::Private(_)) => true,
                _ => false,
            };

            // If the above do not fill `positions`, then that means no kind of prefix was present.
            // Check if a no-prefix-execution is applicable.
            if conf.no_dm_prefix && private && positions.is_empty() {
                positions.push(0);
            }
        }

        if positions.is_empty() {
            return None;
        }

        let pos = *unsafe { positions.get_unchecked(0) };

        let with_whitespace = find_end_of_prefix_with_whitespace(&msg.content, pos);

        if conf.allow_whitespace {
            positions.insert(0, with_whitespace.unwrap_or(pos));
        } else if with_whitespace.is_some() {
            return None;
        }

        Some(positions)
    } else if conf.on_mention.is_some() {
        find_mention_end(&msg.content, conf).map(|mention_end| {
            vec![mention_end] // This can simply be returned without trying to find the end whitespaces as trim will remove it later
        })
    } else {
        None
    }
}

fn find_mention_end(content: &str, conf: &Configuration) -> Option<usize> {
    conf.on_mention.as_ref().and_then(|mentions| {
        mentions
            .iter()
            .find(|mention| content.starts_with(&mention[..]))
            .map(|m| m.len())
    })
}

// Finds the end of the first continuous block of whitespace after the prefix
fn find_end_of_prefix_with_whitespace(content: &str, position: usize) -> Option<usize> {
    let content_len = content.len();
    if position >= content_len { return None; }

    let mut i = 0;
    let chars = content.chars().skip(position);
    for char in chars {
        match char {
            // \t \n \r [space]
            '\t' | '\n' | '\r' | ' ' => i += 1,
            _ => return if i == 0 { None } else { Some(position + i) }
        }
    }
    Some(content.len())
}
<commit_msg>Refactor `command::positions` a little<commit_after>use client::Context;
use model::{
    channel::{
        Message,
        Channel,
    },
    Permissions
};
use std::{
    collections::HashMap,
    fmt,
    fmt::{Debug, Formatter},
    sync::Arc
};
use utils::Colour;
use super::{Args, Configuration, HelpBehaviour};

type CheckFunction = Fn(&mut Context, &Message, &mut Args, &CommandOptions) -> bool
                     + Send
                     + Sync
                     + 'static;

pub struct Check(pub(crate) Box<CheckFunction>);

impl Check {
    pub(crate) fn new<F: Send + Sync + 'static>(f: F) -> Self
        where F: Fn(&mut Context, &Message, &mut Args, &CommandOptions) -> bool
    {
        Check(Box::new(f))
    }
}

impl Debug for Check {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_tuple("Check")
            .field(&"<fn>")
            .finish()
    }
}

pub type HelpFunction = fn(&mut Context, &Message, &HelpOptions, HashMap<String, Arc<CommandGroup>>, &Args)
                   -> Result<(), Error>;

pub struct Help(pub HelpFunction, pub Arc<HelpOptions>);

impl Debug for Help {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Help")
            .field("options", &self.1)
            .finish()
    }
}

impl HelpCommand for Help {
    fn execute(&self, c: &mut Context, m: &Message, ho: &HelpOptions,hm: HashMap<String, Arc<CommandGroup>>, a: &Args) -> Result<(), Error> {
        (self.0)(c, m, ho, hm, a)
    }
}

pub type BeforeHook = Fn(&mut Context, &Message, &str) -> bool + Send + Sync + 'static;
pub type AfterHook = Fn(&mut Context, &Message, &str, Result<(), Error>) + Send + Sync + 'static;
pub type UnrecognisedCommandHook = Fn(&mut Context, &Message, &str) + Send + Sync + 'static;
pub(crate) type InternalCommand = Arc<Command>;
pub type PrefixCheck = Fn(&mut Context, &Message) -> Option<String> + Send + Sync + 'static;

pub enum CommandOrAlias {
    Alias(String),
    Command(InternalCommand),
}

impl fmt::Debug for CommandOrAlias {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CommandOrAlias::Alias(ref s) => f.debug_tuple("CommandOrAlias::Alias").field(&s).finish(),
            CommandOrAlias::Command(ref arc) => f.debug_tuple("CommandOrAlias::Command").field(&arc.options()).finish(),
        }
    }
}

/// An error from a command.
#[derive(Clone, Debug)]
pub struct Error(pub String);

// TODO: Have seperate `From<(&)String>` and `From<&str>` impls via specialization
impl<D: fmt::Display> From<D> for Error {
    fn from(d: D) -> Self {
        Error(d.to_string())
    }
}

#[derive(Debug)]
pub struct CommandGroup {
    pub prefixes: Option<Vec<String>>,
    pub commands: HashMap<String, CommandOrAlias>,
    /// Some fields taken from Command
    pub bucket: Option<String>,
    pub required_permissions: Permissions,
    pub allowed_roles: Vec<String>,
    pub help_available: bool,
    pub dm_only: bool,
    pub guild_only: bool,
    pub owners_only: bool,
    pub help: Option<Arc<Help>>,
    /// A set of checks to be called prior to executing the command-group. The checks
    /// will short-circuit on the first check that returns `false`.
    pub checks: Vec<Check>,
    pub default_command: Option<CommandOrAlias>,
}

impl Default for CommandGroup {
    fn default() -> CommandGroup {
        CommandGroup {
            prefixes: None,
            commands: HashMap::new(),
            bucket: None,
            required_permissions: Permissions::empty(),
            dm_only: false,
            guild_only: false,
            help_available: true,
            owners_only: false,
            allowed_roles: Vec::new(),
            help: None,
            checks: Vec::new(),
            default_command: None,
        }
    }
}

#[derive(Debug)]
pub struct CommandOptions {
    /// A set of checks to be called prior to executing the command. The checks
    /// will short-circuit on the first check that returns `false`.
    pub checks: Vec<Check>,
    /// Ratelimit bucket.
    pub bucket: Option<String>,
    /// Command description, used by other commands.
    pub desc: Option<String>,
    /// Example arguments, used by other commands.
    pub example: Option<String>,
    /// Command usage schema, used by other commands.
    pub usage: Option<String>,
    /// Minumum amount of arguments that should be passed.
    pub min_args: Option<i32>,
    /// Maximum amount of arguments that can be passed.
    pub max_args: Option<i32>,
    /// Permissions required to use this command.
    pub required_permissions: Permissions,
    /// Roles allowed to use this command.
    pub allowed_roles: Vec<String>,
    /// Whether command should be displayed in help list or not, used by other commands.
    pub help_available: bool,
    /// Whether command can be used only privately or not.
    pub dm_only: bool,
    /// Whether command can be used only in guilds or not.
    pub guild_only: bool,
    /// Whether command can only be used by owners or not.
    pub owners_only: bool,
    /// Other names that can be used to call this command instead.
    pub aliases: Vec<String>,
}

#[derive(Debug)]
pub struct HelpOptions {
    /// Suggests a command's name.
    pub suggestion_text: String,
    /// If no help is available, this text will be displayed.
    pub no_help_available_text: String,
    /// How to use a command, `{usage_label}: {command_name} {args}`
    pub usage_label: String,
    /// Actual sample label, `{usage_sample_label}: {command_name} {args}`
    pub usage_sample_label: String,
    /// Text labeling ungrouped commands, `{ungrouped_label}: ...`
    pub ungrouped_label: String,
    /// Text labeling the start of the description.
    pub description_label: String,
    /// Text labeling grouped commands, `{grouped_label} {group_name}: ...`
    pub grouped_label: String,
    /// Text labeling a command's alternative names (aliases).
    pub aliases_label: String,
    /// Text specifying that a command is only usable in a guild.
    pub guild_only_text: String,
    /// Text specifying that a command is only usable in via DM.
    pub dm_only_text: String,
    /// Text specifying that a command can be used via DM and in guilds.
    pub dm_and_guild_text: String,
    /// Text expressing that a command is available.
    pub available_text: String,
    /// Error-message once a command could not be found.
    /// Output-example (without whitespace between both substitutions: `{command_not_found_text}{command_name}`
    /// `{command_name}` describes user's input as in: `{prefix}help {command_name}`.
    pub command_not_found_text: String,
    /// Explains the user on how to use access a single command's details.
    pub individual_command_tip: String,
    /// Explains reasoning behind strikethrough-commands, see fields requiring `HelpBehaviour` for further information.
    /// If `HelpBehaviour::Strike` is unused, this field will evaluate to `None` during creation
    /// inside of `CreateHelpCommand`.
    ///
    /// **Note**: Text is only used in direct messages.
    pub striked_commands_tip_in_dm: Option<String>,
    /// Explains reasoning behind strikethrough-commands, see fields requiring `HelpBehaviour` for further information.
    /// If `HelpBehaviour::Strike` is unused, this field will evaluate to `None` during creation
    /// inside of `CreateHelpCommand`.
    ///
    /// **Note**: Text is only used in guilds.
    pub striked_commands_tip_in_guild: Option<String>,
    /// Announcing a group's prefix as in: {group_prefix} {prefix}.
    pub group_prefix: String,
    /// If a user lacks required roles, this will treat how these commands will be displayed.
    pub lacking_role: HelpBehaviour,
    /// If a user lacks permissions, this will treat how these commands will be displayed.
    pub lacking_permissions: HelpBehaviour,
    /// If a user is using the help-command in a channel where a command is not available,
    /// this behaviour will be executed.
    pub wrong_channel: HelpBehaviour,
    /// Colour help-embed will use upon encountering an error.
    pub embed_error_colour: Colour,
    /// Colour help-embed will use if no error occured.
    pub embed_success_colour: Colour,
}

pub trait HelpCommand: Send + Sync + 'static {
    fn execute(&self, &mut Context, &Message, &HelpOptions, HashMap<String, Arc<CommandGroup>>, &Args) -> Result<(), Error>;

    fn options(&self) -> Arc<CommandOptions> {
        Arc::clone(&DEFAULT_OPTIONS)
    }
}

impl HelpCommand for Arc<HelpCommand> {
    fn execute(&self, c: &mut Context, m: &Message, ho: &HelpOptions, hm: HashMap<String, Arc<CommandGroup>>, a: &Args) -> Result<(), Error> {
        (**self).execute(c, m, ho, hm, a)
    }
}

impl Default for HelpOptions {
    fn default() -> HelpOptions {
        HelpOptions {
            suggestion_text: "Did you mean {}?".to_string(),
            no_help_available_text: "**Error**: No help available.".to_string(),
            usage_label: "Usage".to_string(),
            usage_sample_label: "Sample usage".to_string(),
            ungrouped_label: "Ungrouped".to_string(),
            grouped_label: "Group".to_string(),
            aliases_label: "Aliases".to_string(),
            description_label: "Description".to_string(),
            guild_only_text: "Only in guilds".to_string(),
            dm_only_text: "Only in DM".to_string(),
            dm_and_guild_text: "In DM and guilds".to_string(),
            available_text: "Available".to_string(),
            command_not_found_text: "**Error**: Command `{}` not found.".to_string(),
            individual_command_tip: "To get help with an individual command, pass its \
                 name as an argument to this command.".to_string(),
            group_prefix: "Prefix".to_string(),
            striked_commands_tip_in_dm: Some(String::new()),
            striked_commands_tip_in_guild: Some(String::new()),
            lacking_role: HelpBehaviour::Strike,
            lacking_permissions: HelpBehaviour::Strike,
            wrong_channel: HelpBehaviour::Strike,
            embed_error_colour: Colour::DARK_RED,
            embed_success_colour: Colour::ROSEWATER,
        }
    }
}

lazy_static! {
    static ref DEFAULT_OPTIONS: Arc<CommandOptions> = Arc::new(CommandOptions::default());
}

/// A framework command.
pub trait Command: Send + Sync + 'static {
    fn execute(&self, &mut Context, &Message, Args) -> Result<(), Error>;

    fn options(&self) -> Arc<CommandOptions> {
        Arc::clone(&DEFAULT_OPTIONS)
    }

    /// Called when the command gets registered.
    fn init(&self) {}

    /// "before" middleware. Is called alongside the global middleware in the framework.
    fn before(&self, &mut Context, &Message) -> bool { true }

    /// "after" middleware. Is called alongside the global middleware in the framework.
    fn after(&self, &mut Context, &Message, &Result<(), Error>) { }
}

impl Command for Arc<Command> {
    fn execute(&self, c: &mut Context, m: &Message, a: Args) -> Result<(), Error> {
        (**self).execute(c, m, a)
    }

    fn options(&self) -> Arc<CommandOptions> {
        (**self).options()
    }

    fn init(&self) {
        (**self).init()
    }

    fn before(&self, c: &mut Context, m: &Message) -> bool {
        (**self).before(c, m)
    }

    fn after(&self, c: &mut Context, m: &Message, res: &Result<(), Error>) {
        (**self).after(c, m, res)
    }
}

impl<F> Command for F where F: Fn(&mut Context, &Message, Args) -> Result<(), Error>
    + Send
    + Sync
    + ?Sized
    + 'static {
    fn execute(&self, c: &mut Context, m: &Message, a: Args) -> Result<(), Error> {
        (*self)(c, m, a)
    }
}

impl Default for CommandOptions {
    fn default() -> CommandOptions {
        CommandOptions {
            aliases: Vec::new(),
            checks: Vec::default(),
            desc: None,
            usage: None,
            example: None,
            min_args: None,
            bucket: None,
            max_args: None,
            required_permissions: Permissions::empty(),
            dm_only: false,
            guild_only: false,
            help_available: true,
            owners_only: false,
            allowed_roles: Vec::new(),
        }
    }
}

pub fn positions(ctx: &mut Context, msg: &Message, conf: &Configuration) -> Option<Vec<usize>> {
    // Mentions have the highest precedence.
    if let Some(mention_end) = find_mention_end(&msg.content, conf) {
        return Some(vec![mention_end]); // This can simply be returned without trying to find the end whitespaces as trim will remove it later
    }

    if !conf.prefixes.is_empty() || conf.dynamic_prefix.is_some() {
        // Determine if a prefix was used. Otherwise return None.
        let mut positions = Vec::new();

        // Dynamic prefixes, if present and suitable, always have a higher priority.
        if let Some(x) = conf.dynamic_prefix.as_ref().and_then(|f| f(ctx, msg)) {
            if msg.content.starts_with(&x) {
                positions.push(x.chars().count());
            }
        } else {
            for n in &conf.prefixes {
                if msg.content.starts_with(n) {
                    positions.push(n.chars().count());
                }
            }
        }

        #[cfg(feature = "cache")]
        {
            let private = match msg.channel() {
                Some(Channel::Private(_)) => true,
                _ => false,
            };

            // If the above do not fill `positions`, then that means no kind of prefix was present.
            // Check if a no-prefix-execution is applicable.
            if conf.no_dm_prefix && private && positions.is_empty() {
                positions.push(0);
            }
        }

        if positions.is_empty() {
            return None;
        }

        let pos = *unsafe { positions.get_unchecked(0) };

        let with_whitespace = find_end_of_prefix_with_whitespace(&msg.content, pos);

        if conf.allow_whitespace {
            positions.insert(0, with_whitespace.unwrap_or(pos));
        } else if with_whitespace.is_some() {
            return None;
        }

        Some(positions)
    } else {
        None
    }
}

fn find_mention_end(content: &str, conf: &Configuration) -> Option<usize> {
    conf.on_mention.as_ref().and_then(|mentions| {
        mentions
            .iter()
            .find(|mention| content.starts_with(&mention[..]))
            .map(|m| m.len())
    })
}

// Finds the end of the first continuous block of whitespace after the prefix
fn find_end_of_prefix_with_whitespace(content: &str, position: usize) -> Option<usize> {
    let content_len = content.len();
    if position >= content_len { return None; }

    let mut i = 0;
    let chars = content.chars().skip(position);
    for char in chars {
        match char {
            // \t \n \r [space]
            '\t' | '\n' | '\r' | ' ' => i += 1,
            _ => return if i == 0 { None } else { Some(position + i) }
        }
    }
    Some(content.len())
}
<|endoftext|>


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

fn main() {
    if let Some(path) = env::args().nth(1) {
        let mut contents = String::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_string(&mut contents) {
                    Ok(_) => {
                        match brainfuck::read(&contents) {
                            Ok(program) => {
                                let stdio = io::stdin();
                                let input = stdio.lock();
                                let output = io::stdout();
                                brainfuck::eval(program, input, output);
                            }
                            Err(msg) => {
                                println!("Read the file, but could not parse it: {}", msg)
                            }
                        }
                    }
                    Err(_) => println!("Found the file but failed to read it."),
                }
            }
            Err(_) => println!("Failed to open the file for reading."),
        };
    } else {
        println!("Please provide a path to some brainfuck source as the first argument.")
    }
}

mod brainfuck {
    use std::io::{BufRead, Write};

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum Command {
        IncrementPointer,
        DecrementPointer,
        IncrementValue,
        DecrementValue,
        OutputValue,
        InputValue,
        ForwardsTo(usize),
        BackwardsTo(usize),
    }

    pub fn read(source: &str) -> Result<Vec<Command>, &'static str> {
        let mut forward_pointers: Vec<usize> = vec![];
        let mut backward_pointers: Vec<usize> = vec![];
        let mut position: usize = 0;
        let mut program: Vec<Command> = source
            .chars()
            .filter_map(|token| {
                let command = match token {
                    '>' => Some(Command::IncrementPointer),
                    '<' => Some(Command::DecrementPointer),
                    '+' => Some(Command::IncrementValue),
                    '-' => Some(Command::DecrementValue),
                    '.' => Some(Command::OutputValue),
                    ',' => Some(Command::InputValue),
                    '[' => {
                        forward_pointers.push(position);
                        Some(Command::BackwardsTo(position))
                    }
                    ']' => {
                        backward_pointers.push(position);
                        Some(Command::ForwardsTo(position))
                    }
                    _ => None,
                };

                if command.is_some() {
                    position += 1
                }

                command
            })
            .collect();

        if forward_pointers.len() == backward_pointers.len() {
            for (a, b) in forward_pointers.iter().zip(backward_pointers) {
                program.swap(*a, b)
            }

            Ok(program)
        } else {
            Err("Found an unmatched square brace.")
        }
    }

    pub fn eval<R, W>(program: Vec<Command>, mut reader: R, mut writer: W)
        where R: BufRead,
              W: Write
    {
        let mut memory: Vec<i8> = vec![0; 30000];
        let mut mem_pointer: usize = 0;
        let mut prog_pointer: usize = 0;
        let prog_len = program.len();

        while prog_pointer < prog_len {
            match program[prog_pointer] {
                Command::IncrementPointer => {
                    mem_pointer += 1;
                }
                Command::DecrementPointer => {
                    mem_pointer -= 1;
                }
                Command::IncrementValue => {
                    memory[mem_pointer] += 1;
                }
                Command::DecrementValue => {
                    memory[mem_pointer] -= 1;
                }
                Command::OutputValue => {
                    write!(&mut writer, "{}", memory[mem_pointer]).expect("Unable to write");
                }
                Command::InputValue => {
                    let mut input = String::new();
                    reader.read_line(&mut input).expect("Unable to read");
                    memory[mem_pointer] = input.as_bytes()[0] as i8;
                }
                Command::ForwardsTo(next) => {
                    if memory[mem_pointer] == 0 {
                        prog_pointer = next;
                    }
                }
                Command::BackwardsTo(next) => {
                    if memory[mem_pointer] != 0 {
                        prog_pointer = next;
                    }
                }
            };

            prog_pointer += 1;
        }
    }
}

#[cfg(test)]
mod tests {
    use brainfuck::*;
    use brainfuck::Command::*;
    use std::io::Cursor;

    #[test]
    fn read_empty() {
        let source = "";
        let expected: Vec<Command> = vec![];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_simple() {
        let source = "+>-<.,<.-+>,";
        let expected = vec![IncrementValue,
                            IncrementPointer,
                            DecrementValue,
                            DecrementPointer,
                            OutputValue,
                            InputValue,
                            DecrementPointer,
                            OutputValue,
                            DecrementValue,
                            IncrementValue,
                            IncrementPointer,
                            InputValue];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_garbage() {
        let source = ",.+lol,hey.>there<";
        let expected = vec![InputValue,
                            OutputValue,
                            IncrementValue,
                            InputValue,
                            OutputValue,
                            IncrementPointer,
                            DecrementPointer];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_loop() {
        let source = "[->+<]";
        let expected = vec![ForwardsTo(5),
                            DecrementValue,
                            IncrementPointer,
                            IncrementValue,
                            DecrementPointer,
                            BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_bad_loop() {
        let source = "[,.[,.>+-][./.[]]";
        let expected = "Found an unmatched square brace.";

        match read(source) {
            Ok(_) => assert!(false),
            Err(actual) => assert_eq!(expected, actual),
        };
    }

    #[test]
    fn eval_empty() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_cat() {
        let input = Cursor::new(&b"Hello, World!"[..]);
        let mut output = Cursor::new(vec![]);

        match read(",[.,]") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello, World!";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }
}
<commit_msg>Writing bytes as chars using a fn<commit_after>use std::env;
use std::io;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    if let Some(path) = env::args().nth(1) {
        let mut contents = String::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_string(&mut contents) {
                    Ok(_) => {
                        match brainfuck::read(&contents) {
                            Ok(program) => {
                                let stdio = io::stdin();
                                let input = stdio.lock();
                                let output = io::stdout();
                                brainfuck::eval(program, input, output);
                            }
                            Err(msg) => println!("Read the file, but could not parse it: {}", msg),
                        }
                    }
                    Err(_) => println!("Found the file but failed to read it."),
                }
            }
            Err(_) => println!("Failed to open the file for reading."),
        };
    } else {
        println!("Please provide a path to some brainfuck source as the first argument.")
    }
}

mod brainfuck {
    use std::io::{BufRead, Write};

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum Command {
        IncrementPointer,
        DecrementPointer,
        IncrementValue,
        DecrementValue,
        OutputValue,
        InputValue,
        ForwardsTo(usize),
        BackwardsTo(usize),
    }

    pub fn read(source: &str) -> Result<Vec<Command>, &'static str> {
        let mut forward_pointers: Vec<usize> = vec![];
        let mut backward_pointers: Vec<usize> = vec![];
        let mut position: usize = 0;
        let mut program: Vec<Command> = source
            .chars()
            .filter_map(|token| {
                let command = match token {
                    '>' => Some(Command::IncrementPointer),
                    '<' => Some(Command::DecrementPointer),
                    '+' => Some(Command::IncrementValue),
                    '-' => Some(Command::DecrementValue),
                    '.' => Some(Command::OutputValue),
                    ',' => Some(Command::InputValue),
                    '[' => {
                        forward_pointers.push(position);
                        Some(Command::BackwardsTo(position))
                    }
                    ']' => {
                        backward_pointers.push(position);
                        Some(Command::ForwardsTo(position))
                    }
                    _ => None,
                };

                if command.is_some() {
                    position += 1
                }

                command
            })
            .collect();

        if forward_pointers.len() == backward_pointers.len() {
            for (a, b) in forward_pointers.iter().zip(backward_pointers) {
                program.swap(*a, b)
            }

            Ok(program)
        } else {
            Err("Found an unmatched square brace.")
        }
    }

    fn write_byte<W>(mut writer: W, byte: u8)
        where W: Write
    {
        write!(&mut writer, "{}", byte as char).expect("Unable to write");
    }

    pub fn eval<R, W>(program: Vec<Command>, mut reader: R, mut writer: W)
        where R: BufRead,
              W: Write
    {
        let mut memory: Vec<u8> = vec![0; 30000];
        let mut mem_pointer: usize = 0;
        let mut prog_pointer: usize = 0;
        let prog_len = program.len();

        while prog_pointer < prog_len {
            match program[prog_pointer] {
                Command::IncrementPointer => {
                    mem_pointer += 1;
                }
                Command::DecrementPointer => {
                    mem_pointer -= 1;
                }
                Command::IncrementValue => {
                    memory[mem_pointer] += 1;
                }
                Command::DecrementValue => {
                    memory[mem_pointer] -= 1;
                }
                Command::OutputValue => {
                    write_byte(&mut writer, memory[mem_pointer]);
                }
                Command::InputValue => {
                    let mut input = String::new();
                    reader.read_line(&mut input).expect("Unable to read");
                    memory[mem_pointer] = input.as_bytes()[0] as u8;
                }
                Command::ForwardsTo(next) => {
                    if memory[mem_pointer] == 0 {
                        prog_pointer = next;
                    }
                }
                Command::BackwardsTo(next) => {
                    if memory[mem_pointer] != 0 {
                        prog_pointer = next;
                    }
                }
            };

            prog_pointer += 1;
        }
    }
}

#[cfg(test)]
mod tests {
    use brainfuck::*;
    use brainfuck::Command::*;
    use std::io::Cursor;

    #[test]
    fn read_empty() {
        let source = "";
        let expected: Vec<Command> = vec![];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_simple() {
        let source = "+>-<.,<.-+>,";
        let expected = vec![IncrementValue,
                            IncrementPointer,
                            DecrementValue,
                            DecrementPointer,
                            OutputValue,
                            InputValue,
                            DecrementPointer,
                            OutputValue,
                            DecrementValue,
                            IncrementValue,
                            IncrementPointer,
                            InputValue];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_garbage() {
        let source = ",.+lol,hey.>there<";
        let expected = vec![InputValue,
                            OutputValue,
                            IncrementValue,
                            InputValue,
                            OutputValue,
                            IncrementPointer,
                            DecrementPointer];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_loop() {
        let source = "[->+<]";
        let expected = vec![ForwardsTo(5),
                            DecrementValue,
                            IncrementPointer,
                            IncrementValue,
                            DecrementPointer,
                            BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_bad_loop() {
        let source = "[,.[,.>+-][./.[]]";
        let expected = "Found an unmatched square brace.";

        match read(source) {
            Ok(_) => assert!(false),
            Err(actual) => assert_eq!(expected, actual),
        };
    }

    #[test]
    fn eval_empty() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_new_line() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("++++++++++.") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "\n";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_cat() {
        let input = Cursor::new(&b"Hello, World!"[..]);
        let mut output = Cursor::new(vec![]);

        match read(",[.,]") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello, World!";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }
}
<|endoftext|>


<commit_before>use mime::Mime;

header! {
    #[doc="`Content-Type` header, defined in"]
    #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-3.1.1.5)"]
    #[doc=""]
    #[doc="The `Content-Type` header field indicates the media type of the"]
    #[doc="associated representation: either the representation enclosed in the"]
    #[doc="message payload or the selected representation, as determined by the"]
    #[doc="message semantics.  The indicated media type defines both the data"]
    #[doc="format and how that data is intended to be processed by a recipient,"]
    #[doc="within the scope of the received message semantics, after any content"]
    #[doc="codings indicated by Content-Encoding are decoded."]
    #[doc=""]
    #[doc="# ABNF"]
    #[doc="```plain"]
    #[doc="Content-Type = media-type"]
    #[doc="```"]
    #[doc=""]
    #[doc="# Example values"]
    #[doc="* `text/html; charset=ISO-8859-4`"]
    (ContentType, "Content-Type") => [Mime]

    test_content_type {
        test_header!(
            test1,
            // FIXME: Should be b"text/html; charset=ISO-8859-4" but mime crate lowercases
            // the whole value so parsing and formatting the value gives a different result
            vec![b"text/html; charset=iso-8859-4"],
            Some(HeaderField(Mime(
                TopLevel::Text,
                SubLevel::Html,
                vec![(Attr::Charset, Value::Ext("iso-8859-4".to_string()))]))));
    }
}

bench_header!(bench, ContentType, { vec![b"application/json; charset=utf-8".to_vec()] });
<commit_msg>feat(header): add ContentType::json(), plaintext(), html(), jpeg(), and png() constructors<commit_after>use mime::Mime;

header! {
    #[doc="`Content-Type` header, defined in"]
    #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-3.1.1.5)"]
    #[doc=""]
    #[doc="The `Content-Type` header field indicates the media type of the"]
    #[doc="associated representation: either the representation enclosed in the"]
    #[doc="message payload or the selected representation, as determined by the"]
    #[doc="message semantics.  The indicated media type defines both the data"]
    #[doc="format and how that data is intended to be processed by a recipient,"]
    #[doc="within the scope of the received message semantics, after any content"]
    #[doc="codings indicated by Content-Encoding are decoded."]
    #[doc=""]
    #[doc="# ABNF"]
    #[doc="```plain"]
    #[doc="Content-Type = media-type"]
    #[doc="```"]
    #[doc=""]
    #[doc="# Example values"]
    #[doc="* `text/html; charset=ISO-8859-4`"]
    (ContentType, "Content-Type") => [Mime]

    test_content_type {
        test_header!(
            test1,
            // FIXME: Should be b"text/html; charset=ISO-8859-4" but mime crate lowercases
            // the whole value so parsing and formatting the value gives a different result
            vec![b"text/html; charset=iso-8859-4"],
            Some(HeaderField(Mime(
                TopLevel::Text,
                SubLevel::Html,
                vec![(Attr::Charset, Value::Ext("iso-8859-4".to_string()))]))));
    }
}

impl ContentType {
    /// A constructor  to easily create a `Content-Type: application/json; charset=utf-8` header.
    pub fn json() -> ContentType {
        ContentType(mime!(Application/Json; Charset=Utf8))
    }

    /// A constructor  to easily create a `Content-Type: text/plain; charset=utf-8` header.
    pub fn plaintext() -> ContentType {
        ContentType(mime!(Text/Plain; Charset=Utf8))
    }

    /// A constructor  to easily create a `Content-Type: text/html; charset=utf-8` header.
    pub fn html() -> ContentType {
        ContentType(mime!(Text/Html; Charset=Utf8))
    }

    /// A constructor  to easily create a `Content-Type: image/jpeg` header.
    pub fn jpeg() -> ContentType {
        ContentType(mime!(Image/Jpeg))
    }

    /// A constructor  to easily create a `Content-Type: image/png` header.
    pub fn png() -> ContentType {
        ContentType(mime!(Image/Png))
    }
}
bench_header!(bench, ContentType, { vec![b"application/json; charset=utf-8".to_vec()] });
<|endoftext|>


<commit_before>use rustc::hir::def_id::DefId;
use rustc::mir::*;
use rustc::ty::TyCtxt;
use rustc_data_structures::indexed_vec::Idx;
use std::fmt::Debug;
use std::io::{self, Write};

use super::pretty::dump_mir_def_ids;

/// Write a graphviz DOT graph of a list of MIRs.
pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
                                   single: Option<DefId>,
                                   w: &mut W)
                                   -> io::Result<()>
    where W: Write
{
    for def_id in dump_mir_def_ids(tcx, single) {
        let mir = &tcx.optimized_mir(def_id);
        write_mir_fn_graphviz(tcx, def_id, mir, w)?;
    }
    Ok(())
}

// Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
// it does not have to be user friendly.
pub fn graphviz_safe_def_name(def_id: DefId) -> String {
    format!(
        "{}_{}",
        def_id.krate.index(),
        def_id.index.as_array_index(),
    )
}

/// Write a graphviz DOT graph of the MIR.
pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
                                      def_id: DefId,
                                      mir: &Mir<'_>,
                                      w: &mut W) -> io::Result<()>
    where W: Write
{
    writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?;

    // Global graph properties
    writeln!(w, r#"    graph [fontname="monospace"];"#)?;
    writeln!(w, r#"    node [fontname="monospace"];"#)?;
    writeln!(w, r#"    edge [fontname="monospace"];"#)?;

    // Graph label
    write_graph_label(tcx, def_id, mir, w)?;

    // Nodes
    for (block, _) in mir.basic_blocks().iter_enumerated() {
        write_node(block, mir, w)?;
    }

    // Edges
    for (source, _) in mir.basic_blocks().iter_enumerated() {
        write_edges(source, mir, w)?;
    }
    writeln!(w, "}}")
}

/// Write a graphviz HTML-styled label for the given basic block, with
/// all necessary escaping already performed. (This is suitable for
/// emitting directly, as is done in this module, or for use with the
/// LabelText::HtmlStr from libgraphviz.)
///
/// `init` and `fini` are callbacks for emitting additional rows of
/// data (using HTML enclosed with `<tr>` in the emitted text).
pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
                                              mir: &Mir<'_>,
                                              w: &mut W,
                                              num_cols: u32,
                                              init: INIT,
                                              fini: FINI) -> io::Result<()>
    where INIT: Fn(&mut W) -> io::Result<()>,
          FINI: Fn(&mut W) -> io::Result<()>
{
    let data = &mir[block];

    write!(w, r#"
"#)?;

    // Basic block number at the top.
    write!(w, r#"
{blk}
"#,
           attrs=r#"bgcolor="gray" align="center""#,
           colspan=num_cols,
           blk=block.index())?;

    init(w)?;

    // List of statements in the middle.
    if !data.statements.is_empty() {
        write!(w, r#"
"#)?;
        for statement in &data.statements {
            write!(w, "{}
", escape(statement))?;
        }
        write!(w, "
")?;
    }

    // Terminator head at the bottom, not including the list of successor blocks. Those will be
    // displayed as labels on the edges between blocks.
    let mut terminator_head = String::new();
    data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
    write!(w, r#"
{}
"#, dot::escape_html(&terminator_head))?;

    fini(w)?;

    // Close the table
    writeln!(w, "
")
}

/// Write a graphviz DOT node for the given basic block.
fn write_node<W: Write>(block: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Result<()> {
    // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
    write!(w, r#"    {} [shape="none", label=<"#, node(block))?;
    write_node_label(block, mir, w, 1, |_| Ok(()), |_| Ok(()))?;
    // Close the node label and the node itself.
    writeln!(w, ">];")
}

/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
fn write_edges<W: Write>(source: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Result<()> {
    let terminator = mir[source].terminator();
    let labels = terminator.kind.fmt_successor_labels();

    for (&target, label) in terminator.successors().zip(labels) {
        writeln!(w, r#"    {} -> {} [label="{}"];"#, node(source), node(target), label)?;
    }

    Ok(())
}

/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
/// all the variables and temporaries.
fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                               def_id: DefId,
                                               mir: &Mir<'_>,
                                               w: &mut W)
                                               -> io::Result<()> {
    write!(w, "    label=<fn {}(", dot::escape_html(&tcx.def_path_str(def_id)))?;

    // fn argument types.
    for (i, arg) in mir.args_iter().enumerate() {
        if i > 0 {
            write!(w, ", ")?;
        }
        write!(w,
               "{:?}: {}",
               Place::Base(PlaceBase::Local(arg)),
               escape(&mir.local_decls[arg].ty)
        )?;
    }

    write!(w, ") -> {}", escape(&mir.return_ty()))?;
    write!(w, r#"
"#)?;

    for local in mir.vars_and_temps_iter() {
        let decl = &mir.local_decls[local];

        write!(w, "let ")?;
        if decl.mutability == Mutability::Mut {
            write!(w, "mut ")?;
        }

        if let Some(name) = decl.name {
            write!(w, r#"{:?}: {}; // {}
"#,
                   Place::Base(PlaceBase::Local(local)), escape(&decl.ty), name)?;
        } else {
            write!(w, r#"let mut {:?}: {};
"#,
                   Place::Base(PlaceBase::Local(local)), escape(&decl.ty))?;
        }
    }

    writeln!(w, ">;")
}

fn node(block: BasicBlock) -> String {
    format!("bb{}", block.index())
}

fn escape<T: Debug>(t: &T) -> String {
    dot::escape_html(&format!("{:?}", t))
}
<commit_msg>Rollup merge of #60741 - shiatsumat:patch-let-mut-write-graph-label, r=varkor<commit_after>use rustc::hir::def_id::DefId;
use rustc::mir::*;
use rustc::ty::TyCtxt;
use rustc_data_structures::indexed_vec::Idx;
use std::fmt::Debug;
use std::io::{self, Write};

use super::pretty::dump_mir_def_ids;

/// Write a graphviz DOT graph of a list of MIRs.
pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
                                   single: Option<DefId>,
                                   w: &mut W)
                                   -> io::Result<()>
    where W: Write
{
    for def_id in dump_mir_def_ids(tcx, single) {
        let mir = &tcx.optimized_mir(def_id);
        write_mir_fn_graphviz(tcx, def_id, mir, w)?;
    }
    Ok(())
}

// Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
// it does not have to be user friendly.
pub fn graphviz_safe_def_name(def_id: DefId) -> String {
    format!(
        "{}_{}",
        def_id.krate.index(),
        def_id.index.as_array_index(),
    )
}

/// Write a graphviz DOT graph of the MIR.
pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
                                      def_id: DefId,
                                      mir: &Mir<'_>,
                                      w: &mut W) -> io::Result<()>
    where W: Write
{
    writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?;

    // Global graph properties
    writeln!(w, r#"    graph [fontname="monospace"];"#)?;
    writeln!(w, r#"    node [fontname="monospace"];"#)?;
    writeln!(w, r#"    edge [fontname="monospace"];"#)?;

    // Graph label
    write_graph_label(tcx, def_id, mir, w)?;

    // Nodes
    for (block, _) in mir.basic_blocks().iter_enumerated() {
        write_node(block, mir, w)?;
    }

    // Edges
    for (source, _) in mir.basic_blocks().iter_enumerated() {
        write_edges(source, mir, w)?;
    }
    writeln!(w, "}}")
}

/// Write a graphviz HTML-styled label for the given basic block, with
/// all necessary escaping already performed. (This is suitable for
/// emitting directly, as is done in this module, or for use with the
/// LabelText::HtmlStr from libgraphviz.)
///
/// `init` and `fini` are callbacks for emitting additional rows of
/// data (using HTML enclosed with `<tr>` in the emitted text).
pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
                                              mir: &Mir<'_>,
                                              w: &mut W,
                                              num_cols: u32,
                                              init: INIT,
                                              fini: FINI) -> io::Result<()>
    where INIT: Fn(&mut W) -> io::Result<()>,
          FINI: Fn(&mut W) -> io::Result<()>
{
    let data = &mir[block];

    write!(w, r#"
"#)?;

    // Basic block number at the top.
    write!(w, r#"
{blk}
"#,
           attrs=r#"bgcolor="gray" align="center""#,
           colspan=num_cols,
           blk=block.index())?;

    init(w)?;

    // List of statements in the middle.
    if !data.statements.is_empty() {
        write!(w, r#"
"#)?;
        for statement in &data.statements {
            write!(w, "{}
", escape(statement))?;
        }
        write!(w, "
")?;
    }

    // Terminator head at the bottom, not including the list of successor blocks. Those will be
    // displayed as labels on the edges between blocks.
    let mut terminator_head = String::new();
    data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
    write!(w, r#"
{}
"#, dot::escape_html(&terminator_head))?;

    fini(w)?;

    // Close the table
    writeln!(w, "
")
}

/// Write a graphviz DOT node for the given basic block.
fn write_node<W: Write>(block: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Result<()> {
    // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
    write!(w, r#"    {} [shape="none", label=<"#, node(block))?;
    write_node_label(block, mir, w, 1, |_| Ok(()), |_| Ok(()))?;
    // Close the node label and the node itself.
    writeln!(w, ">];")
}

/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
fn write_edges<W: Write>(source: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Result<()> {
    let terminator = mir[source].terminator();
    let labels = terminator.kind.fmt_successor_labels();

    for (&target, label) in terminator.successors().zip(labels) {
        writeln!(w, r#"    {} -> {} [label="{}"];"#, node(source), node(target), label)?;
    }

    Ok(())
}

/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
/// all the variables and temporaries.
fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                               def_id: DefId,
                                               mir: &Mir<'_>,
                                               w: &mut W)
                                               -> io::Result<()> {
    write!(w, "    label=<fn {}(", dot::escape_html(&tcx.def_path_str(def_id)))?;

    // fn argument types.
    for (i, arg) in mir.args_iter().enumerate() {
        if i > 0 {
            write!(w, ", ")?;
        }
        write!(w,
               "{:?}: {}",
               Place::Base(PlaceBase::Local(arg)),
               escape(&mir.local_decls[arg].ty)
        )?;
    }

    write!(w, ") -> {}", escape(&mir.return_ty()))?;
    write!(w, r#"
"#)?;

    for local in mir.vars_and_temps_iter() {
        let decl = &mir.local_decls[local];

        write!(w, "let ")?;
        if decl.mutability == Mutability::Mut {
            write!(w, "mut ")?;
        }

        if let Some(name) = decl.name {
            write!(w, r#"{:?}: {}; // {}
"#,
                   Place::Base(PlaceBase::Local(local)), escape(&decl.ty), name)?;
        } else {
            write!(w, r#"{:?}: {};
"#,
                   Place::Base(PlaceBase::Local(local)), escape(&decl.ty))?;
        }
    }

    writeln!(w, ">;")
}

fn node(block: BasicBlock) -> String {
    format!("bb{}", block.index())
}

fn escape<T: Debug>(t: &T) -> String {
    dot::escape_html(&format!("{:?}", t))
}
<|endoftext|>


<commit_before>//! Example of basic search-and-replace functionality implemented on top
//! of a Ropey rope.
//!
//! Usage:
//!     search_and_replace <search_pattern> <replacement_text> <input_filepath>
//!
//! The file contents with the search-and-replace performed on it is sent to
//! stdout.

extern crate ropey;

use std::fs::File;
use std::io;

use ropey::{iter::Chars, Rope, RopeSlice};

fn main() {
    // Get arguments from commandline
    let (search_pattern, replacement_text, filepath) = if std::env::args().count() > 3 {
        (
            std::env::args().nth(1).unwrap(),
            std::env::args().nth(2).unwrap(),
            std::env::args().nth(3).unwrap(),
        )
    } else {
        println!(
            "Usage:\n    search_and_replace <search_pattern> <replacement_text> <input_filepath>"
        );
        return;
    };

    // Load file contents into a rope.
    let mut text = Rope::from_reader(io::BufReader::new(File::open(&filepath).unwrap())).expect("Cannot read file: either it doesn't exist, file permissions don't allow reading, or is not utf8 text.");

    // Do the search-and-replace.
    search_and_replace(&mut text, &search_pattern, &replacement_text);

    // Print the new text to stdout.
    println!("{}", text);
}

/// Searches the rope for `search_pattern` and replaces all matches with
/// `replacement_text`.
///
/// There are several ways this could be done:
///
/// 1. Clone the rope and then do the search on the original while replacing
///    on the clone.  This isn't as awful as it sounds because the clone
///    operation is constant-time and the two ropes will share most of their
///    storage in typical cases.  However, this probably isn't the best
///    general solution because it will use a lot of additional space if a
///    large percentage of the text is bring replaced.
///
/// 2. A two-stage approach: first find and collect all the matches, then
///    do the replacements on the original rope.  This is a good solution
///    when a relatively small number of matches are expected.  However, if
///    there are a large number of matches then the space to store the
///    matches themselves can become large.
///
/// 3. A piece-meal approach: search for the first match, replace it, then
///    restart the match from the end of the replacement, repeat.  This is
///    a good solution for memory-constrained situations.  However,
///    computationally it is likely the most expensive when there are a large
///    number of matches and there are costs associated with repeatedly
///    restarting the search.
///
/// 4. Combine approaches #2 and #3: collect a fixed number of matches and
///    replace them, then collect another batch matches and replace them, and
///    so on.  This is probably the best general solution, because it
///    combines the best of both worlds: it allows you to collect the matches
///    in a bounded amount of space, and any costs associated with restarting
///    the search are amortized across multiple matches.
///
/// In this implementation we take approach #4 because it seems the
/// all-around best.
fn search_and_replace(rope: &mut Rope, search_pattern: &str, replacement_text: &str) {
    const BATCH_SIZE: usize = 256;

    let replacement_text_len = replacement_text.chars().count();

    let mut head = 0; // Char index of the search/replace head.
    let mut matches = Vec::with_capacity(BATCH_SIZE);
    loop {
        // Collect the next batch of matches.  Note that we don't use
        // `Iterator::collect()` to collect the batch because we want to
        // re-use the same Vec to avoid unnecessary allocations.
        matches.clear();
        for m in SearchIter::from_rope_slice(&rope.slice(head..), &search_pattern).take(BATCH_SIZE)
        {
            matches.push(m);
        }

        // If there are no matches, we're done!
        if matches.len() == 0 {
            break;
        }

        // Replace the collected matches.
        let mut index_diff: isize = 0;
        for &(start, end) in matches.iter() {
            // Get the properly offset indices.
            let start_d = (head as isize + start as isize + index_diff) as usize;
            let end_d = (head as isize + end as isize + index_diff) as usize;

            // Do the replacement.
            rope.remove(start_d..end_d);
            rope.insert(start_d, &replacement_text);

            // Update the index offset.
            let match_len = (end - start) as isize;
            index_diff = index_diff - match_len + replacement_text_len as isize;
        }

        // Update head for next iteration.
        head = (head as isize + index_diff + matches.last().unwrap().1 as isize) as usize;
    }
}

/// An iterator over simple textual matches in a RopeSlice.
///
/// This implementation is somewhat naive, and could be sped up by using a
/// more sophisticated text searching algorithm such as Boyer-Moore or
/// Knuth-Morris-Pratt.
///
/// The important thing, however, is the interface.  For example, a regex
/// implementation providing an equivalent interface could easily be dropped
/// in, and the search-and-replace function above would then work with it
/// quite happily.
struct SearchIter<'a> {
    char_iter: Chars<'a>,
    search_pattern: &'a str,
    search_pattern_char_len: usize,
    cur_index: usize, // The current char index of the search head.
    possible_matches: Vec<std::str::Chars<'a>>, // Tracks where we are in the search pattern for the current possible matches.
}

impl<'a> SearchIter<'a> {
    fn from_rope_slice<'b>(slice: &'b RopeSlice, search_pattern: &'b str) -> SearchIter<'b> {
        assert!(
            search_pattern.len() > 0,
            "Can't search using an empty search pattern."
        );
        SearchIter {
            char_iter: slice.chars(),
            search_pattern: search_pattern,
            search_pattern_char_len: search_pattern.chars().count(),
            cur_index: 0,
            possible_matches: Vec::new(),
        }
    }
}

impl<'a> Iterator for SearchIter<'a> {
    type Item = (usize, usize);

    // Return the start/end char indices of the next match.
    fn next(&mut self) -> Option<(usize, usize)> {
        while let Some(next_char) = self.char_iter.next() {
            self.cur_index += 1;

            // Push new potential match, for a possible match starting at the
            // current char.
            self.possible_matches.push(self.search_pattern.chars());

            // Check the rope's char against the next character in each of
            // the potential matches, removing the potential matches that
            // don't match.  We're using indexing instead of iteration here
            // so that we can remove the possible matches as we go.
            let mut i = 0;
            while i < self.possible_matches.len() {
                let pattern_char = self.possible_matches[i].next().unwrap();
                if next_char == pattern_char {
                    if self.possible_matches[i].clone().next() == None {
                        // We have a match!  Reset possible matches and
                        // return the successful match's char indices.
                        let char_match_range = (
                            self.cur_index - self.search_pattern_char_len,
                            self.cur_index,
                        );
                        self.possible_matches.clear();
                        return Some(char_match_range);
                    } else {
                        // Match isn't complete yet, move on to the next.
                        i += 1;
                    }
                } else {
                    // Doesn't match, remove it.
                    self.possible_matches.swap_remove(i);
                }
            }
        }

        return None;
    }
}
<commit_msg>Typo fixes and general comment improvements in search-and-replace example.<commit_after>//! Example of basic search-and-replace functionality implemented on top
//! of Ropey.
//!
//! Usage:
//!     search_and_replace <search_pattern> <replacement_text> <input_filepath>
//!
//! The file contents with the search-and-replace performed on it is sent to
//! stdout.

extern crate ropey;

use std::fs::File;
use std::io;

use ropey::{iter::Chars, Rope, RopeSlice};

fn main() {
    // Get arguments from commandline
    let (search_pattern, replacement_text, filepath) = if std::env::args().count() > 3 {
        (
            std::env::args().nth(1).unwrap(),
            std::env::args().nth(2).unwrap(),
            std::env::args().nth(3).unwrap(),
        )
    } else {
        println!(
            "Usage:\n    search_and_replace <search_pattern> <replacement_text> <input_filepath>"
        );
        return;
    };

    // Load file contents into a rope.
    let mut text = Rope::from_reader(io::BufReader::new(File::open(&filepath).unwrap())).expect("Cannot read file: either it doesn't exist, file permissions don't allow reading, or is not utf8 text.");

    // Do the search-and-replace.
    search_and_replace(&mut text, &search_pattern, &replacement_text);

    // Print the new text to stdout.
    println!("{}", text);
}

/// Searches the rope for `search_pattern` and replaces all matches with
/// `replacement_text`.
///
/// There are several ways this could be done:
///
/// 1. Clone the rope and then do the search on the original while replacing
///    on the clone.  This isn't as awful as it sounds because the clone
///    operation is constant-time and the two ropes will share most of their
///    storage in typical cases.  However, this probably isn't the best
///    general solution because it will use a lot of additional space if a
///    large percentage of the text is being replaced.
///
/// 2. A two-stage approach: first find and collect all the matches, then
///    do the replacements on the original rope.  This is a good solution
///    when a relatively small number of matches are expected.  However, if
///    there are a large number of matches then the space to store the
///    matches themselves can become large.
///
/// 3. A piece-meal approach: search for the first match, replace it, then
///    restart the search from there, repeat.  This is a good solution for
///    memory-constrained situations.  However, computationally it is likely
///    the most expensive when there are a large number of matches and there
///    are costs associated with repeatedly restarting the search.
///
/// 4. Combine approaches #2 and #3: collect a fixed number of matches and
///    replace them, then collect another batch of matches and replace them,
///    and so on.  This is probably the best general solution, because it
///    combines the best of both #2 and #3: it allows you to collect the
///    matches in a bounded amount of space, and any costs associated with
///    restarting the search are amortized over multiple matches.
///
/// In this implementation we take approach #4 because it seems the
/// all-around best.
fn search_and_replace(rope: &mut Rope, search_pattern: &str, replacement_text: &str) {
    const BATCH_SIZE: usize = 256;
    let replacement_text_len = replacement_text.chars().count();

    let mut head = 0; // Keep track of where we are between searches
    let mut matches = Vec::with_capacity(BATCH_SIZE);
    loop {
        // Collect the next batch of matches.  Note that we don't use
        // `Iterator::collect()` to collect the batch because we want to
        // re-use the same Vec to avoid unnecessary allocations.
        matches.clear();
        for m in SearchIter::from_rope_slice(&rope.slice(head..), &search_pattern).take(BATCH_SIZE)
        {
            matches.push(m);
        }

        // If there are no matches, we're done!
        if matches.len() == 0 {
            break;
        }

        // Replace the collected matches.
        let mut index_diff: isize = 0;
        for &(start, end) in matches.iter() {
            // Get the properly offset indices.
            let start_d = (head as isize + start as isize + index_diff) as usize;
            let end_d = (head as isize + end as isize + index_diff) as usize;

            // Do the replacement.
            rope.remove(start_d..end_d);
            rope.insert(start_d, &replacement_text);

            // Update the index offset.
            let match_len = (end - start) as isize;
            index_diff = index_diff - match_len + replacement_text_len as isize;
        }

        // Update head for next iteration.
        head = (head as isize + index_diff + matches.last().unwrap().1 as isize) as usize;
    }
}

/// An iterator over simple textual matches in a RopeSlice.
///
/// This implementation is somewhat naive, and could be sped up by using a
/// more sophisticated text searching algorithm such as Boyer-Moore or
/// Knuth-Morris-Pratt.
///
/// The important thing, however, is the interface.  For example, a regex
/// implementation providing an equivalent interface could easily be dropped
/// in, and the search-and-replace function above would work with it quite
/// happily.
struct SearchIter<'a> {
    char_iter: Chars<'a>,
    search_pattern: &'a str,
    search_pattern_char_len: usize,
    cur_index: usize, // The current char index of the search head.
    possible_matches: Vec<std::str::Chars<'a>>, // Tracks where we are in the search pattern for the current possible matches.
}

impl<'a> SearchIter<'a> {
    fn from_rope_slice<'b>(slice: &'b RopeSlice, search_pattern: &'b str) -> SearchIter<'b> {
        assert!(
            search_pattern.len() > 0,
            "Can't search using an empty search pattern."
        );
        SearchIter {
            char_iter: slice.chars(),
            search_pattern: search_pattern,
            search_pattern_char_len: search_pattern.chars().count(),
            cur_index: 0,
            possible_matches: Vec::new(),
        }
    }
}

impl<'a> Iterator for SearchIter<'a> {
    type Item = (usize, usize);

    // Return the start/end char indices of the next match.
    fn next(&mut self) -> Option<(usize, usize)> {
        while let Some(next_char) = self.char_iter.next() {
            self.cur_index += 1;

            // Push new potential match, for a possible match starting at the
            // current char.
            self.possible_matches.push(self.search_pattern.chars());

            // Check the rope's char against the next character in each of
            // the potential matches, removing the potential matches that
            // don't match.  We're using indexing instead of iteration here
            // so that we can remove the possible matches as we go.
            let mut i = 0;
            while i < self.possible_matches.len() {
                let pattern_char = self.possible_matches[i].next().unwrap();
                if next_char == pattern_char {
                    if self.possible_matches[i].clone().next() == None {
                        // We have a match!  Reset possible matches and
                        // return the successful match's char indices.
                        let char_match_range = (
                            self.cur_index - self.search_pattern_char_len,
                            self.cur_index,
                        );
                        self.possible_matches.clear();
                        return Some(char_match_range);
                    } else {
                        // Match isn't complete yet, move on to the next.
                        i += 1;
                    }
                } else {
                    // Doesn't match, remove it.
                    self.possible_matches.swap_remove(i);
                }
            }
        }

        return None;
    }
}
<|endoftext|>


<commit_before>#![feature(env, old_path)]

extern crate civet;
extern crate conduit;
extern crate "conduit-static" as conduit_static;

use std::env;
use std::sync::mpsc::channel;

use civet::{Config, Server};
use conduit_static::Static;

fn main() {
    let handler = Static::new(&env::current_dir().unwrap());
    let _a = Server::start(Config { port: 8888, threads: 50 }, handler);
    let (_tx, rx) = channel::<()>();
    rx.recv().unwrap();
}
<commit_msg>Update to rust master<commit_after>extern crate civet;
extern crate conduit;
extern crate "conduit-static" as conduit_static;

use std::env;
use std::sync::mpsc::channel;

use civet::{Config, Server};
use conduit_static::Static;

fn main() {
    let handler = Static::new(&env::current_dir().unwrap());
    let _a = Server::start(Config { port: 8888, threads: 50 }, handler);
    let (_tx, rx) = channel::<()>();
    rx.recv().unwrap();
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

macro_rules! assert_equal_len {
    ($a:ident, $b: ident, $func:ident, $op:tt) => {
        assert!($a.len() == $b.len(),
                "{}: dimension mismatch: {} {} {}",
                stringify!($func),
                ($a.len(),),
                stringify!($op),
                ($b.len(),));
    }
}

macro_rules! op {
    ($func:ident, $bound:ident, $op:tt, $method:ident) => {
        fn $func<T: $bound<T, T>>(xs: &mut Vec<T>, ys: &Vec<T>) {
            assert_equal_len!(xs, ys, $func, $op);

            for (x, y) in xs.mut_iter().zip(ys.iter()) {
                *x = x.$method(y);
            }
        }
    }
}

// implement add_assign, mul_assign, and sub_assign functions
op!(add_assign, Add, +=, add)
op!(mul_assign, Mul, *=, mul)
op!(sub_assign, Sub, -=, sub)

fn main() {
    let mut xs = Vec::from_elem(5, 0f64);
    let ys = Vec::from_elem(6, 1f64);

    // this operation will fail at runtime
    add_assign(&mut xs, &ys);
}

mod test {
    macro_rules! test {
        ($func: ident, $x:expr, $y:expr, $z:expr) => {
            #[test]
            fn $func() {
                for size in range(0u, 10) {
                    let mut x = Vec::from_elem(size, $x);
                    let y = Vec::from_elem(size, $y);
                    let z = Vec::from_elem(size, $z);

                    super::$func(&mut x, &y);

                    assert_eq!(x, z);
                }
            }
        }
    }

    // test add_assign, mul_assign and sub_assign
    test!(add_assign, 1u, 2u, 3u)
    test!(mul_assign, 2u, 3u, 6u)
    test!(sub_assign, 3u, 2u, 1u)
}
<commit_msg>Fixed mut_iter() to iter_mut()<commit_after>#![feature(macro_rules)]

macro_rules! assert_equal_len {
    ($a:ident, $b: ident, $func:ident, $op:tt) => {
        assert!($a.len() == $b.len(),
                "{}: dimension mismatch: {} {} {}",
                stringify!($func),
                ($a.len(),),
                stringify!($op),
                ($b.len(),));
    }
}

macro_rules! op {
    ($func:ident, $bound:ident, $op:tt, $method:ident) => {
        fn $func<T: $bound<T, T>>(xs: &mut Vec<T>, ys: &Vec<T>) {
            assert_equal_len!(xs, ys, $func, $op);

            for (x, y) in xs.iter_mut().zip(ys.iter()) {
                *x = x.$method(y);
            }
        }
    }
}

// implement add_assign, mul_assign, and sub_assign functions
op!(add_assign, Add, +=, add)
op!(mul_assign, Mul, *=, mul)
op!(sub_assign, Sub, -=, sub)

fn main() {
    let mut xs = Vec::from_elem(5, 0f64);
    let ys = Vec::from_elem(6, 1f64);

    // this operation will fail at runtime
    add_assign(&mut xs, &ys);
}

mod test {
    macro_rules! test {
        ($func: ident, $x:expr, $y:expr, $z:expr) => {
            #[test]
            fn $func() {
                for size in range(0u, 10) {
                    let mut x = Vec::from_elem(size, $x);
                    let y = Vec::from_elem(size, $y);
                    let z = Vec::from_elem(size, $z);

                    super::$func(&mut x, &y);

                    assert_eq!(x, z);
                }
            }
        }
    }

    // test add_assign, mul_assign and sub_assign
    test!(add_assign, 1u, 2u, 3u)
    test!(mul_assign, 2u, 3u, 6u)
    test!(sub_assign, 3u, 2u, 1u)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! Basic serial port driver.
//!
//! As usual, inspired by http://wiki.osdev.org/Serial_Ports

use core::fmt;
use spin::Mutex;
use cpuio;
use self::Register::*;

/// Each COM port has 8 I/O registers associated with it, some of which are
/// dual use.
#[allow(dead_code)]
#[repr(C, u8)]
enum Register {
    /// Either a data register or the low byte of our baud divisor, depending
    /// on the high bit of LineControl.
    DataOrBaudLsb = 0,
    /// Either a interrupt flags register or the high byte of our baud
    /// divisor.
    InterruptEnableOrBaudMsb = 1,
    InterruptIdentAndFifo = 2,
    /// When the high bit of LineControl is set, the first two registers
    /// switch over to their "baud mode".
    LineControl = 3,
    ModemControl = 4,
    LineStatus = 5,
    ModemStatus = 6,
    Scratch = 7
}

/// A COM serial port.
pub struct ComPort {
    /// COM ports are identified by the base address of their associated
    /// I/O registers.
    base_addr: u16,
    /// Has this port been initialized yet?
    initialized: bool,
}

impl ComPort {
    /// Create a new COM port with the specified base address.  Note that
    /// this does not actually finish initializing the serial port, because
    /// this is `const` function that may be computed at compile time.
    /// Initialization is finished by `lazy_initialize`, which should be
    /// called by all safe, public functions in this API.
    const unsafe fn new(base_addr: u16) -> ComPort {
        ComPort { base_addr: base_addr, initialized: false }
    }

    /// Finish the runtime-only setup needed by this port.
    unsafe fn lazy_initialize(&mut self) {
        if self.initialized == true { return; }
        self.initialized = true;

        // Disable interrupts.
        self.port(InterruptEnableOrBaudMsb).write(0x00);

        // Set baud and 8N1 mode.
        self.set_baud_divisor(2); // 115,200 / 2
        self.port(LineControl).write(0x03);

        // Enable FIFOs with 14-byte threshhold.
        self.port(InterruptIdentAndFifo).write(0xC7);

        // Configure modem: RTS/DSR and IRQs on.  But if we actually want
        // to get IRQs, I think we also need to set up
        // InterruptEnableOrBaudMsb.
        self.port(ModemControl).write(0x0B);
    }

    /// Get an cpuio::Port object for one of our associated ports.  This is
    /// marked as `unsafe` because the returned port can potentially be
    /// used to mess with processor interrupts and otherwise violate
    /// fundamental abstractions about how Rust code works.
    unsafe fn port(&mut self, register: Register) -> cpuio::Port<u8> {
        cpuio::Port::new(self.base_addr + (register as u8 as u16))
    }

    /// Set the baud rate as a divisor of 115,200.
    fn set_baud_divisor(&mut self, divisor: u16) {
        unsafe {
            self.lazy_initialize();

            // Switch ports DataOrBaudLsb and InterruptEnableOrBaudMsb to
            // their baud mode by setting the high bit of LineControl.
            let saved_line_control = self.port(LineControl).read();
            self.port(LineControl).write(0x80 | saved_line_control);

            // Set baud divisor.
            self.port(DataOrBaudLsb).write(divisor as u8);
            self.port(InterruptEnableOrBaudMsb).write((divisor >> 8) as u8);

            // Restore previous port modes.
            self.port(LineControl).write(saved_line_control);
        }
    }

    /// Can we safely transmit data on this serial port right now, or will
    /// we block?
    fn can_transmit(&mut self) -> bool {
        unsafe {
            self.lazy_initialize();
            // TODO: Check to see what the meaning of this bit is. OSDev
            // calls it "is_transmit_empty", so maybe we actually want a
            // different bit.
            (self.port(LineStatus).read() & 0x20) != 0
        }
    }
}

impl fmt::Write for ComPort {
    /// Output a string to our COM port.  This allows using nice,
    /// high-level tools like Rust's `write!` macro.
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {
            self.lazy_initialize();

            // Output each byte of our string.
            for &b in s.as_bytes() {
                // Loop until the port's available.
                while !self.can_transmit() {}

                // Write our byte.
                self.port(DataOrBaudLsb).write(b);
            }
        }
        Ok(())
    }
}

/// Our primary serial port.
pub static COM1: Mutex<ComPort> = Mutex::new(unsafe {
    ComPort::new(0x03F8)
});
<commit_msg>remove UART initialization<commit_after>// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

use core::fmt;
use spin::Mutex;
use cpuio;

/// A COM serial port.
pub struct ComPort {
    /// COM ports are identified by the base address of their associated
    /// I/O registers.
    base_addr: u16
}

impl ComPort {
    /// Create a new COM port with the specified base address.
    const fn new(base_addr: u16) -> ComPort {
        ComPort { base_addr: base_addr }
    }
}

impl fmt::Write for ComPort {
    /// Output a string to our COM port.  This allows using nice,
    /// high-level tools like Rust's `write!` macro.
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {
			let mut uart_port : cpuio::Port<u8> = cpuio::Port::new(self.base_addr);

            // Output each byte of our string.
            for &b in s.as_bytes() {
                // Write our byte.
                uart_port.write(b);
            }
        }
        Ok(())
    }
}

/// Our primary serial port.
pub static COM1: Mutex<ComPort> = Mutex::new(ComPort::new(0x3F8));
<|endoftext|>


<commit_before>use std::error::Error;

use ruru::{Class, NilClass, RString, Object, VM};

use server::Server as RustServer;

class!(Server);

methods!(
    Server,
    itself,

    fn initialize(addr: RString) -> Server {
        if let Err(ref error) = addr {
            VM::raise(error.to_exception(), error.description());
        }

        itself.instance_variable_set("@addr", addr.unwrap());

        itself
    }

    fn listen() -> NilClass {
        let handler = VM::block_proc();

        // We can use unsafe here, because the type of addr is checked in the constructor
        let addr = unsafe { itself.instance_variable_get("@addr").to::<RString>().to_string() };

        RustServer::new(addr).listen(handler);

        NilClass::new()
    }
);

impl Server {
    pub fn define_ruby_class() {
        Class::new("RubyHttpServer", None).define(|itself| {
            itself.def("initialize", initialize);
            itself.def("listen", listen);
        });
    }
}
<commit_msg>Rename RubyHttpServer to Trusted::Server<commit_after>use std::error::Error;

use ruru::{Class, NilClass, RString, Object, VM};

use server::Server as RustServer;

class!(Server);

methods!(
    Server,
    itself,

    fn initialize(addr: RString) -> Server {
        if let Err(ref error) = addr {
            VM::raise(error.to_exception(), error.description());
        }

        itself.instance_variable_set("@addr", addr.unwrap());

        itself
    }

    fn listen() -> NilClass {
        let handler = VM::block_proc();

        // We can use unsafe here, because the type of addr is checked in the constructor
        let addr = unsafe { itself.instance_variable_get("@addr").to::<RString>().to_string() };

        RustServer::new(addr).listen(handler);

        NilClass::new()
    }
);

impl Server {
    pub fn define_ruby_class() {
        Class::from_existing("Trusted").define(|itself| {
            itself.define_nested_class("Server", None).define(|itself| {
                itself.def("initialize", initialize);
                itself.def("listen", listen);
            });
        });
    }
}
<|endoftext|>