<commit_before>//! String processing utilities

/// Split a long line into multiple lines that fit a given width.
///
/// Will treat newlines in the input as regular whitespace, you probably want to split your input
/// at newlines before using `split_line` on the individual lines.
pub fn split_line<'a, F>(text: &'a str, char_width: F, max_width: f32) -> LineSplit<'a, F>
    where F: Fn(char) -> f32
{
    LineSplit {
        remain: text,
        char_width: char_width,
        max_width: max_width,
        finished: false,
    }
}

pub struct LineSplit<'a, F> {
    remain: &'a str,
    char_width: F,
    max_width: f32,
    finished: bool,
}

impl<'a, F> Iterator for LineSplit<'a, F>
    where F: Fn(char) -> f32
{
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.finished {
            return None;
        }

        #[derive(Copy, Clone)]
        struct State {
            total_width: f32,
            clip_pos: usize,
            last_word_break: Option<(usize, f32)>,
            prev: char,
        }

        impl State {
            fn new() -> State {
                State {
                    total_width: 0.0,
                    clip_pos: 0,
                    last_word_break: None,
                    prev: 'A',
                }
            }

            fn update<F: Fn(char) -> f32>(&mut self, char_width: &F, c: char) {
                if c.is_whitespace() && !self.prev.is_whitespace() {
                    self.last_word_break = Some((self.clip_pos, self.total_width));
                }
                self.clip_pos += c.len_utf8();
                self.total_width += char_width(c);
                self.prev = c;
            }

            fn best_pos(&self) -> (usize, f32) {
                // Return the cut in the current word if there is no last_word_break set yet.
                if let Some(x) = self.last_word_break {
                    x
                } else {
                    (self.clip_pos, self.total_width)
                }
            }
        }

        let end_pos = {
            self.remain
                .chars()
                .chain(Some(' ')) // Makes the ending of the last word in line show up.
                .scan(State::new(), |s, c| {
                    s.update(&self.char_width, c);
                    Some(*s)
                })
                // Guarantee at least one item is taken if there are any items by
                // recognizing the first item from len_utf8 and always taking it.
                .take_while(|s| s.clip_pos == s.prev.len_utf8() || s.best_pos().1 <= self.max_width)
                .map(|s| s.best_pos().0)
                .last()
                .unwrap_or(0)
        };

        let ret = &self.remain[..end_pos];

        self.remain = &self.remain[end_pos..];
        // Strip whitespace between this line and the next.
        let start_pos = self.remain
                            .chars()
                            .take_while(|&c| c.is_whitespace())
                            .map(|c| c.len_utf8())
                            .sum();
        self.remain = &self.remain[start_pos..];
        if self.remain.is_empty() {
            self.finished = true;
        }

        Some(ret)
    }
}

pub struct Map2DIterator<T> {
    /// Input iterator
    iter: T,
    x: i32,
    y: i32,
}

impl<T: Iterator<Item = char>> Iterator for Map2DIterator<T> {
    type Item = (char, i32, i32);

    fn next(&mut self) -> Option<(char, i32, i32)> {
        loop {
            match self.iter.next() {
                None => return None,
                Some(c) if c == '\n' => {
                    self.y += 1;
                    self.x = 0;
                }
                Some(c) if (c as u32) < 32 => {}
                Some(c) => {
                    self.x += 1;
                    return Some((c, self.x - 1, self.y));
                }
            }
        }
    }
}

pub trait Map2DUtil: Sized {
    /// Convert an input value into a sequence of 2D coordinates associated
    /// with a subvalue.
    ///
    /// Used for converting a string of ASCII art into characters and their
    /// coordinates.
    fn map2d(self) -> Map2DIterator<Self>;
}

impl<T: Iterator<Item = char>> Map2DUtil for T {
    fn map2d(self) -> Map2DIterator<T> {
        Map2DIterator {
            iter: self,
            x: 0,
            y: 0,
        }
    }
}
<commit_msg>Simplify line splitter<commit_after>//! String processing utilities

/// Split a long line into multiple lines that fit a given width.
///
/// Will treat newlines in the input as regular whitespace, you probably want to split your input
/// at newlines before using `split_line` on the individual lines.
pub fn split_line<'a, F>(text: &'a str, char_width: F, max_width: f32) -> LineSplit<'a, F>
    where F: Fn(char) -> f32
{
    LineSplit {
        remain: text,
        char_width: char_width,
        max_width: max_width,
        finished: false,
    }
}

pub struct LineSplit<'a, F> {
    remain: &'a str,
    char_width: F,
    max_width: f32,
    finished: bool,
}

impl<'a, F> Iterator for LineSplit<'a, F>
    where F: Fn(char) -> f32
{
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.finished {
            return None;
        }

        struct State {
            total_width: f32,
            clip_pos: usize,
            last_word_break: Option<(usize, f32)>,
            prev: char,
        }

        impl State {
            fn new() -> State {
                State {
                    total_width: 0.0,
                    clip_pos: 0,
                    last_word_break: None,
                    prev: 'A',
                }
            }

            fn update<F: Fn(char) -> f32>(
                &mut self,
                char_width: &F,
                c: char
            ) -> Option<(usize, f32)> {
                if c.is_whitespace() && !self.prev.is_whitespace() {
                    self.last_word_break = Some((self.clip_pos, self.total_width));
                }
                self.clip_pos += c.len_utf8();
                self.total_width += char_width(c);
                self.prev = c;

                // Return the cut in the current word if there is no last_word_break set yet.
                Some(self.last_word_break.unwrap_or((self.clip_pos, self.total_width)))
            }
        }

        let end_pos = {
            self.remain
                .chars()
                .chain(Some(' ')) // Makes the ending of the last word in line show up.
                .scan(State::new(), |s, c| s.update(&self.char_width, c))
                .scan(true, |is_first, (i, w)| {
                    // Always return at least one element.
                    // Past that return the last element that fits in the space.
                    if *is_first {
                        *is_first = false;
                        Some(i)
                    } else {
                        if w <= self.max_width { Some(i) } else { None }
                    }
                })
                .last()
                .unwrap_or(0)
        };

        let ret = &self.remain[..end_pos];

        self.remain = &self.remain[end_pos..];
        // Strip whitespace between this line and the next.
        let start_pos = self.remain
                            .chars()
                            .take_while(|&c| c.is_whitespace())
                            .map(|c| c.len_utf8())
                            .sum();
        self.remain = &self.remain[start_pos..];
        if self.remain.is_empty() {
            self.finished = true;
        }

        Some(ret)
    }
}

pub struct Map2DIterator<T> {
    /// Input iterator
    iter: T,
    x: i32,
    y: i32,
}

impl<T: Iterator<Item = char>> Iterator for Map2DIterator<T> {
    type Item = (char, i32, i32);

    fn next(&mut self) -> Option<(char, i32, i32)> {
        loop {
            match self.iter.next() {
                None => return None,
                Some(c) if c == '\n' => {
                    self.y += 1;
                    self.x = 0;
                }
                Some(c) if (c as u32) < 32 => {}
                Some(c) => {
                    self.x += 1;
                    return Some((c, self.x - 1, self.y));
                }
            }
        }
    }
}

pub trait Map2DUtil: Sized {
    /// Convert an input value into a sequence of 2D coordinates associated
    /// with a subvalue.
    ///
    /// Used for converting a string of ASCII art into characters and their
    /// coordinates.
    fn map2d(self) -> Map2DIterator<Self>;
}

impl<T: Iterator<Item = char>> Map2DUtil for T {
    fn map2d(self) -> Map2DIterator<T> {
        Map2DIterator {
            iter: self,
            x: 0,
            y: 0,
        }
    }
}
<|endoftext|>


<commit_before>use parking_lot::RwLock;
use serde::de::Error as DeError;
use serde_json;
use std::sync::Arc;
use super::utils::*;
use super::*;

/// A representation of the data retrieved from the bot gateway endpoint.
///
/// This is different from the [`Gateway`], as this includes the number of
/// shards that Discord recommends to use for a bot user.
///
/// This is only applicable to bot users.
#[derive(Clone, Debug, Deserialize)]
pub struct BotGateway {
    /// The number of shards that is recommended to be used by the current bot
    /// user.
    pub shards: u64,
    /// The gateway to connect to.
    pub url: String,
}

/// Representation of a game that a [`User`] is playing -- or streaming in the
/// case that a stream URL is provided.
#[derive(Clone, Debug)]
pub struct Game {
    /// The type of game status.
    pub kind: GameType,
    /// The name of the game being played.
    pub name: String,
    /// The Stream URL if [`kind`] is [`GameType::Streaming`].
    ///
    /// [`GameType::Streaming`]: enum.GameType.html#variant.Streaming
    /// [`kind`]: #structfield.kind
    pub url: Option<String>,
}

#[cfg(feature = "model")]
impl Game {
    /// Creates a `Game` struct that appears as a `Playing <name>` status.
    ///
    /// **Note**: Maximum `name` length is 128.
    ///
    /// # Examples
    ///
    /// Create a command that sets the current game being played:
    ///
    /// ```rust,no_run
    /// # #[macro_use] extern crate serenity;
    /// #
    /// use serenity::framework::standard::Args;
    /// use serenity::model::Game;
    ///
    /// command!(game(ctx, _msg, args) {
    ///     let name = args.join(" ");
    ///     ctx.set_game(Game::playing(&name));
    /// });
    /// #
    /// # fn main() {}
    /// ```
    pub fn playing(name: &str) -> Game {
        Game {
            kind: GameType::Playing,
            name: name.to_string(),
            url: None,
        }
    }

    /// Creates a `Game` struct that appears as a `Streaming <name>` status.
    ///
    /// **Note**: Maximum `name` length is 128.
    ///
    /// # Examples
    ///
    /// Create a command that sets the current game and stream:
    ///
    /// ```rust,no_run
    /// # #[macro_use] extern crate serenity;
    /// #
    /// use serenity::framework::standard::Args;
    /// use serenity::model::Game;
    ///
    /// // Assumes command has min_args set to 2.
    /// command!(stream(ctx, _msg, args) {
    ///     # let stream_url = String::from("");
    ///     let name = args.full();
    ///     ctx.set_game(Game::streaming(&name, &stream_url));
    /// });
    /// #
    /// # fn main() {}
    /// ```
    pub fn streaming(name: &str, url: &str) -> Game {
        Game {
            kind: GameType::Streaming,
            name: name.to_string(),
            url: Some(url.to_string()),
        }
    }
}

impl<'de> Deserialize<'de> for Game {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
        let mut map = JsonMap::deserialize(deserializer)?;
        let kind = map.remove("type")
            .and_then(|v| GameType::deserialize(v).ok())
            .unwrap_or(GameType::Playing);
        let name = map.remove("name")
            .and_then(|v| String::deserialize(v).ok())
            .unwrap_or_else(String::new);
        let url = map.remove("url")
            .and_then(|v| serde_json::from_value::<String>(v).ok());

        Ok(Game {
            kind: kind,
            name: name,
            url: url,
        })
    }
}

enum_number!(
    /// The type of activity that is being performed when playing a game.
    GameType {
        /// An indicator that the user is playing a game.
        Playing = 0,
        /// An indicator that the user is streaming to a service.
        Streaming = 1,
    }
);

impl Default for GameType {
    fn default() -> Self { GameType::Playing }
}

/// A representation of the data retrieved from the gateway endpoint.
///
/// For the bot-specific gateway, refer to [`BotGateway`].
///
/// [`BotGateway`]: struct.BotGateway.html
#[derive(Clone, Debug, Deserialize)]
pub struct Gateway {
    /// The gateway to connect to.
    pub url: String,
}

/// Information detailing the current online status of a [`User`].
///
/// [`User`]: struct.User.html
#[derive(Clone, Debug)]
pub struct Presence {
    /// The game that a [`User`] is current playing.
    ///
    /// [`User`]: struct.User.html
    pub game: Option<Game>,
    /// The date of the last presence update.
    pub last_modified: Option<u64>,
    /// The nickname of the member, if applicable.
    pub nick: Option<String>,
    /// The user's online status.
    pub status: OnlineStatus,
    /// The Id of the [`User`]. Can be used to calculate the user's creation
    /// date.
    pub user_id: UserId,
    /// The associated user instance.
    pub user: Option<Arc<RwLock<User>>>,
}

impl<'de> Deserialize<'de> for Presence {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Presence, D::Error> {
        let mut map = JsonMap::deserialize(deserializer)?;
        let mut user_map = map.remove("user")
            .ok_or_else(|| DeError::custom("expected presence user"))
            .and_then(JsonMap::deserialize)
            .map_err(DeError::custom)?;

        let (user_id, user) = if user_map.len() > 1 {
            let user = User::deserialize(Value::Object(user_map))
                .map_err(DeError::custom)?;

            (user.id, Some(Arc::new(RwLock::new(user))))
        } else {
            let user_id = user_map
                .remove("id")
                .ok_or_else(|| DeError::custom("Missing presence user id"))
                .and_then(|x| UserId::deserialize(x.clone()))
                .map_err(DeError::custom)?;

            (user_id, None)
        };

        let game = match map.remove("game") {
            Some(v) => serde_json::from_value::<Option<Game>>(v)
                .map_err(DeError::custom)?,
            None => None,
        };
        let last_modified = match map.remove("last_modified") {
            Some(v) => Some(u64::deserialize(v).map_err(DeError::custom)?),
            None => None,
        };
        let nick = match map.remove("nick") {
            Some(v) => serde_json::from_value::<Option<String>>(v)
                .map_err(DeError::custom)?,
            None => None,
        };
        let status = map.remove("status")
            .ok_or_else(|| DeError::custom("expected presence status"))
            .and_then(OnlineStatus::deserialize)
            .map_err(DeError::custom)?;

        Ok(Presence {
            game: game,
            last_modified: last_modified,
            nick: nick,
            status: status,
            user: user,
            user_id: user_id,
        })
    }
}

/// An initial set of information given after IDENTIFYing to the gateway.
#[derive(Clone, Debug, Deserialize)]
pub struct Ready {
    pub guilds: Vec<GuildStatus>,
    #[serde(deserialize_with = "deserialize_presences")] pub presences: HashMap<UserId, Presence>,
    #[serde(deserialize_with = "deserialize_private_channels")]
    pub private_channels:
        HashMap<ChannelId, Channel>,
    pub session_id: String,
    pub shard: Option<[u64; 2]>,
    #[serde(default, rename = "_trace")] pub trace: Vec<String>,
    pub user: CurrentUser,
    #[serde(rename = "v")] pub version: u64,
}
<commit_msg>Add the new game types (#219)<commit_after>use parking_lot::RwLock;
use serde::de::Error as DeError;
use serde_json;
use std::sync::Arc;
use super::utils::*;
use super::*;

/// A representation of the data retrieved from the bot gateway endpoint.
///
/// This is different from the [`Gateway`], as this includes the number of
/// shards that Discord recommends to use for a bot user.
///
/// This is only applicable to bot users.
#[derive(Clone, Debug, Deserialize)]
pub struct BotGateway {
    /// The number of shards that is recommended to be used by the current bot
    /// user.
    pub shards: u64,
    /// The gateway to connect to.
    pub url: String,
}

/// Representation of a game that a [`User`] is playing -- or streaming in the
/// case that a stream URL is provided.
#[derive(Clone, Debug)]
pub struct Game {
    /// The type of game status.
    pub kind: GameType,
    /// The name of the game being played.
    pub name: String,
    /// The Stream URL if [`kind`] is [`GameType::Streaming`].
    ///
    /// [`GameType::Streaming`]: enum.GameType.html#variant.Streaming
    /// [`kind`]: #structfield.kind
    pub url: Option<String>,
}

#[cfg(feature = "model")]
impl Game {
    /// Creates a `Game` struct that appears as a `Playing <name>` status.
    ///
    /// **Note**: Maximum `name` length is 128.
    ///
    /// # Examples
    ///
    /// Create a command that sets the current game being played:
    ///
    /// ```rust,no_run
    /// # #[macro_use] extern crate serenity;
    /// #
    /// use serenity::framework::standard::Args;
    /// use serenity::model::Game;
    ///
    /// command!(game(ctx, _msg, args) {
    ///     let name = args.join(" ");
    ///     ctx.set_game(Game::playing(&name));
    /// });
    /// #
    /// # fn main() {}
    /// ```
    pub fn playing(name: &str) -> Game {
        Game {
            kind: GameType::Playing,
            name: name.to_string(),
            url: None,
        }
    }

    /// Creates a `Game` struct that appears as a `Streaming <name>` status.
    ///
    /// **Note**: Maximum `name` length is 128.
    ///
    /// # Examples
    ///
    /// Create a command that sets the current game and stream:
    ///
    /// ```rust,no_run
    /// # #[macro_use] extern crate serenity;
    /// #
    /// use serenity::framework::standard::Args;
    /// use serenity::model::Game;
    ///
    /// // Assumes command has min_args set to 2.
    /// command!(stream(ctx, _msg, args) {
    ///     # let stream_url = String::from("");
    ///     let name = args.full();
    ///     ctx.set_game(Game::streaming(&name, &stream_url));
    /// });
    /// #
    /// # fn main() {}
    /// ```
    pub fn streaming(name: &str, url: &str) -> Game {
        Game {
            kind: GameType::Streaming,
            name: name.to_string(),
            url: Some(url.to_string()),
        }
    }

    /// Creates a `Game` struct that appears as a `Listening to <name>` status.
    ///
    /// **Note**: Maximum `name` length is 128.
    ///
    /// # Examples
    ///
    /// Create a command that sets the current game being played:
    ///
    /// ```rust,no_run
    /// # #[macro_use] extern crate serenity;
    /// #
    /// use serenity::framework::standard::Args;
    /// use serenity::model::Game;
    ///
    /// command!(listen(ctx, _msg, args) {
    ///     let name = args.join(" ");
    ///     ctx.set_game(Game::listening(&name));
    /// });
    /// #
    /// # fn main() {}
    /// ```
    pub fn listening(name: &str) -> Game {
        Game {
            kind: GameType::Listening,
            name: name.to_string(),
            url: None,
        }
    }

    /// Creates a `Game` struct that appears as a `Watching <name>` status.
    ///
    /// **Note**: Maximum `name` length is 128.
    ///
    /// # Examples
    ///
    /// Create a command that sets the current game being played:
    ///
    /// ```rust,no_run
    /// # #[macro_use] extern crate serenity;
    /// #
    /// use serenity::framework::standard::Args;
    /// use serenity::model::Game;
    ///
    /// command!(watch(ctx, _msg, args) {
    ///     let name = args.join(" ");
    ///     ctx.set_game(Game::watching(&name));
    /// });
    /// #
    /// # fn main() {}
    /// ```
    pub fn watching(name: &str) -> Game {
        Game {
            kind: GameType::Watching,
            name: name.to_string(),
            url: None,
        }
    }
}

impl<'de> Deserialize<'de> for Game {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
        let mut map = JsonMap::deserialize(deserializer)?;
        let kind = map.remove("type")
            .and_then(|v| GameType::deserialize(v).ok())
            .unwrap_or(GameType::Playing);
        let name = map.remove("name")
            .and_then(|v| String::deserialize(v).ok())
            .unwrap_or_else(String::new);
        let url = map.remove("url")
            .and_then(|v| serde_json::from_value::<String>(v).ok());

        Ok(Game {
            kind: kind,
            name: name,
            url: url,
        })
    }
}

enum_number!(
    /// The type of activity that is being performed when playing a game.
    GameType {
        /// An indicator that the user is playing a game.
        Playing = 0,
        /// An indicator that the user is streaming to a service.
        Streaming = 1,
        /// An indicator that the user is listening to something.
        Listening = 2,
        /// An indicator that the user is watching something.
        Watching = 3,
    }
);

impl Default for GameType {
    fn default() -> Self { GameType::Playing }
}

/// A representation of the data retrieved from the gateway endpoint.
///
/// For the bot-specific gateway, refer to [`BotGateway`].
///
/// [`BotGateway`]: struct.BotGateway.html
#[derive(Clone, Debug, Deserialize)]
pub struct Gateway {
    /// The gateway to connect to.
    pub url: String,
}

/// Information detailing the current online status of a [`User`].
///
/// [`User`]: struct.User.html
#[derive(Clone, Debug)]
pub struct Presence {
    /// The game that a [`User`] is current playing.
    ///
    /// [`User`]: struct.User.html
    pub game: Option<Game>,
    /// The date of the last presence update.
    pub last_modified: Option<u64>,
    /// The nickname of the member, if applicable.
    pub nick: Option<String>,
    /// The user's online status.
    pub status: OnlineStatus,
    /// The Id of the [`User`]. Can be used to calculate the user's creation
    /// date.
    pub user_id: UserId,
    /// The associated user instance.
    pub user: Option<Arc<RwLock<User>>>,
}

impl<'de> Deserialize<'de> for Presence {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Presence, D::Error> {
        let mut map = JsonMap::deserialize(deserializer)?;
        let mut user_map = map.remove("user")
            .ok_or_else(|| DeError::custom("expected presence user"))
            .and_then(JsonMap::deserialize)
            .map_err(DeError::custom)?;

        let (user_id, user) = if user_map.len() > 1 {
            let user = User::deserialize(Value::Object(user_map))
                .map_err(DeError::custom)?;

            (user.id, Some(Arc::new(RwLock::new(user))))
        } else {
            let user_id = user_map
                .remove("id")
                .ok_or_else(|| DeError::custom("Missing presence user id"))
                .and_then(|x| UserId::deserialize(x.clone()))
                .map_err(DeError::custom)?;

            (user_id, None)
        };

        let game = match map.remove("game") {
            Some(v) => serde_json::from_value::<Option<Game>>(v)
                .map_err(DeError::custom)?,
            None => None,
        };
        let last_modified = match map.remove("last_modified") {
            Some(v) => Some(u64::deserialize(v).map_err(DeError::custom)?),
            None => None,
        };
        let nick = match map.remove("nick") {
            Some(v) => serde_json::from_value::<Option<String>>(v)
                .map_err(DeError::custom)?,
            None => None,
        };
        let status = map.remove("status")
            .ok_or_else(|| DeError::custom("expected presence status"))
            .and_then(OnlineStatus::deserialize)
            .map_err(DeError::custom)?;

        Ok(Presence {
            game: game,
            last_modified: last_modified,
            nick: nick,
            status: status,
            user: user,
            user_id: user_id,
        })
    }
}

/// An initial set of information given after IDENTIFYing to the gateway.
#[derive(Clone, Debug, Deserialize)]
pub struct Ready {
    pub guilds: Vec<GuildStatus>,
    #[serde(deserialize_with = "deserialize_presences")] pub presences: HashMap<UserId, Presence>,
    #[serde(deserialize_with = "deserialize_private_channels")]
    pub private_channels:
        HashMap<ChannelId, Channel>,
    pub session_id: String,
    pub shard: Option<[u64; 2]>,
    #[serde(default, rename = "_trace")] pub trace: Vec<String>,
    pub user: CurrentUser,
    #[serde(rename = "v")] pub version: u64,
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
const END_TAG_LEN: u32 = 8;

use core::mem::transmute;

#[macro_use]
macro_rules! ptr {
    ($it:expr) => { &$it as *const _ }
}

pub mod elf;
pub mod elf64;

#[repr(C)]
pub struct Info { pub length: u32
                , _pad: u32
                , tag_start: Tag
                }

impl Info {

    pub unsafe fn from(addr: usize) -> &'static Self {
        let info = &*(addr as *const Info);
        assert!(info.has_end());
        info
    }

    /// Finds the tag with the given tag type.
    ///
    /// This is actually safe since the tag types are constrained by The
    /// `TagType` enum
    pub fn get_tag(&self, tag_type: TagType) -> Option<&'static Tag> {
        self.tags()
            .find(|t| t.ty == tag_type)
    }

    #[inline]
    pub fn mem_map(&self) -> Option<&'static MemMapTag> {
        self.get_tag(TagType::MemoryMap)
            .map(|tag| unsafe { &*(ptr!(tag) as *const MemMapTag) })
    }

    #[inline]
    pub fn elf64_sections(&self) -> Option<&'static elf64::SectionsTag> {
        self.get_tag(TagType::ELFSections)
            .map(|tag| unsafe { &*(ptr!(tag) as *const elf64::SectionsTag) })
    }

    #[inline]
    fn tags(&self) -> Tags { Tags(ptr!(self.tag_start)) }

    fn has_end(&self) -> bool {
        let end_tag_addr
            = (self as *const _) as usize +
              (self.length - END_TAG_LEN) as usize;
        let end_tag = unsafe {&*(end_tag_addr as *const Tag)};
        end_tag.ty == TagType::End && end_tag.length == 8
    }
}

/// A Multiboot tag.
///
/// From the specification:
///
/// Boot information consists of a fixed part and a series of tags.
/// Its start is 8-bytes aligned. Fixed part is as following:
///
///<rawtext>
///
///             +-------------------+
///     u32     | total_size        |
///     u32     | reserved          |
///             +-------------------+
///</rawtext>
///
/// `total_size` contains the total size of boot information including this
/// field and terminating tag in bytes.
/// `reserved` is always set to zero and must be ignored by OS image.
///
///  Every tag begins with following fields:
///<rawtext>
///
///             +-------------------+
///     u32     | type              |
///     u32     | size              |
///             +-------------------+
///</rawtext>
/// `type` contains an identifier of contents of the rest of the tag. `size`
/// contains the size of tag including header fields but not including padding.
/// Tags follow one another padded when necessary in order for each tag to
/// start at 8-bytes aligned address. Tags are terminated by a tag of type `0`
/// and size `8`.
#[repr(C)]
#[derive(Debug)]
pub struct Tag { ty: TagType
               , length: u32
               }

/// Types of Multiboot tags
///
/// Refer to Chapter 3 of the Multiboot 2 spec
#[repr(u32)]
#[derive(Debug, Eq, PartialEq)]
pub enum TagType { /// Tag that indicates the end of multiboot tags
                   End              = 0
                 , /// Command line passed to the bootloader
                   CommandLine      = 1
                 , BootloaderName   = 2
                 , Modules          = 3
                 , BasicMemInfo     = 4
                 , BIOSBootDev      = 5
                 , MemoryMap        = 6
                 , VBEInfo          = 7
                 , FramebufferInfo  = 8
                 , ELFSections      = 9
                 , APMTable         = 10
                 }

struct Tags(*const Tag);

impl Tags {
    #[inline] fn advance(&mut self, size: u32) {
        let next_addr = self.0 as usize + size as usize;
        self.0 = (((next_addr-1) & !0x7) + 0x8) as *const _;
    }
}

impl Iterator for Tags {
    type Item = &'static Tag;

    fn next(&mut self) -> Option<Self::Item> {
        match unsafe { &*self.0 } {
            &Tag{ ty: TagType::End, length: END_TAG_LEN } => None
          , tag => { self.advance(tag.length); Some(tag) }
        }
    }
}

#[repr(C)]
pub struct MemMapTag { tag: Tag
                     , entry_size: u32
                     , entry_version: u32
                     , first_entry: MemArea
                     }
impl MemMapTag {
    pub fn entries(&self) -> Entries {
        let p = self as *const MemMapTag;
        Entries { curr: (&self.first_entry) as *const MemArea
                , last: ((p as u32) + self.tag.length - self.entry_size)
                        as *const MemArea
                , size: self.entry_size
                }
    }
}

#[repr(u32)]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum MemAreaType { Available = 1
                     , ACPI      = 3
                     , Preserve  = 4
                     }

#[repr(C)]
pub struct MemArea { pub base: u64
                   , pub length: u64
                   , ty: MemAreaType
                   , _pad: u32
                   }

pub struct Entries { curr: *const MemArea
                   , last: *const MemArea
                   , size: u32
                   }

impl Iterator for Entries {
    type Item = &'static MemArea;
    fn next(&mut self) -> Option<&'static MemArea> {
        if self.curr > self.last {
            None
        } else {
            let current = unsafe { &*self.curr };
            self.curr = (self.curr as u32 + self.size) as *const MemArea;
            if current.ty == MemAreaType::Available {
                Some(current)
            } else {
                self.next()
            }
        }
    }
}
<commit_msg>Second KP fix attempt<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
const END_TAG_LEN: u32 = 8;

use core::mem::transmute;

#[macro_use]
macro_rules! ptr {
    ($it:expr) => { &$it as *const _ }
}

pub mod elf;
pub mod elf64;

#[repr(C)]
pub struct Info { pub length: u32
                , _pad: u32
                , tag_start: Tag
                }

impl Info {

    pub unsafe fn from(addr: usize) -> &'static Self {
        let info = &*(addr as *const Info);
        assert!(info.has_end());
        info
    }

    /// Finds the tag with the given tag type.
    ///
    /// This is actually safe since the tag types are constrained by The
    /// `TagType` enum
    pub fn get_tag(&self, tag_type: TagType) -> Option<&'static Tag> {
        self.tags()
            .find(|t| t.ty == tag_type)
    }

    #[inline]
    pub fn mem_map(&self) -> Option<&'static MemMapTag> {
        self.get_tag(TagType::MemoryMap)
            .map(|tag| unsafe { &*(ptr!(tag) as *const MemMapTag) })
    }

    #[inline]
    pub fn elf64_sections(&self) -> Option<&'static elf64::SectionsTag> {
        self.get_tag(TagType::ELFSections)
            .map(|tag| unsafe { &*(ptr!(tag) as *const elf64::SectionsTag) })
    }

    #[inline]
    fn tags(&self) -> Tags { Tags(ptr!(self.tag_start)) }

    fn has_end(&self) -> bool {
        let end_tag_addr
            = (self as *const _) as usize +
              (self.length - END_TAG_LEN) as usize;
        let end_tag = unsafe {&*(end_tag_addr as *const Tag)};
        end_tag.ty == TagType::End && end_tag.length == 8
    }
}

/// A Multiboot tag.
///
/// From the specification:
///
/// Boot information consists of a fixed part and a series of tags.
/// Its start is 8-bytes aligned. Fixed part is as following:
///
///<rawtext>
///
///             +-------------------+
///     u32     | total_size        |
///     u32     | reserved          |
///             +-------------------+
///</rawtext>
///
/// `total_size` contains the total size of boot information including this
/// field and terminating tag in bytes.
/// `reserved` is always set to zero and must be ignored by OS image.
///
///  Every tag begins with following fields:
///<rawtext>
///
///             +-------------------+
///     u32     | type              |
///     u32     | size              |
///             +-------------------+
///</rawtext>
/// `type` contains an identifier of contents of the rest of the tag. `size`
/// contains the size of tag including header fields but not including padding.
/// Tags follow one another padded when necessary in order for each tag to
/// start at 8-bytes aligned address. Tags are terminated by a tag of type `0`
/// and size `8`.
#[repr(C)]
#[derive(Debug)]
pub struct Tag { ty: TagType
               , length: u32
               }

/// Types of Multiboot tags
///
/// Refer to Chapter 3 of the Multiboot 2 spec
#[repr(u32)]
#[derive(Debug, Eq, PartialEq)]
pub enum TagType { /// Tag that indicates the end of multiboot tags
                   End              = 0
                 , /// Command line passed to the bootloader
                   CommandLine      = 1
                 , BootloaderName   = 2
                 , Modules          = 3
                 , BasicMemInfo     = 4
                 , BIOSBootDev      = 5
                 , MemoryMap        = 6
                 , VBEInfo          = 7
                 , FramebufferInfo  = 8
                 , ELFSections      = 9
                 , APMTable         = 10
                 }

struct Tags(*const Tag);

impl Tags {
    #[inline] fn advance(&mut self, size: u32) {
        let next_addr = self.0 as usize + size as usize;
        self.0 = (((next_addr-1) & !0x7) + 0x8) as *const _;
    }
}

impl Iterator for Tags {
    type Item = &'static Tag;

    fn next(&mut self) -> Option<Self::Item> {
        match unsafe { &*self.0 } {
            &Tag{ ty: TagType::End, length: END_TAG_LEN } => None
          , tag => { self.advance(tag.length); Some(tag) }
        }
    }
}

#[repr(C)]
pub struct MemMapTag { tag: Tag
                     , entry_size: u32
                     , entry_version: u32
                     , first_entry: MemArea
                     }
impl MemMapTag {
    pub fn entries(&self) -> Entries {
        let p =
        Entries { curr: (&self.first_entry) as *const MemArea
                , last: ((self as *const MemMapTag as u32) +
                        (self.tag.length - self.entry_size))
                        as *const MemArea
                , size: self.entry_size
                }
    }
}

#[repr(u32)]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum MemAreaType { Available = 1
                     , ACPI      = 3
                     , Preserve  = 4
                     }

#[repr(C)]
pub struct MemArea { pub base: u64
                   , pub length: u64
                   , ty: MemAreaType
                   , _pad: u32
                   }

pub struct Entries { curr: *const MemArea
                   , last: *const MemArea
                   , size: u32
                   }

impl Iterator for Entries {
    type Item = &'static MemArea;
    fn next(&mut self) -> Option<&'static MemArea> {
        if self.curr > self.last {
            None
        } else {
            let current = unsafe { &*self.curr };
            self.curr = (self.curr as u32 + self.size) as *const MemArea;
            if current.ty == MemAreaType::Available {
                Some(current)
            } else {
                self.next()
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This is a port of the pcre project's `pcredemo` sample using rust-pcre bindings.

extern crate collections;
//extern crate extra;
extern crate getopts;
extern crate pcre;

use collections::treemap::{TreeMap};
use collections::enum_set::{EnumSet};
use getopts::{OptGroup, getopts, optflag};
use pcre::{CompileOption, Match, Pcre, pcre_version};
use std::io::stdio::stderr;
use std::os;
use std::string::{String};

fn print_usage(program: &String, opts: &[OptGroup]) {
    drop(opts);
    println!("Usage: {} [options] pattern subject", program);
    println!("Options:");
    println!("    -g                  Find all matches");
    println!("    -h, --help          Print usage and exit");
    println!("    --version           Print version information and exit");
}

fn print_version_info() {
    println!("rust-pcre 0.1 compiled against libpcre {}", pcre_version());
}

fn print_match(m: &Match, name_table: &TreeMap<String, Vec<uint>>) {
    println!("Match succeeded at offset {:u}", m.group_start(0u));

    // Show captured substrings by number.
    let mut i = 0u;
    while i < m.string_count() {
        println!("{:2u}: {:s}", i, m.group(i));
        i += 1;
    }

    let name_count = name_table.len();
    if name_count <= 0 {
        println!("No named substrings");
    } else {
        println!("Named substrings:");
        for (name, n_vec) in name_table.iter() {
            for n in n_vec.iter() {
                println!("({:u}) {:s}: {:s}", *n, *name, m.group(*n));
            }
        }
    }
}

fn main() {
    let args = os::args();
    let program = args.get(0);

    let opts = [
        optflag("g", "", "find all matches"),
        optflag("h", "help", "print usage and exit"),
        optflag("", "version", "print version information and exit")
    ];

    let opt_matches = match getopts(args.tail(), opts) {
        Ok(m)  => m,
        Err(f) => {
            writeln!(stderr(), "Error: {}", f.to_err_msg());
            os::set_exit_status(1);
            return;
        }
    };

    if opt_matches.opt_present("h") || opt_matches.opt_present("help") {
        print_usage(program, opts);
        return;
    }

    if opt_matches.opt_present("version") {
        print_version_info();
        return;
    }

    let find_all = opt_matches.opt_present("g");
    if opt_matches.free.len() == 0 {
        writeln!(stderr(), "Error: No pattern");
        os::set_exit_status(1);
        return;
    } else if opt_matches.free.len() == 1 {
        writeln!(stderr(), "Error: No subject");
        os::set_exit_status(1);
        return;
    } else if opt_matches.free.len() > 2 {
        writeln!(stderr(), "Error: Too many command line arguments");
        os::set_exit_status(1);
        return;
    }

    let pattern = opt_matches.free.get(0);
    let subject = opt_matches.free.get(1);

    let mut compile_options: EnumSet<CompileOption> = EnumSet::empty();
    compile_options.add(pcre::DupNames);
    let re = match Pcre::compile_with_options(pattern.as_slice(), &compile_options) {
        Err(err) => {
            writeln!(stderr(), "Error: The pattern could not be compiled: {:s}", err.to_str());
            os::set_exit_status(1);
            return;
        },
        Ok(re) => re
    };
    let name_table = re.name_table();

    let opt_m = re.exec(subject.as_slice());
    let m = match opt_m {
        None => {
            println!("No match");
            os::set_exit_status(1);
            return;
        }
        Some(m) => m
    };
    print_match(&m, &name_table);

    if find_all {
        let mut start_offset = m.group_end(0);
        loop {
            let opt_m = re.exec_from(subject.as_slice(), start_offset);
            let m = match opt_m {
                None => {
                    println!("\nNo more matches");
                    return;
                }
                Some(m) => m
            };

            println!("");
            print_match(&m, &name_table);

            start_offset = m.group_end(0);
        }
    }
}
<commit_msg>Fix error: type `pcre::CompilationError` does not implement any method in scope named `to_str`<commit_after>// Copyright 2014 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This is a port of the pcre project's `pcredemo` sample using rust-pcre bindings.

extern crate collections;
//extern crate extra;
extern crate getopts;
extern crate pcre;

use collections::treemap::{TreeMap};
use collections::enum_set::{EnumSet};
use getopts::{OptGroup, getopts, optflag};
use pcre::{CompileOption, Match, Pcre, pcre_version};
use std::io::stdio::stderr;
use std::os;
use std::string::{String};

fn print_usage(program: &String, opts: &[OptGroup]) {
    drop(opts);
    println!("Usage: {} [options] pattern subject", program);
    println!("Options:");
    println!("    -g                  Find all matches");
    println!("    -h, --help          Print usage and exit");
    println!("    --version           Print version information and exit");
}

fn print_version_info() {
    println!("rust-pcre 0.1 compiled against libpcre {}", pcre_version());
}

fn print_match(m: &Match, name_table: &TreeMap<String, Vec<uint>>) {
    println!("Match succeeded at offset {:u}", m.group_start(0u));

    // Show captured substrings by number.
    let mut i = 0u;
    while i < m.string_count() {
        println!("{:2u}: {:s}", i, m.group(i));
        i += 1;
    }

    let name_count = name_table.len();
    if name_count <= 0 {
        println!("No named substrings");
    } else {
        println!("Named substrings:");
        for (name, n_vec) in name_table.iter() {
            for n in n_vec.iter() {
                println!("({:u}) {:s}: {:s}", *n, *name, m.group(*n));
            }
        }
    }
}

fn main() {
    let args = os::args();
    let program = args.get(0);

    let opts = [
        optflag("g", "", "find all matches"),
        optflag("h", "help", "print usage and exit"),
        optflag("", "version", "print version information and exit")
    ];

    let opt_matches = match getopts(args.tail(), opts) {
        Ok(m)  => m,
        Err(f) => {
            writeln!(stderr(), "Error: {}", f.to_err_msg());
            os::set_exit_status(1);
            return;
        }
    };

    if opt_matches.opt_present("h") || opt_matches.opt_present("help") {
        print_usage(program, opts);
        return;
    }

    if opt_matches.opt_present("version") {
        print_version_info();
        return;
    }

    let find_all = opt_matches.opt_present("g");
    if opt_matches.free.len() == 0 {
        writeln!(stderr(), "Error: No pattern");
        os::set_exit_status(1);
        return;
    } else if opt_matches.free.len() == 1 {
        writeln!(stderr(), "Error: No subject");
        os::set_exit_status(1);
        return;
    } else if opt_matches.free.len() > 2 {
        writeln!(stderr(), "Error: Too many command line arguments");
        os::set_exit_status(1);
        return;
    }

    let pattern = opt_matches.free.get(0);
    let subject = opt_matches.free.get(1);

    let mut compile_options: EnumSet<CompileOption> = EnumSet::empty();
    compile_options.add(pcre::DupNames);
    let re = match Pcre::compile_with_options(pattern.as_slice(), &compile_options) {
        Err(err) => {
            writeln!(stderr(), "Error: The pattern could not be compiled: {}", err);
            os::set_exit_status(1);
            return;
        },
        Ok(re) => re
    };
    let name_table = re.name_table();

    let opt_m = re.exec(subject.as_slice());
    let m = match opt_m {
        None => {
            println!("No match");
            os::set_exit_status(1);
            return;
        }
        Some(m) => m
    };
    print_match(&m, &name_table);

    if find_all {
        let mut start_offset = m.group_end(0);
        loop {
            let opt_m = re.exec_from(subject.as_slice(), start_offset);
            let m = match opt_m {
                None => {
                    println!("\nNo more matches");
                    return;
                }
                Some(m) => m
            };

            println!("");
            print_match(&m, &name_table);

            start_offset = m.group_end(0);
        }
    }
}
<|endoftext|>


<commit_before>// spell-checker:ignore regfile
use crate::common::util::*;

static GIBBERISH: &str = "supercalifragilisticexpialidocious";

#[test]
fn test_resolve() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    scene.ucmd().arg("bar").succeeds().stdout_contains("foo\n");
}

#[test]
fn test_canonicalize() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg("-f").arg(".").run().stdout_move_str();
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_canonicalize_existing() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg("-e").arg(".").run().stdout_move_str();
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_canonicalize_missing() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg("-m").arg(GIBBERISH).run().stdout_move_str();
    let expect = path_concat!(at.root_dir_resolved(), GIBBERISH) + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_current_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Create a 256-character path to current directory
    let dir = path_concat!(".", ..128);
    let actual = ucmd.arg("-n").arg("-m").arg(dir).run().stdout_move_str();
    let expect = at.root_dir_resolved();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_root() {
    // Create a 255-character path to root
    let dir = path_concat!("..", ..85);
    let actual = new_ucmd!()
        .arg("-n")
        .arg("-m")
        .arg(dir)
        .run()
        .stdout_move_str();
    let expect = get_root_path();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_symlink_to_itself_verbose() {
    let (at, mut ucmd) = at_and_ucmd!();
    at.relative_symlink_file("a", "a");
    ucmd.args(&["-ev", "a"])
        .fails()
        .code_is(1)
        .stderr_contains("Too many levels of symbolic links");
}

#[test]
fn test_trailing_slash_regular_file() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.touch("regfile");
    scene
        .ucmd()
        .args(&["-ev", "./regfile/"])
        .fails()
        .code_is(1)
        .stderr_contains("Not a directory")
        .no_stdout();
    scene
        .ucmd()
        .args(&["-e", "./regfile"])
        .succeeds()
        .stdout_contains("regfile");
}

#[test]
fn test_trailing_slash_symlink_to_regular_file() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.touch("regfile");
    at.relative_symlink_file("regfile", "link");
    scene
        .ucmd()
        .args(&["-ev", "./link/"])
        .fails()
        .code_is(1)
        .stderr_contains("Not a directory")
        .no_stdout();
    scene
        .ucmd()
        .args(&["-e", "./link"])
        .succeeds()
        .stdout_contains("regfile");
    scene
        .ucmd()
        .args(&["-ev", "./link/more"])
        .fails()
        .code_is(1)
        .stderr_contains("Not a directory")
        .no_stdout();
}

#[test]
fn test_trailing_slash_directory() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("directory");
    for query in ["./directory", "./directory/"] {
        scene
            .ucmd()
            .args(&["-e", query])
            .succeeds()
            .stdout_contains("directory");
    }
}

#[test]
fn test_trailing_slash_symlink_to_directory() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("directory");
    at.relative_symlink_dir("directory", "link");
    for query in ["./link", "./link/"] {
        scene
            .ucmd()
            .args(&["-e", query])
            .succeeds()
            .stdout_contains("directory");
    }
    scene
        .ucmd()
        .args(&["-ev", "./link/more"])
        .fails()
        .code_is(1)
        .stderr_contains("No such file or directory");
}

#[test]
fn test_trailing_slash_symlink_to_missing() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("subdir");
    at.relative_symlink_file("missing", "link");
    at.relative_symlink_file("subdir/missing", "link2");
    for query in [
        "missing",
        "./missing/",
        "link",
        "./link/",
        "link/more",
        "link2",
        "./link2/",
        "link2/more",
    ] {
        scene
            .ucmd()
            .args(&["-ev", query])
            .fails()
            .code_is(1)
            .stderr_contains("No such file or directory");
    }
}

#[test]
fn test_canonicalize_trailing_slash_regfile() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.touch("regfile");
    at.relative_symlink_file("regfile", "link1");
    for name in ["regfile", "link1"] {
        scene
            .ucmd()
            .args(&["-f", name])
            .succeeds()
            .stdout_contains("regfile");
        scene
            .ucmd()
            .args(&["-fv", &format!("./{}/", name)])
            .fails()
            .code_is(1)
            .stderr_contains("Not a directory");
        scene
            .ucmd()
            .args(&["-fv", &format!("{}/more", name)])
            .fails()
            .code_is(1)
            .stderr_contains("Not a directory");
        scene
            .ucmd()
            .args(&["-fv", &format!("./{}/more/", name)])
            .fails()
            .code_is(1)
            .stderr_contains("Not a directory");
    }
}

#[test]
fn test_canonicalize_trailing_slash_subdir() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("subdir");
    at.relative_symlink_dir("subdir", "link2");
    for name in ["subdir", "link2"] {
        scene
            .ucmd()
            .args(&["-f", name])
            .succeeds()
            .stdout_contains("subdir");
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/", name)])
            .succeeds()
            .stdout_contains("subdir");
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more", name)])
            .succeeds()
            .stdout_contains(path_concat!("subdir", "more"));
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/", name)])
            .succeeds()
            .stdout_contains(path_concat!("subdir", "more"));
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more/more2", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/more2/", name)])
            .fails()
            .code_is(1);
    }
}

#[test]
fn test_canonicalize_trailing_slash_missing() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.relative_symlink_file("missing", "link3");
    for name in ["missing", "link3"] {
        scene
            .ucmd()
            .args(&["-f", name])
            .succeeds()
            .stdout_contains("missing");
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/", name)])
            .succeeds()
            .stdout_contains("missing");
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/", name)])
            .fails()
            .code_is(1);
    }
}

#[test]
fn test_canonicalize_trailing_slash_subdir_missing() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("subdir");
    at.relative_symlink_file("subdir/missing", "link4");
    for name in ["link4"] {
        scene
            .ucmd()
            .args(&["-f", name])
            .succeeds()
            .stdout_contains(path_concat!("subdir", "missing"));
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/", name)])
            .succeeds()
            .stdout_contains(path_concat!("subdir", "missing"));
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/", name)])
            .fails()
            .code_is(1);
    }
}

#[test]
fn test_canonicalize_trailing_slash_symlink_loop() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.relative_symlink_file("link5", "link5");
    for name in ["link5"] {
        scene.ucmd().args(&["-f", name]).fails().code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/", name)])
            .fails()
            .code_is(1);
    }
}
<commit_msg>tests/readlink: follow clippy advice<commit_after>// spell-checker:ignore regfile
use crate::common::util::*;

static GIBBERISH: &str = "supercalifragilisticexpialidocious";

#[test]
fn test_resolve() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    scene.ucmd().arg("bar").succeeds().stdout_contains("foo\n");
}

#[test]
fn test_canonicalize() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg("-f").arg(".").run().stdout_move_str();
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_canonicalize_existing() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg("-e").arg(".").run().stdout_move_str();
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_canonicalize_missing() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg("-m").arg(GIBBERISH).run().stdout_move_str();
    let expect = path_concat!(at.root_dir_resolved(), GIBBERISH) + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_current_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Create a 256-character path to current directory
    let dir = path_concat!(".", ..128);
    let actual = ucmd.arg("-n").arg("-m").arg(dir).run().stdout_move_str();
    let expect = at.root_dir_resolved();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_root() {
    // Create a 255-character path to root
    let dir = path_concat!("..", ..85);
    let actual = new_ucmd!()
        .arg("-n")
        .arg("-m")
        .arg(dir)
        .run()
        .stdout_move_str();
    let expect = get_root_path();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_symlink_to_itself_verbose() {
    let (at, mut ucmd) = at_and_ucmd!();
    at.relative_symlink_file("a", "a");
    ucmd.args(&["-ev", "a"])
        .fails()
        .code_is(1)
        .stderr_contains("Too many levels of symbolic links");
}

#[test]
fn test_trailing_slash_regular_file() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.touch("regfile");
    scene
        .ucmd()
        .args(&["-ev", "./regfile/"])
        .fails()
        .code_is(1)
        .stderr_contains("Not a directory")
        .no_stdout();
    scene
        .ucmd()
        .args(&["-e", "./regfile"])
        .succeeds()
        .stdout_contains("regfile");
}

#[test]
fn test_trailing_slash_symlink_to_regular_file() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.touch("regfile");
    at.relative_symlink_file("regfile", "link");
    scene
        .ucmd()
        .args(&["-ev", "./link/"])
        .fails()
        .code_is(1)
        .stderr_contains("Not a directory")
        .no_stdout();
    scene
        .ucmd()
        .args(&["-e", "./link"])
        .succeeds()
        .stdout_contains("regfile");
    scene
        .ucmd()
        .args(&["-ev", "./link/more"])
        .fails()
        .code_is(1)
        .stderr_contains("Not a directory")
        .no_stdout();
}

#[test]
fn test_trailing_slash_directory() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("directory");
    for query in ["./directory", "./directory/"] {
        scene
            .ucmd()
            .args(&["-e", query])
            .succeeds()
            .stdout_contains("directory");
    }
}

#[test]
fn test_trailing_slash_symlink_to_directory() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("directory");
    at.relative_symlink_dir("directory", "link");
    for query in ["./link", "./link/"] {
        scene
            .ucmd()
            .args(&["-e", query])
            .succeeds()
            .stdout_contains("directory");
    }
    scene
        .ucmd()
        .args(&["-ev", "./link/more"])
        .fails()
        .code_is(1)
        .stderr_contains("No such file or directory");
}

#[test]
fn test_trailing_slash_symlink_to_missing() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("subdir");
    at.relative_symlink_file("missing", "link");
    at.relative_symlink_file("subdir/missing", "link2");
    for query in [
        "missing",
        "./missing/",
        "link",
        "./link/",
        "link/more",
        "link2",
        "./link2/",
        "link2/more",
    ] {
        scene
            .ucmd()
            .args(&["-ev", query])
            .fails()
            .code_is(1)
            .stderr_contains("No such file or directory");
    }
}

#[test]
fn test_canonicalize_trailing_slash_regfile() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.touch("regfile");
    at.relative_symlink_file("regfile", "link1");
    for name in ["regfile", "link1"] {
        scene
            .ucmd()
            .args(&["-f", name])
            .succeeds()
            .stdout_contains("regfile");
        scene
            .ucmd()
            .args(&["-fv", &format!("./{}/", name)])
            .fails()
            .code_is(1)
            .stderr_contains("Not a directory");
        scene
            .ucmd()
            .args(&["-fv", &format!("{}/more", name)])
            .fails()
            .code_is(1)
            .stderr_contains("Not a directory");
        scene
            .ucmd()
            .args(&["-fv", &format!("./{}/more/", name)])
            .fails()
            .code_is(1)
            .stderr_contains("Not a directory");
    }
}

#[test]
fn test_canonicalize_trailing_slash_subdir() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("subdir");
    at.relative_symlink_dir("subdir", "link2");
    for name in ["subdir", "link2"] {
        scene
            .ucmd()
            .args(&["-f", name])
            .succeeds()
            .stdout_contains("subdir");
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/", name)])
            .succeeds()
            .stdout_contains("subdir");
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more", name)])
            .succeeds()
            .stdout_contains(path_concat!("subdir", "more"));
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/", name)])
            .succeeds()
            .stdout_contains(path_concat!("subdir", "more"));
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more/more2", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/more2/", name)])
            .fails()
            .code_is(1);
    }
}

#[test]
fn test_canonicalize_trailing_slash_missing() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.relative_symlink_file("missing", "link3");
    for name in ["missing", "link3"] {
        scene
            .ucmd()
            .args(&["-f", name])
            .succeeds()
            .stdout_contains("missing");
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/", name)])
            .succeeds()
            .stdout_contains("missing");
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/", name)])
            .fails()
            .code_is(1);
    }
}

#[test]
fn test_canonicalize_trailing_slash_subdir_missing() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("subdir");
    at.relative_symlink_file("subdir/missing", "link4");
    let name = "link4";
    scene
        .ucmd()
        .args(&["-f", name])
        .succeeds()
        .stdout_contains(path_concat!("subdir", "missing"));
    scene
        .ucmd()
        .args(&["-f", &format!("./{}/", name)])
        .succeeds()
        .stdout_contains(path_concat!("subdir", "missing"));
    scene
        .ucmd()
        .args(&["-f", &format!("{}/more", name)])
        .fails()
        .code_is(1);
    scene
        .ucmd()
        .args(&["-f", &format!("./{}/more/", name)])
        .fails()
        .code_is(1);
}

#[test]
fn test_canonicalize_trailing_slash_symlink_loop() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.relative_symlink_file("link5", "link5");
    for name in ["link5"] {
        scene.ucmd().args(&["-f", name]).fails().code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("{}/more", name)])
            .fails()
            .code_is(1);
        scene
            .ucmd()
            .args(&["-f", &format!("./{}/more/", name)])
            .fails()
            .code_is(1);
    }
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;

use core::cmp;

use common::event::{KeyEvent, MouseEvent};

use drivers::io::{Io, Pio, ReadOnly, WriteOnly};

use graphics::display::VBEMODEINFO;

use fs::KScheme;

use drivers::kb_layouts::layouts;

pub struct Ps2Keyboard<'a> {
    bus: &'a mut Ps2
}

impl<'a> Ps2Keyboard<'a> {
    //TODO: Use result
    fn cmd(&mut self, command: u8) -> u8 {
        self.bus.wait_write();
        self.bus.data.write(command);
        self.bus.wait_read();
        self.bus.data.read()
    }
}

pub struct Ps2Mouse<'a> {
    bus: &'a mut Ps2
}

impl<'a> Ps2Mouse<'a> {
    //TODO: Use result
    fn cmd(&mut self, command: u8) -> u8 {
        self.bus.write(0xD4, command);
        self.bus.wait_read();
        self.bus.data.read()
    }
}

/// PS2
pub struct Ps2 {
    /// The data register
    data: Pio<u8>,
    /// The status register
    sts: ReadOnly<Pio<u8>>,
    /// The command register
    cmd: WriteOnly<Pio<u8>>,
    /// Left shift?
    lshift: bool,
    /// Right shift?
    rshift: bool,
    /// Caps lock?
    caps_lock: bool,
    /// Caps lock toggle
    caps_lock_toggle: bool,
    /// AltGr?
    altgr: bool,
    /// The mouse packet
    mouse_packet: [u8; 4],
    /// Mouse packet index
    mouse_i: usize,
    /// Mouse point x
    mouse_x: i32,
    /// Mouse point y
    mouse_y: i32,
    /// Layout for keyboard
    /// Default: English
    layout: layouts::Layout,
}

impl Ps2 {
    /// Create new PS2 data
    pub fn new() -> Box<Self> {
        let mut module = box Ps2 {
            data: Pio::new(0x60),
            sts: ReadOnly::new(Pio::new(0x64)),
            cmd: WriteOnly::new(Pio::new(0x64)),
            lshift: false,
            rshift: false,
            caps_lock: false,
            caps_lock_toggle: false,
            altgr: false,
            mouse_packet: [0; 4],
            mouse_i: 0,
            mouse_x: 0,
            mouse_y: 0,
            layout: layouts::Layout::English,
        };

        module.init();

        module
    }

    fn wait_read(&self) {
        while ! self.sts.readf(1) {}
    }

    fn wait_write(&self) {
        while self.sts.readf(2) {}
    }

    fn cmd(&mut self, command: u8) {
        self.wait_write();
        self.cmd.write(command);
    }

    fn read(&mut self, command: u8) -> u8 {
        self.cmd(command);
        self.wait_read();
        self.data.read()
    }

    fn write(&mut self, command: u8, data: u8) {
        self.cmd(command);
        self.wait_write();
        self.data.write(data);
    }

    fn keyboard<'a>(&'a mut self) -> Ps2Keyboard<'a> {
        Ps2Keyboard {
            bus: self
        }
    }

    fn mouse<'a>(&'a mut self) -> Ps2Mouse<'a> {
        Ps2Mouse {
            bus: self
        }
    }

    fn init(&mut self) {
        while self.sts.readf(1) {
            self.data.read();
        }

        debugln!(" + PS/2");

        // No interrupts, system flag set, clocks enabled, translation enabled
        self.write(0x60, 0b01000100);

        while self.sts.readf(1) {
            debugln!("Extra {}: {:X}", line!(), self.data.read());
        }

        // Enable First Port
        debugln!("   + Keyboard");
        self.cmd(0xAE);

        while self.sts.readf(1) {
            debugln!("Extra {}: {:X}", line!(), self.data.read());
        }

        {
            // Reset
            debug!("     - Reset {:X}", self.keyboard().cmd(0xFF));
            self.wait_read();
            debugln!(", {:X}", self.data.read());

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }

            // Set defaults
            debugln!("     - Set defaults {:X}", self.keyboard().cmd(0xF6));

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }

            // Enable Streaming
            debugln!("     - Enable streaming {:X}", self.keyboard().cmd(0xF4));

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }
        }

        // Enable Second Port
        debugln!("   + PS/2 Mouse");
        self.cmd(0xA8);

        while self.sts.readf(1) {
            debugln!("Extra {}: {:X}", line!(), self.data.read());
        }

        {
            // Reset
            debug!("     - Reset {:X}", self.keyboard().cmd(0xFF));
            self.wait_read();
            debugln!(", {:X}", self.data.read());

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }

            // Set defaults
            debugln!("     - Set defaults {:X}", self.mouse().cmd(0xF6));

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }

            // Enable Streaming
            debugln!("     - Enable streaming {:X}", self.mouse().cmd(0xF4));

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }
        }

        // Key and mouse interrupts, system flag set, clocks enabled, translation enabled
        self.write(0x60, 0b01000111);

        while self.sts.readf(1) {
            debugln!("Extra {}: {:X}", line!(), self.data.read());
        }
    }

    /// Keyboard interrupt
    pub fn keyboard_interrupt(&mut self, mut scancode: u8) -> Option<KeyEvent> {
        if scancode == 0 {
            return None;
        } else if scancode == 0x2A {
            self.lshift = true;
        } else if scancode == 0xAA {
            self.lshift = false;
        } else if scancode == 0x36 {
            self.rshift = true;
        } else if scancode == 0xB6 {
            self.rshift = false;
        } else if scancode == 0x3A {
            if !self.caps_lock {
                self.caps_lock = true;
                self.caps_lock_toggle = true;
            } else {
                self.caps_lock_toggle = false;
            }
        } else if scancode == 0xBA {
            if self.caps_lock && !self.caps_lock_toggle {
                self.caps_lock = false;
            }
        } else if scancode == 0xE0 {
            let scancode_byte_2 = self.data.read();
            if scancode_byte_2 == 0x38 {
                self.altgr = true;
            } else if scancode_byte_2 == 0xB8 {
                self.altgr = false;
            } else {
                scancode = scancode_byte_2;
            }
        }

        let shift = self.caps_lock != (self.lshift || self.rshift);

        return Some(KeyEvent {
            character: layouts::char_for_scancode(scancode & 0x7F, shift, self.altgr, &self.layout),
            scancode: scancode & 0x7F,
            pressed: scancode < 0x80,
        });
    }

    /// Mouse interrupt
    pub fn mouse_interrupt(&mut self, byte: u8) -> Option<MouseEvent> {
        if self.mouse_i == 0 {
            if byte & 0x8 == 0x8 {
                self.mouse_packet[0] = byte;
                self.mouse_i += 1;
            }
        } else if self.mouse_i == 1 {
            self.mouse_packet[1] = byte;

            self.mouse_i += 1;
        } else {
            self.mouse_packet[2] = byte;

            let left_button = (self.mouse_packet[0] & 1) == 1;
            let right_button = (self.mouse_packet[0] & 2) == 2;
            let middle_button = (self.mouse_packet[0] & 4) == 4;

            let x;
            if (self.mouse_packet[0] & 0x40) != 0x40 && self.mouse_packet[1] != 0 {
                x = (self.mouse_packet[1] as isize -
                     (((self.mouse_packet[0] as isize) << 4) & 0x100)) as i32;
            } else {
                x = 0;
            }

            let y;
            if (self.mouse_packet[0] & 0x80) != 0x80 && self.mouse_packet[2] != 0 {
                y = ((((self.mouse_packet[0] as isize) << 3) & 0x100) -
                     self.mouse_packet[2] as isize) as i32;
            } else {
                y = 0;
            }

            if let Some(mode_info) = unsafe { VBEMODEINFO } {
                self.mouse_x = cmp::max(0, cmp::min(mode_info.xresolution as i32, self.mouse_x + x));
                self.mouse_y = cmp::max(0, cmp::min(mode_info.yresolution as i32, self.mouse_y + y));
            }

            self.mouse_i = 0;

            return Some(MouseEvent {
                x: self.mouse_x,
                y: self.mouse_y,
                left_button: left_button,
                right_button: right_button,
                middle_button: middle_button,
            });
        }

        return None;
    }

    /// Function to change the layout of the keyboard
    pub fn change_layout(&mut self, layout: usize) {
        self.layout = match layout {
            0 => layouts::Layout::English,
            1 => layouts::Layout::French,
            2 => layouts::Layout::German,
            _ => layouts::Layout::English,
        }
    }
}

impl KScheme for Ps2 {
    fn on_irq(&mut self, irq: u8) {
        if irq == 0xC || irq == 0x1 {
            loop {
                let status = self.sts.read();
                if status & 0x21 == 0x21 {
                    let data = self.data.read();
                    if let Some(mouse_event) = self.mouse_interrupt(data) {
                        if unsafe { & *::env().console.get() }.draw {
                            //Ignore mouse event
                        } else {
                            ::env().events.send(mouse_event.to_event(), "Ps2::on_irq mouse");
                        }
                    }
                } else if status & 0x21 == 0x01 {
                    let data = self.data.read();
                    if let Some(key_event) = self.keyboard_interrupt(data) {
                        if unsafe { & *::env().console.get() }.draw {
                            unsafe { &mut *::env().console.get() }.event(key_event.to_event());
                        } else {
                            ::env().events.send(key_event.to_event(), "Ps2::on_irq key");
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }
}
<commit_msg>Ctrl-C, Ctrl-D in VGA console<commit_after>use alloc::boxed::Box;

use collections::String;

use core::cmp;

use common::event::{KeyEvent, MouseEvent};

use drivers::io::{Io, Pio, ReadOnly, WriteOnly};

use graphics::display::VBEMODEINFO;

use fs::KScheme;

use drivers::kb_layouts::layouts;

pub struct Ps2Keyboard<'a> {
    bus: &'a mut Ps2
}

impl<'a> Ps2Keyboard<'a> {
    //TODO: Use result
    fn cmd(&mut self, command: u8) -> u8 {
        self.bus.wait_write();
        self.bus.data.write(command);
        self.bus.wait_read();
        self.bus.data.read()
    }
}

pub struct Ps2Mouse<'a> {
    bus: &'a mut Ps2
}

impl<'a> Ps2Mouse<'a> {
    //TODO: Use result
    fn cmd(&mut self, command: u8) -> u8 {
        self.bus.write(0xD4, command);
        self.bus.wait_read();
        self.bus.data.read()
    }
}

/// PS2
pub struct Ps2 {
    /// The data register
    data: Pio<u8>,
    /// The status register
    sts: ReadOnly<Pio<u8>>,
    /// The command register
    cmd: WriteOnly<Pio<u8>>,
    /// Left shift
    lshift: bool,
    /// Right shift
    rshift: bool,
    /// Caps lock
    caps_lock: bool,
    /// Caps lock toggle
    caps_lock_toggle: bool,
    /// Left control
    lctrl: bool,
    /// AltGr?
    altgr: bool,
    /// The mouse packet
    mouse_packet: [u8; 4],
    /// Mouse packet index
    mouse_i: usize,
    /// Mouse point x
    mouse_x: i32,
    /// Mouse point y
    mouse_y: i32,
    /// Layout for keyboard
    /// Default: English
    layout: layouts::Layout,
}

impl Ps2 {
    /// Create new PS2 data
    pub fn new() -> Box<Self> {
        let mut module = box Ps2 {
            data: Pio::new(0x60),
            sts: ReadOnly::new(Pio::new(0x64)),
            cmd: WriteOnly::new(Pio::new(0x64)),
            lshift: false,
            rshift: false,
            caps_lock: false,
            caps_lock_toggle: false,
            lctrl: false,
            altgr: false,
            mouse_packet: [0; 4],
            mouse_i: 0,
            mouse_x: 0,
            mouse_y: 0,
            layout: layouts::Layout::English,
        };

        module.init();

        module
    }

    fn wait_read(&self) {
        while ! self.sts.readf(1) {}
    }

    fn wait_write(&self) {
        while self.sts.readf(2) {}
    }

    fn cmd(&mut self, command: u8) {
        self.wait_write();
        self.cmd.write(command);
    }

    fn read(&mut self, command: u8) -> u8 {
        self.cmd(command);
        self.wait_read();
        self.data.read()
    }

    fn write(&mut self, command: u8, data: u8) {
        self.cmd(command);
        self.wait_write();
        self.data.write(data);
    }

    fn keyboard<'a>(&'a mut self) -> Ps2Keyboard<'a> {
        Ps2Keyboard {
            bus: self
        }
    }

    fn mouse<'a>(&'a mut self) -> Ps2Mouse<'a> {
        Ps2Mouse {
            bus: self
        }
    }

    fn init(&mut self) {
        while self.sts.readf(1) {
            self.data.read();
        }

        debugln!(" + PS/2");

        // No interrupts, system flag set, clocks enabled, translation enabled
        self.write(0x60, 0b01000100);

        while self.sts.readf(1) {
            debugln!("Extra {}: {:X}", line!(), self.data.read());
        }

        // Enable First Port
        debugln!("   + Keyboard");
        self.cmd(0xAE);

        while self.sts.readf(1) {
            debugln!("Extra {}: {:X}", line!(), self.data.read());
        }

        {
            // Reset
            debug!("     - Reset {:X}", self.keyboard().cmd(0xFF));
            self.wait_read();
            debugln!(", {:X}", self.data.read());

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }

            // Set defaults
            debugln!("     - Set defaults {:X}", self.keyboard().cmd(0xF6));

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }

            // Enable Streaming
            debugln!("     - Enable streaming {:X}", self.keyboard().cmd(0xF4));

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }
        }

        // Enable Second Port
        debugln!("   + PS/2 Mouse");
        self.cmd(0xA8);

        while self.sts.readf(1) {
            debugln!("Extra {}: {:X}", line!(), self.data.read());
        }

        {
            // Reset
            debug!("     - Reset {:X}", self.keyboard().cmd(0xFF));
            self.wait_read();
            debugln!(", {:X}", self.data.read());

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }

            // Set defaults
            debugln!("     - Set defaults {:X}", self.mouse().cmd(0xF6));

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }

            // Enable Streaming
            debugln!("     - Enable streaming {:X}", self.mouse().cmd(0xF4));

            while self.sts.readf(1) {
                debugln!("Extra {}: {:X}", line!(), self.data.read());
            }
        }

        // Key and mouse interrupts, system flag set, clocks enabled, translation enabled
        self.write(0x60, 0b01000111);

        while self.sts.readf(1) {
            debugln!("Extra {}: {:X}", line!(), self.data.read());
        }
    }

    /// Keyboard interrupt
    pub fn keyboard_interrupt(&mut self, mut scancode: u8) -> Option<KeyEvent> {
        if scancode == 0 {
            return None;
        } else if scancode == 0x2A {
            self.lshift = true;
        } else if scancode == 0xAA {
            self.lshift = false;
        } else if scancode == 0x36 {
            self.rshift = true;
        } else if scancode == 0xB6 {
            self.rshift = false;
        } else if scancode == 0x3A {
            if !self.caps_lock {
                self.caps_lock = true;
                self.caps_lock_toggle = true;
            } else {
                self.caps_lock_toggle = false;
            }
        } else if scancode == 0xBA {
            if self.caps_lock && !self.caps_lock_toggle {
                self.caps_lock = false;
            }
        } else if scancode == 0x1D {
            self.lctrl = true;
        } else if scancode == 0x9D {
            self.lctrl = false;
        } else if scancode == 0xE0 {
            let scancode_byte_2 = self.data.read();
            if scancode_byte_2 == 0x38 {
                self.altgr = true;
            } else if scancode_byte_2 == 0xB8 {
                self.altgr = false;
            } else {
                scancode = scancode_byte_2;
            }
        }

        if self.lctrl {
            if scancode == 0x2E {
                let console = unsafe { &mut *::env().console.get() };

                console.write(b"^C\n");
                console.commands.send(String::new(), "Serial Control C");

                return None;
            } else if scancode == 0x20 {
                let console = unsafe { &mut *::env().console.get() };

                console.write(b"^D\n");

                {
                    let contexts = unsafe { &mut *::env().contexts.get() };
                    console.write(format!("Magic CTRL-D {}\n", ::common::time::Duration::monotonic().secs).as_bytes());
                    for context in contexts.iter() {
                        console.write(format!("  PID {}: {}\n", context.pid, context.name).as_bytes());

                        if context.blocked > 0 {
                            console.write(format!("    BLOCKED {}\n", context.blocked).as_bytes());
                        }

                        if let Some(current_syscall) = context.current_syscall {
                            console.write(format!("    SYS {:X}: {} {} {:X} {:X} {:X}\n", current_syscall.0, current_syscall.1, ::syscall::name(current_syscall.1), current_syscall.2, current_syscall.3, current_syscall.4).as_bytes());
                        }
                    }
                }

                return None;
            }
        }

        let shift = self.caps_lock != (self.lshift || self.rshift);

        Some(KeyEvent {
            character: layouts::char_for_scancode(scancode & 0x7F, shift, self.altgr, &self.layout),
            scancode: scancode & 0x7F,
            pressed: scancode < 0x80,
        })
    }

    /// Mouse interrupt
    pub fn mouse_interrupt(&mut self, byte: u8) -> Option<MouseEvent> {
        if self.mouse_i == 0 {
            if byte & 0x8 == 0x8 {
                self.mouse_packet[0] = byte;
                self.mouse_i += 1;
            }
        } else if self.mouse_i == 1 {
            self.mouse_packet[1] = byte;

            self.mouse_i += 1;
        } else {
            self.mouse_packet[2] = byte;

            let left_button = (self.mouse_packet[0] & 1) == 1;
            let right_button = (self.mouse_packet[0] & 2) == 2;
            let middle_button = (self.mouse_packet[0] & 4) == 4;

            let x;
            if (self.mouse_packet[0] & 0x40) != 0x40 && self.mouse_packet[1] != 0 {
                x = (self.mouse_packet[1] as isize -
                     (((self.mouse_packet[0] as isize) << 4) & 0x100)) as i32;
            } else {
                x = 0;
            }

            let y;
            if (self.mouse_packet[0] & 0x80) != 0x80 && self.mouse_packet[2] != 0 {
                y = ((((self.mouse_packet[0] as isize) << 3) & 0x100) -
                     self.mouse_packet[2] as isize) as i32;
            } else {
                y = 0;
            }

            if let Some(mode_info) = unsafe { VBEMODEINFO } {
                self.mouse_x = cmp::max(0, cmp::min(mode_info.xresolution as i32, self.mouse_x + x));
                self.mouse_y = cmp::max(0, cmp::min(mode_info.yresolution as i32, self.mouse_y + y));
            }

            self.mouse_i = 0;

            return Some(MouseEvent {
                x: self.mouse_x,
                y: self.mouse_y,
                left_button: left_button,
                right_button: right_button,
                middle_button: middle_button,
            });
        }

        return None;
    }

    /// Function to change the layout of the keyboard
    pub fn change_layout(&mut self, layout: usize) {
        self.layout = match layout {
            0 => layouts::Layout::English,
            1 => layouts::Layout::French,
            2 => layouts::Layout::German,
            _ => layouts::Layout::English,
        }
    }
}

impl KScheme for Ps2 {
    fn on_irq(&mut self, irq: u8) {
        if irq == 0xC || irq == 0x1 {
            loop {
                let status = self.sts.read();
                if status & 0x21 == 0x21 {
                    let data = self.data.read();
                    if let Some(mouse_event) = self.mouse_interrupt(data) {
                        if unsafe { & *::env().console.get() }.draw {
                            //Ignore mouse event
                        } else {
                            ::env().events.send(mouse_event.to_event(), "Ps2::on_irq mouse");
                        }
                    }
                } else if status & 0x21 == 0x01 {
                    let data = self.data.read();
                    if let Some(key_event) = self.keyboard_interrupt(data) {
                        if unsafe { & *::env().console.get() }.draw {
                            unsafe { &mut *::env().console.get() }.event(key_event.to_event());
                        } else {
                            ::env().events.send(key_event.to_event(), "Ps2::on_irq key");
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;

pub enum ParseError {
    Eof(&'static str),
    NotFound(&'static str),
    Expected(Vec<u8>),
    ExpectedType(&'static str),
    Io(IoError),
    InvalidBodyChar(u8),
    LineTooLong(usize),
    TrailingInput(&'static str, usize),
    InternalError,
    Parse(&'static str, Box<ParseError>),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        match *self {
            ParseError::Eof(ref field) => write!(f, "{} while looking for \"{}\"",
                                                 self.description(), field),
            ParseError::NotFound(ref token) => write!(f, "\"{}\" {}",
                                                      token, self.description()),
            ParseError::Expected(ref bytes) => write!(f, "{}. Expected \"{:?}\"",
                                                      self.description(), bytes),
            ParseError::ExpectedType(ref t) => write!(f, "{}. Expected {}",
                                                      self.description(), t),
            ParseError::Io(ref e) => write!(f, "{}: {}",
                                            self.description(), e),
            ParseError::InvalidBodyChar(ref c) => write!(f, "{}: {} is not 7-bit ASCII",
                                                         self.description(), c),
            ParseError::LineTooLong(ref l) => write!(f, "Line {} is too long", l),
            ParseError::TrailingInput(ref field, ref c) => write!(
                f, "Trailing input at byte {} in {}", c, field),
            ParseError::Parse(ref field, ref inner) => write!(
                f, "{} {}: {}", self.description(), field, inner),
            _ => write!(f, "{}", self.description()),
        }
    }
}

impl fmt::Debug for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        <Self as fmt::Display>::fmt(self, f)
    }
}

impl StdError for ParseError {
    fn description(&self) -> &str
    {
        match *self {
            ParseError::Eof(_) => "End of File",
            ParseError::NotFound(_) => "Not Found",
            ParseError::Expected(_) => "Expectation Failed",
            ParseError::ExpectedType(_) => "Expectation Failed",
            ParseError::Io(_) => "I/O Error",
            ParseError::InvalidBodyChar(_) => "Invalid Body Character",
            ParseError::LineTooLong(_) => "Line too long",
            ParseError::TrailingInput(_,_) => "Trailing input",
            ParseError::InternalError => "Internal error",
            ParseError::Parse(_,_) => "Unable to parse",
        }
    }

    fn cause(&self) -> Option<&StdError>
    {
        match *self {
            ParseError::Io(ref e) => Some(e),
            ParseError::Parse(_, ref e) => Some(e),
            _ => None,
        }
    }
}
<commit_msg>Utilize new dyn operator<commit_after>
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;

pub enum ParseError {
    Eof(&'static str),
    NotFound(&'static str),
    Expected(Vec<u8>),
    ExpectedType(&'static str),
    Io(IoError),
    InvalidBodyChar(u8),
    LineTooLong(usize),
    TrailingInput(&'static str, usize),
    InternalError,
    Parse(&'static str, Box<ParseError>),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        match *self {
            ParseError::Eof(ref field) => write!(f, "{} while looking for \"{}\"",
                                                 self.description(), field),
            ParseError::NotFound(ref token) => write!(f, "\"{}\" {}",
                                                      token, self.description()),
            ParseError::Expected(ref bytes) => write!(f, "{}. Expected \"{:?}\"",
                                                      self.description(), bytes),
            ParseError::ExpectedType(ref t) => write!(f, "{}. Expected {}",
                                                      self.description(), t),
            ParseError::Io(ref e) => write!(f, "{}: {}",
                                            self.description(), e),
            ParseError::InvalidBodyChar(ref c) => write!(f, "{}: {} is not 7-bit ASCII",
                                                         self.description(), c),
            ParseError::LineTooLong(ref l) => write!(f, "Line {} is too long", l),
            ParseError::TrailingInput(ref field, ref c) => write!(
                f, "Trailing input at byte {} in {}", c, field),
            ParseError::Parse(ref field, ref inner) => write!(
                f, "{} {}: {}", self.description(), field, inner),
            _ => write!(f, "{}", self.description()),
        }
    }
}

impl fmt::Debug for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        <Self as fmt::Display>::fmt(self, f)
    }
}

impl StdError for ParseError {
    fn description(&self) -> &str
    {
        match *self {
            ParseError::Eof(_) => "End of File",
            ParseError::NotFound(_) => "Not Found",
            ParseError::Expected(_) => "Expectation Failed",
            ParseError::ExpectedType(_) => "Expectation Failed",
            ParseError::Io(_) => "I/O Error",
            ParseError::InvalidBodyChar(_) => "Invalid Body Character",
            ParseError::LineTooLong(_) => "Line too long",
            ParseError::TrailingInput(_,_) => "Trailing input",
            ParseError::InternalError => "Internal error",
            ParseError::Parse(_,_) => "Unable to parse",
        }
    }

    fn cause(&self) -> Option<&dyn StdError>
    {
        match *self {
            ParseError::Io(ref e) => Some(e),
            ParseError::Parse(_, ref e) => Some(e),
            _ => None,
        }
    }
}
<|endoftext|>