<commit_before>extern crate core_graphics;
extern crate libc;

// TODO(dustin): use only the things i need

use self::core_graphics::display::*;
use self::core_graphics::event::*;
use self::core_graphics::event_source::*;
use self::core_graphics::geometry::*;
use self::libc::*;

use super::{KeyboardControllable, MouseControllable};
use std::mem;

use std::ptr;

// little hack until servo fixed a bug in core_graphics
// https://github.com/servo/core-graphics-rs/issues/70
// https://github.com/servo/core-graphics-rs/pull/71
#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
    fn CGEventCreateMouseEvent(source: CGEventSourceRef,
                               mouseType: FIXMEEventType,
                               mouseCursorPosition: CGPoint,
                               mouseButton: CGMouseButton)
                               -> CGEventRef;

    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    // not present in servo/core-graphics
    fn CGEventCreateScrollWheelEvent(source: CGEventSourceRef,
                                     units: ScrollUnit,
                                     wheelCount: uint32_t,
                                     wheel1: int32_t,
                                     ...)
                                     -> CGEventRef;
}

#[derive(Debug)]
enum FIXMEEventType {
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    MouseMoved = 5,
}

// not present in servo/core-graphics
#[derive(Debug)]
enum ScrollUnit {
    Pixel = 0,
    Line = 1,
}
// hack

/// The main struct for handling the event emitting
pub struct Enigo {
    current_x: i32,
    current_y: i32,
    display_width: usize,
    display_height: usize,
}

impl Enigo {
    /// Constructs a new `Enigo` instance.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// ```
    pub fn new() -> Self {
        let displayID = unsafe { CGMainDisplayID() };
        let width = unsafe { CGDisplayPixelsWide(displayID) };
        let height = unsafe { CGDisplayPixelsHigh(displayID) };

        Enigo {
            current_x: 500,
            current_y: 500,
            display_width: width,
            display_height: height,
        }
    }
}

impl MouseControllable for Enigo {
    fn mouse_move_to(&mut self, x: i32, y: i32) {
        self.current_x = x;
        self.current_y = y;

        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(ptr::null(),
                                                   FIXMEEventType::MouseMoved,
                                                   CGPoint::new(self.current_x as f64,
                                                                self.current_y as f64),
                                                   CGMouseButton::Left);

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    fn mouse_move_relative(&mut self, x: i32, y: i32) {
        let new_x = self.current_x + x;
        let new_y = self.current_y + y;

        if new_x < 0 || new_x as usize > self.display_width || new_y < 0 ||
           new_y as usize > self.display_height {
            return;
        }

        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(ptr::null(),
                                                   FIXMEEventType::MouseMoved,
                                                   CGPoint::new(new_x as f64, new_y as f64),
                                                   CGMouseButton::Left);

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }

        // TODO(dustin): use interior mutability
        self.current_x = new_x;
        self.current_y = new_y;
    }

    // TODO(dustin): use button parameter, current implementation
    // is using the left mouse button every time
    fn mouse_down(&mut self, button: u32) {
        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(ptr::null(),
                                                   FIXMEEventType::LeftMouseDown,
                                                   CGPoint::new(self.current_x as f64,
                                                                self.current_y as f64),
                                                   CGMouseButton::Left);

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    // TODO(dustin): use button parameter, current implementation
    // is using the left mouse button every time
    fn mouse_up(&mut self, button: u32) {
        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(ptr::null(),
                                                   FIXMEEventType::LeftMouseUp,
                                                   CGPoint::new(self.current_x as f64,
                                                                self.current_y as f64),
                                                   CGMouseButton::Left);

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    fn mouse_click(&mut self, button: u32) {
        self.mouse_down(button);
        self.mouse_up(button);
    }

    fn mouse_scroll_x(&mut self, length: i32) {
        let mut scroll_direction = -1; // 1 left -1 right;
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mouse_ev = CGEventCreateScrollWheelEvent(ptr::null(),
                                                             ScrollUnit::Line,
                                                             2, // CGWheelCount 1 = y 2 = xy 3 = xyz
                                                             0,
                                                             scroll_direction);

                CGEventPost(CGEventTapLocation::HID, mouse_ev);
                CFRelease(mem::transmute(mouse_ev));
            }
        }
    }

    fn mouse_scroll_y(&mut self, length: i32) {
        let mut scroll_direction = -1; // 1 left -1 right;
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mouse_ev = CGEventCreateScrollWheelEvent(ptr::null(),
                                                             ScrollUnit::Line,
                                                             1, // CGWheelCount 1 = y 2 = xy 3 = xyz
                                                             scroll_direction);

                CGEventPost(CGEventTapLocation::HID, mouse_ev);
                CFRelease(mem::transmute(mouse_ev));
            }
        }
    }
}

impl KeyboardControllable for Enigo {
    fn key_sequence(&self, sequence: &str) {
        unimplemented!()
        //TODO(dustin): postpone this until it is added in public core_graphics crate. possibly after 0.7.0
        //  let source = CGEventSource::new(CGEventSourceStateID::HIDSystemState).expect("Failed creating event source");
        //  let event = CGEvent::new_keyboard_event(source, 0, true).expect("Failed creating event");
        //  event.set_string(sequence);
        //  event.post(CGEventTapLocation::HID);
    }
}
<commit_msg>fix macos keyboard impl<commit_after>extern crate core_graphics;
extern crate libc;

// TODO(dustin): use only the things i need

use self::core_graphics::display::*;
use self::core_graphics::event::*;
use self::core_graphics::event_source::*;
use self::core_graphics::geometry::*;
use self::libc::*;

use super::{KeyboardControllable, MouseControllable};
use std::mem;

use std::ptr;

// little hack until servo fixed a bug in core_graphics
// https://github.com/servo/core-graphics-rs/issues/70
// https://github.com/servo/core-graphics-rs/pull/71
#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
    fn CGEventCreateMouseEvent(source: CGEventSourceRef,
                               mouseType: FIXMEEventType,
                               mouseCursorPosition: CGPoint,
                               mouseButton: CGMouseButton)
                               -> CGEventRef;

    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    // not present in servo/core-graphics
    fn CGEventCreateScrollWheelEvent(source: CGEventSourceRef,
                                     units: ScrollUnit,
                                     wheelCount: uint32_t,
                                     wheel1: int32_t,
                                     ...)
                                     -> CGEventRef;
}

#[derive(Debug)]
enum FIXMEEventType {
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    MouseMoved = 5,
}

// not present in servo/core-graphics
#[derive(Debug)]
enum ScrollUnit {
    Pixel = 0,
    Line = 1,
}
// hack

/// The main struct for handling the event emitting
pub struct Enigo {
    current_x: i32,
    current_y: i32,
    display_width: usize,
    display_height: usize,
}

impl Enigo {
    /// Constructs a new `Enigo` instance.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// ```
    pub fn new() -> Self {
        let displayID = unsafe { CGMainDisplayID() };
        let width = unsafe { CGDisplayPixelsWide(displayID) };
        let height = unsafe { CGDisplayPixelsHigh(displayID) };

        Enigo {
            current_x: 500,
            current_y: 500,
            display_width: width,
            display_height: height,
        }
    }
}

impl MouseControllable for Enigo {
    fn mouse_move_to(&mut self, x: i32, y: i32) {
        self.current_x = x;
        self.current_y = y;

        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(ptr::null(),
                                                   FIXMEEventType::MouseMoved,
                                                   CGPoint::new(self.current_x as f64,
                                                                self.current_y as f64),
                                                   CGMouseButton::Left);

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    fn mouse_move_relative(&mut self, x: i32, y: i32) {
        let new_x = self.current_x + x;
        let new_y = self.current_y + y;

        if new_x < 0 || new_x as usize > self.display_width || new_y < 0 ||
           new_y as usize > self.display_height {
            return;
        }

        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(ptr::null(),
                                                   FIXMEEventType::MouseMoved,
                                                   CGPoint::new(new_x as f64, new_y as f64),
                                                   CGMouseButton::Left);

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }

        // TODO(dustin): use interior mutability
        self.current_x = new_x;
        self.current_y = new_y;
    }

    // TODO(dustin): use button parameter, current implementation
    // is using the left mouse button every time
    fn mouse_down(&mut self, button: u32) {
        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(ptr::null(),
                                                   FIXMEEventType::LeftMouseDown,
                                                   CGPoint::new(self.current_x as f64,
                                                                self.current_y as f64),
                                                   CGMouseButton::Left);

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    // TODO(dustin): use button parameter, current implementation
    // is using the left mouse button every time
    fn mouse_up(&mut self, button: u32) {
        unsafe {
            let mouse_ev = CGEventCreateMouseEvent(ptr::null(),
                                                   FIXMEEventType::LeftMouseUp,
                                                   CGPoint::new(self.current_x as f64,
                                                                self.current_y as f64),
                                                   CGMouseButton::Left);

            CGEventPost(CGEventTapLocation::HID, mouse_ev);
            CFRelease(mem::transmute(mouse_ev));
        }
    }

    fn mouse_click(&mut self, button: u32) {
        self.mouse_down(button);
        self.mouse_up(button);
    }

    fn mouse_scroll_x(&mut self, length: i32) {
        let mut scroll_direction = -1; // 1 left -1 right;
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mouse_ev = CGEventCreateScrollWheelEvent(ptr::null(),
                                                             ScrollUnit::Line,
                                                             2, // CGWheelCount 1 = y 2 = xy 3 = xyz
                                                             0,
                                                             scroll_direction);

                CGEventPost(CGEventTapLocation::HID, mouse_ev);
                CFRelease(mem::transmute(mouse_ev));
            }
        }
    }

    fn mouse_scroll_y(&mut self, length: i32) {
        let mut scroll_direction = -1; // 1 left -1 right;
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mouse_ev = CGEventCreateScrollWheelEvent(ptr::null(),
                                                             ScrollUnit::Line,
                                                             1, // CGWheelCount 1 = y 2 = xy 3 = xyz
                                                             scroll_direction);

                CGEventPost(CGEventTapLocation::HID, mouse_ev);
                CFRelease(mem::transmute(mouse_ev));
            }
        }
    }
}

impl KeyboardControllable for Enigo {
    fn key_sequence(&mut self, sequence: &str) {
        unimplemented!()
        //TODO(dustin): postpone this until it is added in public core_graphics crate. possibly after 0.7.0
        //  let source = CGEventSource::new(CGEventSourceStateID::HIDSystemState).expect("Failed creating event source");
        //  let event = CGEvent::new_keyboard_event(source, 0, true).expect("Failed creating event");
        //  event.set_string(sequence);
        //  event.post(CGEventTapLocation::HID);
    }
}
<|endoftext|>


<commit_before>use std::convert::{TryFrom, TryInto};
use std::fmt::{Debug, Display, Error, Formatter};
use std::ops::Index;

/// Maximum size of a [`Memory`](struct.Memory.html) block in
/// [`Word`](struct.Word.html)s
///
/// = 2^24
const MAX_MEM_SIZE: u32 = 16_777_216;

#[derive(Clone, Copy, Default)]
pub struct Word {
    // little endian
    val: [u8; 3],
}

impl Word {
    pub fn new() -> Self {
        Word { val: [0; 3] }
    }
}

impl Debug for Word {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.debug_struct("Word")
            .field("val", &format_args!("[{:?}, {:?}, {:?}]",
                                        &self.val[2],
                                        &self.val[1],
                                        &self.val[0]))
            .finish()
    }
}

impl From<Word> for u32 {
    fn from(word: Word) -> u32 {
        word.val[0] as u32
            + ((word.val[1] as u32) << 8)
            + ((word.val[2] as u32) << 16)
    }
}

#[derive(Debug)]
pub struct Memory {
    data: Vec<Word>,
    size: u32,
}

impl Memory {
    /// Creates a new `Memory` block of the given `size`.
    ///
    /// The maximum size of a `Memory` block is
    /// [`MAX_MEM_SIZE`](constant.MAX_MEM_SIZE.html). If `size` is greater
    /// than that, the created `Memory` block will be
    /// [`MAX_MEM_SIZE`](constant.MAX_MEM_SIZE.html) long.
    pub fn new(size: u32) -> Self {
        let size = if size > MAX_MEM_SIZE {
            MAX_MEM_SIZE
        } else {
            size
        };
        Memory { data: vec![Word::default(); size.try_into().unwrap()], size }
    }
}

impl Index<u32> for Memory {
    type Output = Word;

    fn index(&self, i: u32) -> &Self::Output {
        &self.data[usize::try_from(i).unwrap()]
    }
}
<commit_msg>Just use usize for index<commit_after>use std::convert::TryInto;
use std::fmt::{Debug, Display, Error, Formatter};
use std::ops::Index;

/// Maximum size of a [`Memory`](struct.Memory.html) block in
/// [`Word`](struct.Word.html)s
///
/// = 2^24
const MAX_MEM_SIZE: u32 = 16_777_216;

#[derive(Clone, Copy, Default)]
pub struct Word {
    // little endian
    val: [u8; 3],
}

impl Word {
    pub fn new() -> Self {
        Word { val: [0; 3] }
    }
}

impl Debug for Word {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.debug_struct("Word")
            .field("val", &format_args!("[{:?}, {:?}, {:?}]",
                                        &self.val[2],
                                        &self.val[1],
                                        &self.val[0]))
            .finish()
    }
}

impl From<Word> for u32 {
    fn from(word: Word) -> u32 {
        word.val[0] as u32
            + ((word.val[1] as u32) << 8)
            + ((word.val[2] as u32) << 16)
    }
}

#[derive(Debug)]
pub struct Memory {
    data: Vec<Word>,
    size: u32,
}

impl Memory {
    /// Creates a new `Memory` block of the given `size`.
    ///
    /// The maximum size of a `Memory` block is
    /// [`MAX_MEM_SIZE`](constant.MAX_MEM_SIZE.html). If `size` is greater
    /// than that, the created `Memory` block will be
    /// [`MAX_MEM_SIZE`](constant.MAX_MEM_SIZE.html) long.
    pub fn new(size: u32) -> Self {
        let size = if size > MAX_MEM_SIZE {
            MAX_MEM_SIZE
        } else {
            size
        };
        Memory { data: vec![Word::default(); size.try_into().unwrap()], size }
    }
}

impl Index<usize> for Memory {
    type Output = Word;

    fn index(&self, i: usize) -> &Self::Output {
        &self.data[i]
    }
}
<|endoftext|>


<commit_before>//! A lazily populated index for looking up entities by name.
#![allow(dead_code)]

use crate::ir::cc::{Ident, Path};
use clang::{self, Entity, EntityKind};
use std::collections::HashMap;
use thiserror::Error;

/// Represents errors which can occur while looking up entities in the index.
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum LookupError {
    #[error("couldn't find `{0}`")]
    NotFound(Path),
}

/// The result of a lookup operation.
type Result<T> = std::result::Result<T, LookupError>;

/// An ID assigned to a `Path` in the index.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NodeId(u32);

impl NodeId {
    #[inline(always)]
    fn from_usize(n: usize) -> NodeId {
        NodeId(n as u32)
    }
    #[allow(dead_code)]
    #[inline(always)]
    fn as_usize(&self) -> usize {
        self.0 as usize
    }
}

/// An index `Node` is the entity or set of entities referred to by a `Path`.
///
/// For example, `std` and `std::vector` are both nodes.
///
/// Nodes may contain children, and they may be represented by multiple
/// entities. Namespaces, for example, can have many AST entities associated
/// with them. Template specializations are another example.
#[derive(Debug, Default)]
pub struct Node<'tu> {
    //kind: EntityKind,
    entities: Vec<Entity<'tu>>,
    items: Option<HashMap<Ident, NodeId>>,
    inline_items: Vec<NodeId>,
}
impl<'tu> Node<'tu> {
    fn items_mut(&mut self) -> &mut HashMap<Ident, NodeId> {
        self.items.as_mut().unwrap()
    }
}

/// A lazily populated index for looking up `Node`s by name.
pub struct Index<'tu> {
    nodes: Vec<Node<'tu>>,
}
impl<'tu> Index<'tu> {
    /// Creates an index from the given TranslationUnit.
    pub fn new(file: &'tu clang::TranslationUnit<'_>) -> Index<'tu> {
        let entity = file.get_entity();
        let file_node = Node {
            //kind: entity.get_kind(),
            entities: vec![entity],
            items: None,
            inline_items: vec![],
        };
        Index {
            nodes: vec![file_node],
        }
    }

    #[inline(always)]
    pub fn node(&self, id: NodeId) -> &Node<'tu> {
        &self.nodes[id.0 as usize]
    }

    #[inline(always)]
    fn node_mut(&mut self, id: NodeId) -> &mut Node<'tu> {
        &mut self.nodes[id.0 as usize]
    }

    /// Returns the `Node` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub fn lookup(&mut self, path: &Path) -> Result<&Node<'tu>> {
        self.lookup_id(&path).map(move |id| self.node(id))
    }

    /// Returns the `NodeId` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub fn lookup_id(&mut self, path: &Path) -> Result<NodeId> {
        let mut cur = NodeId(0);
        for (idx, name) in path.iter().enumerate() {
            cur = match self.child_id_of(cur, name)? {
                Some(child) => child,
                None => {
                    let err_path = path.iter().take(idx + 1).cloned().collect::<Path>();
                    return Err(LookupError::NotFound(err_path));
                }
            };
        }
        Ok(cur)
    }

    /// Returns the child named `child` of the given `node`.
    #[allow(dead_code)]
    pub fn child_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<&Node>> {
        self.child_id_of(node, child)
            .map(|opt| opt.map(move |id| self.node(id)))
    }

    /// Returns the `NodeId` of the child named `child` of the given `node`.
    pub fn child_id_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<NodeId>> {
        if self.node(node).items.is_none() {
            self.expand(node)?;
        }
        let children = self.node(node).items.as_ref().unwrap();
        Ok(children.get(child).copied())
    }

    fn expand(&mut self, node: NodeId) -> Result<()> {
        self.node_mut(node).items = Some(HashMap::new());
        let num_entities = self.node(node).entities.len();
        for ent_idx in 0..num_entities {
            let ent = self.node(node).entities[ent_idx];

            // TODO: Looking up children of unsupported entity types will result
            // in confusing NotFound errors.
            if should_expand(ent) {
                self.populate_children(node, ent)?;
            }
        }
        Ok(())
    }

    fn populate_children(&mut self, parent: NodeId, ent: Entity<'tu>) -> Result<()> {
        for child in ent.get_children() {
            let name = match child.get_name() {
                Some(name) => Ident::from(name),
                None => continue,
            };
            let child_id = self.get_or_insert_child(parent, name);
            self.node_mut(child_id).entities.push(child);

            if should_inline(child) {
                //self.node_mut(parent).inline_items.push(child_id);
                // Populate the parent with all of this node's children.
                self.populate_children(parent, child)?;
            }
        }
        Ok(())
    }

    fn get_or_insert_child(&mut self, parent: NodeId, child: Ident) -> NodeId {
        let next_id = self.next_node_id();
        let child_id = *self
            .node_mut(parent)
            .items_mut()
            .entry(child)
            .or_insert(next_id);
        if child_id == next_id {
            self.nodes.push(Default::default());
        }
        child_id
    }

    #[inline(always)]
    fn next_node_id(&self) -> NodeId {
        NodeId::from_usize(self.nodes.len())
    }
}

fn should_expand(ent: Entity<'_>) -> bool {
    use EntityKind::*;
    match ent.get_kind() {
        TranslationUnit => true,
        Namespace | StructDecl | ClassDecl | ClassTemplate => true,
        _ => false,
    }
}

fn should_inline(ent: Entity<'_>) -> bool {
    use EntityKind::*;
    match ent.get_kind() {
        Namespace => false,
        EnumDecl => !ent.is_scoped(),
        _ => false,
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::test_util;

    #[test]
    fn inline_namespace() {
        let clang = &test_util::CLANG;
        let index = clang::Index::new(&clang, true, true);
        let file = cpp_parse!(&index, {
            namespace std {
                inline namespace __1 {
                    struct vector {};
                }
                namespace notinline {
                    struct foo {};
                }
            }
        });
        let mut index = Index::new(&file);
        assert!(index.lookup(&Path::from("std::__1::vector")).is_ok());
        assert!(index.lookup(&Path::from("std::notinline::foo")).is_ok());
        assert!(index.lookup(&Path::from("std::foo")).is_err());
    }

    #[test]
    fn paths() {
        assert_eq!(
            Path::from("::std::stuff::basic_iterator"),
            Path::from("std::stuff::basic_iterator")
        );
        assert_eq!(
            Path::from("::std::vector<bool>::basic_iterator")
                .iter()
                .cloned()
                .collect::<Vec<_>>(),
            ["std", "vector<bool>", "basic_iterator"]
                .into_iter()
                .copied()
                .map(Ident::from)
                .collect::<Vec<_>>()
        );
    }
}
<commit_msg>Fix warning<commit_after>//! A lazily populated index for looking up entities by name.
#![allow(dead_code)]

use crate::ir::cc::{Ident, Path};
use clang::{self, Entity, EntityKind};
use std::collections::HashMap;
use thiserror::Error;

/// Represents errors which can occur while looking up entities in the index.
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum LookupError {
    #[error("couldn't find `{0}`")]
    NotFound(Path),
}

/// The result of a lookup operation.
type Result<T> = std::result::Result<T, LookupError>;

/// An ID assigned to a `Path` in the index.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NodeId(u32);

impl NodeId {
    #[inline(always)]
    fn from_usize(n: usize) -> NodeId {
        NodeId(n as u32)
    }
    #[allow(dead_code)]
    #[inline(always)]
    fn as_usize(&self) -> usize {
        self.0 as usize
    }
}

/// An index `Node` is the entity or set of entities referred to by a `Path`.
///
/// For example, `std` and `std::vector` are both nodes.
///
/// Nodes may contain children, and they may be represented by multiple
/// entities. Namespaces, for example, can have many AST entities associated
/// with them. Template specializations are another example.
#[derive(Debug, Default)]
pub struct Node<'tu> {
    //kind: EntityKind,
    entities: Vec<Entity<'tu>>,
    items: Option<HashMap<Ident, NodeId>>,
    inline_items: Vec<NodeId>,
}
impl<'tu> Node<'tu> {
    fn items_mut(&mut self) -> &mut HashMap<Ident, NodeId> {
        self.items.as_mut().unwrap()
    }
}

/// A lazily populated index for looking up `Node`s by name.
pub struct Index<'tu> {
    nodes: Vec<Node<'tu>>,
}
impl<'tu> Index<'tu> {
    /// Creates an index from the given TranslationUnit.
    pub fn new(file: &'tu clang::TranslationUnit<'_>) -> Index<'tu> {
        let entity = file.get_entity();
        let file_node = Node {
            //kind: entity.get_kind(),
            entities: vec![entity],
            items: None,
            inline_items: vec![],
        };
        Index {
            nodes: vec![file_node],
        }
    }

    #[inline(always)]
    pub fn node(&self, id: NodeId) -> &Node<'tu> {
        &self.nodes[id.0 as usize]
    }

    #[inline(always)]
    fn node_mut(&mut self, id: NodeId) -> &mut Node<'tu> {
        &mut self.nodes[id.0 as usize]
    }

    /// Returns the `Node` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub fn lookup(&mut self, path: &Path) -> Result<&Node<'tu>> {
        self.lookup_id(&path).map(move |id| self.node(id))
    }

    /// Returns the `NodeId` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub fn lookup_id(&mut self, path: &Path) -> Result<NodeId> {
        let mut cur = NodeId(0);
        for (idx, name) in path.iter().enumerate() {
            cur = match self.child_id_of(cur, name)? {
                Some(child) => child,
                None => {
                    let err_path = path.iter().take(idx + 1).cloned().collect::<Path>();
                    return Err(LookupError::NotFound(err_path));
                }
            };
        }
        Ok(cur)
    }

    /// Returns the child named `child` of the given `node`.
    #[allow(dead_code)]
    pub fn child_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<&Node>> {
        self.child_id_of(node, child)
            .map(|opt| opt.map(move |id| self.node(id)))
    }

    /// Returns the `NodeId` of the child named `child` of the given `node`.
    pub fn child_id_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<NodeId>> {
        if self.node(node).items.is_none() {
            self.expand(node)?;
        }
        let children = self.node(node).items.as_ref().unwrap();
        Ok(children.get(child).copied())
    }

    fn expand(&mut self, node: NodeId) -> Result<()> {
        self.node_mut(node).items = Some(HashMap::new());
        let num_entities = self.node(node).entities.len();
        for ent_idx in 0..num_entities {
            let ent = self.node(node).entities[ent_idx];

            // TODO: Looking up children of unsupported entity types will result
            // in confusing NotFound errors.
            if should_expand(ent) {
                self.populate_children(node, ent)?;
            }
        }
        Ok(())
    }

    fn populate_children(&mut self, parent: NodeId, ent: Entity<'tu>) -> Result<()> {
        for child in ent.get_children() {
            let name = match child.get_name() {
                Some(name) => Ident::from(name),
                None => continue,
            };
            let child_id = self.get_or_insert_child(parent, name);
            self.node_mut(child_id).entities.push(child);

            if should_inline(child) {
                //self.node_mut(parent).inline_items.push(child_id);
                // Populate the parent with all of this node's children.
                self.populate_children(parent, child)?;
            }
        }
        Ok(())
    }

    fn get_or_insert_child(&mut self, parent: NodeId, child: Ident) -> NodeId {
        let next_id = self.next_node_id();
        let child_id = *self
            .node_mut(parent)
            .items_mut()
            .entry(child)
            .or_insert(next_id);
        if child_id == next_id {
            self.nodes.push(Default::default());
        }
        child_id
    }

    #[inline(always)]
    fn next_node_id(&self) -> NodeId {
        NodeId::from_usize(self.nodes.len())
    }
}

fn should_expand(ent: Entity<'_>) -> bool {
    use EntityKind::*;
    match ent.get_kind() {
        TranslationUnit => true,
        Namespace | StructDecl | ClassDecl | ClassTemplate => true,
        _ => false,
    }
}

fn should_inline(ent: Entity<'_>) -> bool {
    use EntityKind::*;
    match ent.get_kind() {
        Namespace => false,
        EnumDecl => !ent.is_scoped(),
        _ => false,
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::test_util;

    #[test]
    fn inline_namespace() {
        let clang = &test_util::CLANG;
        let index = clang::Index::new(&clang, true, true);
        let file = cpp_parse!(&index, {
            namespace std {
                inline namespace __1 {
                    struct vector {};
                }
                namespace notinline {
                    struct foo {};
                }
            }
        });
        let mut index = Index::new(&file);
        assert!(index.lookup(&Path::from("std::__1::vector")).is_ok());
        assert!(index.lookup(&Path::from("std::notinline::foo")).is_ok());
        assert!(index.lookup(&Path::from("std::foo")).is_err());
    }

    #[test]
    fn paths() {
        assert_eq!(
            Path::from("::std::stuff::basic_iterator"),
            Path::from("std::stuff::basic_iterator")
        );
        assert_eq!(
            Path::from("::std::vector<bool>::basic_iterator")
                .iter()
                .cloned()
                .collect::<Vec<_>>(),
            ["std", "vector<bool>", "basic_iterator"]
                .iter()
                .copied()
                .map(Ident::from)
                .collect::<Vec<_>>()
        );
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;
use std::iter::Peekable;
use errors::{CalcrResult, CalcrError};
use token::Token;
use token::TokVal::*;
use token::OpKind::*;
use token::DelimKind::*;

pub fn lex_equation(eq: &String) -> CalcrResult<Vec<Token>> {
    let mut lexer = Lexer {
        pos: 0,
        iter: eq.chars().peekable(),
    };
    lexer.lex_expression()
}

pub struct Lexer<'a> {
    pos: usize,
    iter: Peekable<Chars<'a>>,
}

impl<'a> Lexer<'a> {
    pub fn lex_expression(&mut self) -> CalcrResult<Vec<Token>> {
        let mut out = Vec::new();
        loop {
            self.consume_whitespace();
            let tok = match self.peek_char() {
                Some(ch) if ch.is_numeric() => try!(self.lex_number()),
                Some(ch) if ch.is_alphabetic() => try!(self.lex_name()),
                Some(_) => try!(self.lex_single_char()),
                None => break,
            };
            out.push(tok);
        }
        Ok(out)
    }

    fn lex_number(&mut self) -> CalcrResult<Token> {
        let num_str = self.consume_while(|ch| ch.is_numeric() || ch == '.');
        if let Ok(num) = num_str.parse::<f64>() {
            Ok(Token {
                val: Num(num),
                span: (self.pos - num_str.len(), self.pos),
            })
        } else {
            Err(CalcrError {
                desc: format!("Invalid number: {}", num_str),
                span: Some((self.pos - num_str.len(), self.pos)),
            })
        }
    }

    fn lex_name(&mut self) -> CalcrResult<Token> {
        let name_str = self.consume_while(|ch| ch.is_alphabetic() || ch.is_numeric());
        let len = name_str.chars().count();
        Ok(Token {
            val: Name(name_str),
            span: (self.pos - len, self.pos),
        })
    }

    fn lex_single_char(&mut self) -> CalcrResult<Token> {
        let val = match self.consume_char() {
            '+' => Op(Plus),
            '-' => Op(Minus),
            '*' => Op(Mult),
            '/' => Op(Div),
            '^' => Op(Pow),
            '!' => Op(Fact),
            '=' => Op(Assign),
            '√' => Name("sqrt".to_string()),
            '(' => OpenDelim(Paren),
            '[' => OpenDelim(Bracket),
            '{' => OpenDelim(Brace),
            ')' => CloseDelim(Paren),
            ']' => CloseDelim(Bracket),
            '}' => CloseDelim(Brace),
            '|' => AbsDelim,
            ch => return Err(CalcrError {
                desc: format!("Invalid char: {}", ch),
                span: Some((self.pos - 1, self.pos)),
            }),
        };
        Ok(Token {
            val: val,
            span: (self.pos - 1, self.pos),
        })
    }

    /// Peeks at the next `char` and returns `Some` if one was found, or `None` if none are left
    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().map(|ch| *ch)
    }

    /// Consumes a `char` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more chars to consume
    fn consume_char(&mut self) -> char {
        let ch = self.iter.next();
        self.pos += 1;
        ch.unwrap().to_lowercase().next().unwrap()
    }

    /// Consumes `char`s long as `pred` returns true and we are not eof
    ///
    /// The `char`s are returned as a `String`. Note that unlike `consume_char` this function will
    /// not panic.
    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        loop {
            match self.peek_char() {
                Some(ch) if pred(ch) => out.push(self.consume_char()),
                _ => break,
            }
        }
        out
    }

    /// Consumes any current whitespace
    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }
}

#[cfg(test)]
mod tests {
    use super::lex_equation;
    use token::Token;
    use token::TokVal::*;
    use ast::OpKind::*;

    #[test]
    fn empty() {
        let eq = "".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!()));
    }

    #[test]
    fn single_char() {
        let eq = "2".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Num(2.0), span: (0, 1) })));
    }

    #[test]
    fn utf8() {
        let eq = "π𐍈".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Name(eq), span: (0, 2) })));
    }

    #[test]
    fn ops() {
        let eq = "+-*/!^".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Op(Plus), span: (0,1) },
                                 Token { val: Op(Minus), span: (1,2) },
                                 Token { val: Op(Mult), span: (2,3) },
                                 Token { val: Op(Div), span: (3,4) },
                                 Token { val: Op(Fact), span: (4,5) },
                                 Token { val: Op(Pow), span: (5,6) })));
    }

    #[test]
    fn delims() {
        let eq = "|()[]".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: AbsDelim, span: (0,1) },
                                 Token { val: ParenOpen, span: (1,2) },
                                 Token { val: ParenClose, span: (2,3) },
                                 Token { val: ParenOpen, span: (3,4) },
                                 Token { val: ParenClose, span: (4,5) })));
    }

    #[test]
    fn sqrt_single_char() {
        let eq = "√".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Name("sqrt".to_string()), span: (0,1) })));
    }

    #[test]
    fn invalid_char() {
        let eq = "?".to_string();
        let err = lex_equation(&eq);
        assert!(err.is_err());
    }
}<commit_msg>Add lexer test for the new delimiters<commit_after>use std::str::Chars;
use std::iter::Peekable;
use errors::{CalcrResult, CalcrError};
use token::Token;
use token::TokVal::*;
use token::OpKind::*;
use token::DelimKind::*;

pub fn lex_equation(eq: &String) -> CalcrResult<Vec<Token>> {
    let mut lexer = Lexer {
        pos: 0,
        iter: eq.chars().peekable(),
    };
    lexer.lex_expression()
}

pub struct Lexer<'a> {
    pos: usize,
    iter: Peekable<Chars<'a>>,
}

impl<'a> Lexer<'a> {
    pub fn lex_expression(&mut self) -> CalcrResult<Vec<Token>> {
        let mut out = Vec::new();
        loop {
            self.consume_whitespace();
            let tok = match self.peek_char() {
                Some(ch) if ch.is_numeric() => try!(self.lex_number()),
                Some(ch) if ch.is_alphabetic() => try!(self.lex_name()),
                Some(_) => try!(self.lex_single_char()),
                None => break,
            };
            out.push(tok);
        }
        Ok(out)
    }

    fn lex_number(&mut self) -> CalcrResult<Token> {
        let num_str = self.consume_while(|ch| ch.is_numeric() || ch == '.');
        if let Ok(num) = num_str.parse::<f64>() {
            Ok(Token {
                val: Num(num),
                span: (self.pos - num_str.len(), self.pos),
            })
        } else {
            Err(CalcrError {
                desc: format!("Invalid number: {}", num_str),
                span: Some((self.pos - num_str.len(), self.pos)),
            })
        }
    }

    fn lex_name(&mut self) -> CalcrResult<Token> {
        let name_str = self.consume_while(|ch| ch.is_alphabetic() || ch.is_numeric());
        let len = name_str.chars().count();
        Ok(Token {
            val: Name(name_str),
            span: (self.pos - len, self.pos),
        })
    }

    fn lex_single_char(&mut self) -> CalcrResult<Token> {
        let val = match self.consume_char() {
            '+' => Op(Plus),
            '-' => Op(Minus),
            '*' => Op(Mult),
            '/' => Op(Div),
            '^' => Op(Pow),
            '!' => Op(Fact),
            '=' => Op(Assign),
            '√' => Name("sqrt".to_string()),
            '(' => OpenDelim(Paren),
            '[' => OpenDelim(Bracket),
            '{' => OpenDelim(Brace),
            ')' => CloseDelim(Paren),
            ']' => CloseDelim(Bracket),
            '}' => CloseDelim(Brace),
            '|' => AbsDelim,
            ch => return Err(CalcrError {
                desc: format!("Invalid char: {}", ch),
                span: Some((self.pos - 1, self.pos)),
            }),
        };
        Ok(Token {
            val: val,
            span: (self.pos - 1, self.pos),
        })
    }

    /// Peeks at the next `char` and returns `Some` if one was found, or `None` if none are left
    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().map(|ch| *ch)
    }

    /// Consumes a `char` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more chars to consume
    fn consume_char(&mut self) -> char {
        let ch = self.iter.next();
        self.pos += 1;
        ch.unwrap().to_lowercase().next().unwrap()
    }

    /// Consumes `char`s long as `pred` returns true and we are not eof
    ///
    /// The `char`s are returned as a `String`. Note that unlike `consume_char` this function will
    /// not panic.
    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        loop {
            match self.peek_char() {
                Some(ch) if pred(ch) => out.push(self.consume_char()),
                _ => break,
            }
        }
        out
    }

    /// Consumes any current whitespace
    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }
}

#[cfg(test)]
mod tests {
    use super::lex_equation;
    use token::Token;
    use token::TokVal::*;
    use token::OpKind::*;
    use token::DelimKind::*;

    #[test]
    fn empty() {
        let eq = "".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!()));
    }

    #[test]
    fn single_char() {
        let eq = "2".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Num(2.0), span: (0, 1) })));
    }

    #[test]
    fn utf8() {
        let eq = "π𐍈".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Name(eq), span: (0, 2) })));
    }

    #[test]
    fn ops() {
        let eq = "+-*/!^".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Op(Plus), span: (0,1) },
                                 Token { val: Op(Minus), span: (1,2) },
                                 Token { val: Op(Mult), span: (2,3) },
                                 Token { val: Op(Div), span: (3,4) },
                                 Token { val: Op(Fact), span: (4,5) },
                                 Token { val: Op(Pow), span: (5,6) })));
    }

    #[test]
    fn delims() {
        let eq = "|()[]{}".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: AbsDelim, span: (0,1) },
                                 Token { val: OpenDelim(Paren), span: (1,2) },
                                 Token { val: CloseDelim(Paren), span: (2,3) },
                                 Token { val: OpenDelim(Bracket), span: (3,4) },
                                 Token { val: CloseDelim(Bracket), span: (4,5) },
                                 Token { val: OpenDelim(Brace), span: (5,6) },
                                 Token { val: CloseDelim(Brace), span: (6,7) })));
    }

    #[test]
    fn sqrt_single_char() {
        let eq = "√".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Name("sqrt".to_string()), span: (0,1) })));
    }

    #[test]
    fn invalid_char() {
        let eq = "?".to_string();
        let err = lex_equation(&eq);
        assert!(err.is_err());
    }
}<|endoftext|>


<commit_before>
#[macro_export]
macro_rules! ice {
    () => ({
        ice!("ICE: Please report an issue at https://github.com/gluon-lang/gluon/issues")
    });
    ($msg:expr) => ({
        panic!(concat!($msg, ". Please report an issue at https://github.com/gluon-lang/gluon/issues"))
    });
    ($fmt:expr, $($arg:tt)+) => ({
        panic!(concat!($fmt, ". Please report an issue at https://github.com/gluon-lang/gluon/issues"), $($arg)+)
    });
}
<commit_msg>fix(base): parameterless ice! macro.<commit_after>
#[macro_export]
macro_rules! ice {
    () => ({
        panic!("ICE: Please report an issue at https://github.com/gluon-lang/gluon/issues")
    });
    ($msg:expr) => ({
        panic!(concat!($msg, ". Please report an issue at https://github.com/gluon-lang/gluon/issues"))
    });
    ($fmt:expr, $($arg:tt)+) => ({
        panic!(concat!($fmt, ". Please report an issue at https://github.com/gluon-lang/gluon/issues"), $($arg)+)
    });
}
<|endoftext|>


<commit_before>
mod_interface::mod_interface!
{
  #[ cfg( feature = "impls_index" ) ]
  #[ doc( inline ) ]
  prelude use ::impls_index::prelude::*;
  #[ cfg( feature = "mod_interface" ) ]
  #[ doc( inline ) ]
  prelude use ::mod_interface::prelude::*;

  prelude use ::mod_interface::prelude::mod_interface;

  #[ cfg( feature = "for_each" ) ]
  #[ doc( inline ) ]
  prelude use ::for_each::prelude::*;
  #[ cfg( any( feature = "options", feature = "meta_options" ) ) ]
  #[ doc( inline ) ]
  prelude use ::woptions::prelude::*;
  #[ cfg( any( feature = "former", feature = "meta_former" ) ) ]
  #[ doc( inline ) ]
  prelude use ::former::prelude::*;
  #[ cfg( feature = "collection_make" ) ]
  #[ doc( inline ) ]
  prelude use ::literally::*;
}
<commit_msg>Fix exports of module `meta_tools`, export aliases<commit_after>
mod_interface::mod_interface!
{
  #[ cfg( feature = "impls_index" ) ]
  #[ doc( inline ) ]
  prelude use ::impls_index::prelude::*;
  #[ cfg( feature = "mod_interface" ) ]
  #[ doc( inline ) ]
  prelude use ::mod_interface::prelude::*;

  prelude use ::mod_interface::prelude::mod_interface;

  #[ cfg( feature = "for_each" ) ]
  #[ doc( inline ) ]
  prelude use ::for_each::prelude::*;
  #[ cfg( any( feature = "options", feature = "meta_options" ) ) ]
  #[ doc( inline ) ]
  prelude use ::woptions::prelude::*;
  #[ cfg( any( feature = "options", feature = "meta_options" ) ) ]
  #[ doc( inline ) ]
  prelude use ::woptions as options;
  #[ cfg( any( feature = "former", feature = "meta_former" ) ) ]
  #[ doc( inline ) ]
  prelude use ::former::prelude::*;
  #[ cfg( any( feature = "former", feature = "meta_former" ) ) ]
  #[ doc( inline ) ]
  prelude use ::former as former;
  #[ cfg( feature = "collection_make" ) ]
  #[ doc( inline ) ]
  prelude use ::literally::*;
}
<|endoftext|>


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

#![allow(dead_code)]

use std::io;
use std::result;
use std::time::Duration;

use libc;

pub use libc::{epoll_event, EPOLLERR, EPOLLET, EPOLLIN, EPOLLONESHOT, EPOLLOUT, EPOLLPRI};

pub type Result<T> = result::Result<T, io::Error>;

// We're using EventFd to wake up another thread
// that's waiting for epoll_wait() to return.
#[derive(Debug)]
pub struct EventFd {
    fd: i32,
}

impl EventFd {
    pub fn new() -> Result<EventFd> {
        Ok(EventFd {
            fd: parse_retval!(unsafe {
                libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_SEMAPHORE)
            })?,
        })
    }

    pub fn notify(&self) -> Result<()> {
        let buffer: u64 = 1;

        parse_retval!(unsafe {
            libc::write(self.fd, &buffer as *const u64 as *const libc::c_void, 8)
        })?;

        Ok(())
    }

    pub fn fd(&self) -> i32 {
        self.fd
    }
}

impl Drop for EventFd {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}

#[derive(Debug)]
pub struct Epoll {
    fd: libc::c_int,
}

impl Epoll {
    pub fn new() -> Result<Epoll> {
        Ok(Epoll {
            fd: parse_retval!(unsafe { libc::epoll_create1(0) })?,
        })
    }

    pub fn add(&self, fd: i32, id: u64, event_mask: i32) -> Result<()> {
        let mut event = libc::epoll_event {
            events: event_mask as u32,
            u64: id as u64,
        };

        parse_retval!(unsafe { libc::epoll_ctl(self.fd, libc::EPOLL_CTL_ADD, fd, &mut event) })?;

        Ok(())
    }

    pub fn modify(&self, fd: i32, id: u64, event_mask: i32) -> Result<()> {
        let mut event = libc::epoll_event {
            events: event_mask as u32,
            u64: id as u64,
        };

        parse_retval!(unsafe { libc::epoll_ctl(self.fd, libc::EPOLL_CTL_MOD, fd, &mut event) })?;

        Ok(())
    }

    pub fn delete(&self, fd: i32) -> Result<()> {
        let mut event = libc::epoll_event { events: 0, u64: 0 };

        parse_retval!(unsafe { libc::epoll_ctl(self.fd, libc::EPOLL_CTL_DEL, fd, &mut event) })?;

        Ok(())
    }

    pub fn wait(
        &self,
        events: &mut [libc::epoll_event],
        timeout: Option<Duration>,
    ) -> Result<usize> {
        if events.is_empty() {
            return Ok(0);
        }

        let timeout: i32 = if let Some(duration) = timeout {
            (duration.as_secs() * 1_000) as i32 + duration.subsec_millis() as i32
        } else {
            -1
        };

        Ok(parse_retval!(unsafe {
            libc::epoll_wait(self.fd, events.as_mut_ptr(), events.len() as i32, timeout)
        })? as usize)
    }
}

impl Drop for Epoll {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}
<commit_msg>Cast to `c_int` instead of `i32`.<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#![allow(dead_code)]

use std::io;
use std::result;
use std::time::Duration;

use libc;
use libc::c_int;

pub use libc::{epoll_event, EPOLLERR, EPOLLET, EPOLLIN, EPOLLONESHOT, EPOLLOUT, EPOLLPRI};

pub type Result<T> = result::Result<T, io::Error>;

// We're using EventFd to wake up another thread
// that's waiting for epoll_wait() to return.
#[derive(Debug)]
pub struct EventFd {
    fd: i32,
}

impl EventFd {
    pub fn new() -> Result<EventFd> {
        Ok(EventFd {
            fd: parse_retval!(unsafe {
                libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_SEMAPHORE)
            })?,
        })
    }

    pub fn notify(&self) -> Result<()> {
        let buffer: u64 = 1;

        parse_retval!(unsafe {
            libc::write(self.fd, &buffer as *const u64 as *const libc::c_void, 8)
        })?;

        Ok(())
    }

    pub fn fd(&self) -> i32 {
        self.fd
    }
}

impl Drop for EventFd {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}

#[derive(Debug)]
pub struct Epoll {
    fd: libc::c_int,
}

impl Epoll {
    pub fn new() -> Result<Epoll> {
        Ok(Epoll {
            fd: parse_retval!(unsafe { libc::epoll_create1(0) })?,
        })
    }

    pub fn add(&self, fd: i32, id: u64, event_mask: i32) -> Result<()> {
        let mut event = libc::epoll_event {
            events: event_mask as u32,
            u64: id as u64,
        };

        parse_retval!(unsafe { libc::epoll_ctl(self.fd, libc::EPOLL_CTL_ADD, fd, &mut event) })?;

        Ok(())
    }

    pub fn modify(&self, fd: i32, id: u64, event_mask: i32) -> Result<()> {
        let mut event = libc::epoll_event {
            events: event_mask as u32,
            u64: id as u64,
        };

        parse_retval!(unsafe { libc::epoll_ctl(self.fd, libc::EPOLL_CTL_MOD, fd, &mut event) })?;

        Ok(())
    }

    pub fn delete(&self, fd: i32) -> Result<()> {
        let mut event = libc::epoll_event { events: 0, u64: 0 };

        parse_retval!(unsafe { libc::epoll_ctl(self.fd, libc::EPOLL_CTL_DEL, fd, &mut event) })?;

        Ok(())
    }

    pub fn wait(
        &self,
        events: &mut [libc::epoll_event],
        timeout: Option<Duration>,
    ) -> Result<usize> {
        if events.is_empty() {
            return Ok(0);
        }

        let timeout = if let Some(duration) = timeout {
            (duration.as_secs() * 1_000 + duration.subsec_millis() as u64) as c_int
        } else {
            -1
        };

        Ok(parse_retval!(unsafe {
            libc::epoll_wait(self.fd, events.as_mut_ptr(), events.len() as c_int, timeout)
        })? as usize)
    }
}

impl Drop for Epoll {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}
<|endoftext|>


<commit_before>//! Headers container, and common header fields.
//!
//! hyper has the opinion that Headers should be strongly-typed, because that's
//! why we're using Rust in the first place. To set or get any header, an object
//! must implement the `Header` trait from this module. Several common headers
//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
use std::ascii::OwnedAsciiExt;
use std::char::is_lowercase;
use std::fmt::{mod, Show};
use std::intrinsics::TypeId;
use std::mem::{transmute, transmute_copy};
use std::raw::TraitObject;
use std::str::{from_utf8, SendStr, Slice, Owned};
use std::string::raw;
use std::collections::hashmap::{HashMap, Entries};

use uany::UncheckedAnyDowncast;

use http::read_header;
use {HttpResult};

/// Common Headers
pub mod common;

/// A trait for any object that will represent a header field and value.
pub trait Header: 'static {
    /// Returns the name of the header field this belongs to.
    ///
    /// The market `Option` is to hint to the type system which implementation
    /// to call. This can be done away with once UFCS arrives.
    fn header_name(marker: Option<Self>) -> &'static str;
    /// Parse a header from a raw stream of bytes.
    ///
    /// It's possible that a request can include a header field more than once,
    /// and in that case, the slice will have a length greater than 1. However,
    /// it's not necessarily the case that a Header is *allowed* to have more
    /// than one field value. If that's the case, you **should** return `None`
    /// if `raw.len() > 1`.
    fn parse_header(raw: &[Vec<u8>]) -> Option<Self>;
    /// Format a header to be output into a TcpStream.
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result;
}

impl<'a> UncheckedAnyDowncast<'a> for &'a Header + 'a {
    #[inline]
    unsafe fn downcast_ref_unchecked<T: 'static>(self) -> &'a T {
        let to: TraitObject = transmute_copy(&self);
        transmute(to.data)
    }
}

fn header_name<T: Header>() -> &'static str {
    let name = Header::header_name(None::<T>);
    debug_assert!(name.as_slice().chars().all(|c| c == '-' || is_lowercase(c)),
        "Header names should be lowercase: {}", name);
    name
}

/// A map of header fields on requests and responses.
pub struct Headers {
    data: HashMap<SendStr, Item>
}

impl Headers {

    /// Creates a new, empty headers map.
    pub fn new() -> Headers {
        Headers {
            data: HashMap::new()
        }
    }

    #[doc(hidden)]
    pub fn from_raw<R: Reader>(rdr: &mut R) -> HttpResult<Headers> {
        let mut headers = Headers::new();
        loop {
            match try!(read_header(rdr)) {
                Some((name, value)) => {
                    // read_header already checks that name is a token, which
                    // means its safe utf8
                    let name = unsafe {
                        raw::from_utf8(name)
                    }.into_ascii_lower();
                    let item = headers.data.find_or_insert(Owned(name), raw(vec![]));
                    item.raw.push(value);
                },
                None => break,
            }
        }
        Ok(headers)
    }

    /// Set a header field to the corresponding value.
    ///
    /// The field is determined by the type of the value being set.
    pub fn set<H: Header>(&mut self, value: H) {
        self.data.insert(Slice(header_name::<H>()), Item {
            raw: vec![],
            tid: Some(TypeId::of::<H>()),
            typed: Some(box value as Box<Header>)
        });
    }

    /// Get a clone of the header field's value, if it exists.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let content_type = headers.get::<ContentType>();
    /// ```
    pub fn get<H: Header + Clone>(&mut self) -> Option<H> {
        self.get_ref().map(|v: &H| v.clone())
    }

    /// Access the raw value of a header, if it exists and has not
    /// been already parsed.
    ///
    /// If the header field has already been parsed into a typed header,
    /// then you *must* access it through that representation.
    ///
    /// Example:
    /// ```
    /// # use hyper::header::Headers;
    /// # let mut headers = Headers::new();
    /// let raw_content_type = unsafe { headers.get_raw("content-type") };
    /// ```
    pub unsafe fn get_raw(&self, name: &'static str) -> Option<&[Vec<u8>]> {
        self.data.find(&Slice(name)).map(|item| {
            item.raw.as_slice()
        })
    }

    /// Get a reference to the header field's value, if it exists.
    pub fn get_ref<H: Header>(&mut self) -> Option<&H> {
        self.data.find_mut(&Slice(header_name::<H>())).and_then(|item| {
            debug!("get_ref, name={}, val={}", header_name::<H>(), item);
            let expected_tid = TypeId::of::<H>();
            let header = match item.tid {
                Some(tid) if tid == expected_tid => return Some(item),
                _ => match Header::parse_header(item.raw.as_slice()) {
                    Some::<H>(h) => {
                        h
                    },
                    None => return None
                },
            };
            item.typed = Some(box header as Box<Header>);
            item.tid = Some(expected_tid);
            Some(item)
        }).and_then(|item| {
            debug!("downcasting {}", item);
            let ret = match item.typed {
                Some(ref val) => {
                    unsafe {
                        Some(val.downcast_ref_unchecked())
                    }
                },
                None => unreachable!()
            };
            ret
        })
    }

    /// Returns a boolean of whether a certain header is in the map.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let has_type = headers.has::<ContentType>();
    /// ```
    pub fn has<H: Header>(&self) -> bool {
        self.data.contains_key(&Slice(header_name::<H>()))
    }

    /// Removes a header from the map, if one existed.
    /// Returns true if a header has been removed.
    pub fn remove<H: Header>(&mut self) -> bool {
        self.data.pop_equiv(&Header::header_name(None::<H>)).is_some()
    }

    /// Returns an iterator over the header fields.
    pub fn iter<'a>(&'a self) -> HeadersItems<'a> {
        HeadersItems {
            inner: self.data.iter()
        }
    }
}

impl fmt::Show for Headers {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!("Headers {\n".fmt(fmt));
        for (k, v) in self.iter() {
            try!(write!(fmt, "\t{}: {}\n", k, v));
        }
        "}".fmt(fmt)
    }
}

/// An `Iterator` over the fields in a `Headers` map.
pub struct HeadersItems<'a> {
    inner: Entries<'a, SendStr, Item>
}

impl<'a> Iterator<(&'a str, HeaderView<'a>)> for HeadersItems<'a> {
    fn next(&mut self) -> Option<(&'a str, HeaderView<'a>)> {
        match self.inner.next() {
            Some((k, v)) => Some((k.as_slice(), HeaderView(v))),
            None => None
        }
    }
}

/// Returned with the `HeadersItems` iterator.
pub struct HeaderView<'a>(&'a Item);

impl<'a> fmt::Show for HeaderView<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let HeaderView(item) = *self;
        item.fmt(fmt)
    }
}

impl Collection for Headers {
    fn len(&self) -> uint {
        self.data.len()
    }
}

impl Mutable for Headers {
    fn clear(&mut self) {
        self.data.clear()
    }
}

struct Item {
    raw: Vec<Vec<u8>>,
    tid: Option<TypeId>,
    typed: Option<Box<Header>>,
}

fn raw(parts: Vec<Vec<u8>>) -> Item {
    Item {
        raw: parts,
        tid: None,
        typed: None,
    }
}

impl fmt::Show for Item {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.typed {
            Some(ref h) => h.fmt_header(fmt),
            None => {
                for part in self.raw.iter() {
                    try!(fmt.write(part.as_slice()));
                }
                Ok(())
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io::MemReader;
    use std::fmt;
    use mime::{Mime, Text, Plain};
    use super::{Headers, Header};
    use super::common::{ContentLength, ContentType};

    fn mem(s: &str) -> MemReader {
        MemReader::new(s.as_bytes().to_vec())
    }

    #[test]
    fn test_from_raw() {
        let mut headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        assert_eq!(headers.get_ref(), Some(&ContentLength(10)));
    }

    #[test]
    fn test_content_type() {
        let content_type = Header::parse_header(["text/plain".as_bytes().to_vec()].as_slice());
        assert_eq!(content_type, Some(ContentType(Mime(Text, Plain, vec![]))));
    }

    #[deriving(Clone)]
    struct CrazyLength(Option<bool>, uint);

    impl Header for CrazyLength {
        fn header_name(_: Option<CrazyLength>) -> &'static str {
            "content-length"
        }
        fn parse_header(raw: &[Vec<u8>]) -> Option<CrazyLength> {
            use std::str::from_utf8;
            use std::from_str::FromStr;

            if raw.len() != 1 {
                return None;
            }
            // we JUST checked that raw.len() == 1, so raw[0] WILL exist.
            match from_utf8(unsafe { raw.as_slice().unsafe_get(0).as_slice() }) {
                Some(s) => FromStr::from_str(s),
                None => None
            }.map(|u| CrazyLength(Some(false), u))
        }
        fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            use std::fmt::Show;
            let CrazyLength(_, ref value) = *self;
            value.fmt(fmt)
        }
    }

    #[test]
    fn test_different_structs_for_same_header() {
        let mut headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        let ContentLength(num) = headers.get::<ContentLength>().unwrap();
        let CrazyLength(_, crazy_num) = headers.get::<CrazyLength>().unwrap();
        assert_eq!(num, crazy_num);
    }
}
<commit_msg>Refactor Header representation to not store the raw representation<commit_after>//! Headers container, and common header fields.
//!
//! hyper has the opinion that Headers should be strongly-typed, because that's
//! why we're using Rust in the first place. To set or get any header, an object
//! must implement the `Header` trait from this module. Several common headers
//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
use std::ascii::OwnedAsciiExt;
use std::char::is_lowercase;
use std::fmt::{mod, Show};
use std::intrinsics::TypeId;
use std::mem::{transmute, transmute_copy};
use std::raw::TraitObject;
use std::str::{from_utf8, SendStr, Slice, Owned};
use std::string::raw;
use std::collections::hashmap::{HashMap, Entries};

use uany::UncheckedAnyDowncast;
use typeable::Typeable;

use http::read_header;
use {HttpResult};

/// Common Headers
pub mod common;

/// A trait for any object that will represent a header field and value.
pub trait Header: Typeable {
    /// Returns the name of the header field this belongs to.
    ///
    /// The market `Option` is to hint to the type system which implementation
    /// to call. This can be done away with once UFCS arrives.
    fn header_name(marker: Option<Self>) -> &'static str;
    /// Parse a header from a raw stream of bytes.
    ///
    /// It's possible that a request can include a header field more than once,
    /// and in that case, the slice will have a length greater than 1. However,
    /// it's not necessarily the case that a Header is *allowed* to have more
    /// than one field value. If that's the case, you **should** return `None`
    /// if `raw.len() > 1`.
    fn parse_header(raw: &[Vec<u8>]) -> Option<Self>;
    /// Format a header to be output into a TcpStream.
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result;
}

#[doc(hidden)]
trait Is {
    fn is<T: 'static>(self) -> bool;
}

impl<'a> Is for &'a Header {
    fn is<T: 'static>(self) -> bool {
        self.get_type() == TypeId::of::<T>()
    }
}

impl<'a> UncheckedAnyDowncast<'a> for &'a Header {
    #[inline]
    unsafe fn downcast_ref_unchecked<T: 'static>(self) -> &'a T {
        let to: TraitObject = transmute_copy(&self);
        transmute(to.data)
    }
}

fn header_name<T: Header>() -> &'static str {
    let name = Header::header_name(None::<T>);
    debug_assert!(name.as_slice().chars().all(|c| c == '-' || is_lowercase(c)),
        "Header names should be lowercase: {}", name);
    name
}

/// A map of header fields on requests and responses.
pub struct Headers {
    data: HashMap<SendStr, Item>
}

impl Headers {

    /// Creates a new, empty headers map.
    pub fn new() -> Headers {
        Headers {
            data: HashMap::new()
        }
    }

    #[doc(hidden)]
    pub fn from_raw<R: Reader>(rdr: &mut R) -> HttpResult<Headers> {
        let mut headers = Headers::new();
        loop {
            match try!(read_header(rdr)) {
                Some((name, value)) => {
                    // read_header already checks that name is a token, which
                    // means its safe utf8
                    let name = unsafe {
                        raw::from_utf8(name)
                    }.into_ascii_lower();
                    let item = headers.data.find_or_insert(Owned(name), Raw(vec![]));
                    match *item {
                        Raw(ref mut raw) => raw.push(value),
                        // Unreachable
                        _ => {}
                    };
                },
                None => break,
            }
        }
        Ok(headers)
    }

    /// Set a header field to the corresponding value.
    ///
    /// The field is determined by the type of the value being set.
    pub fn set<H: Header>(&mut self, value: H) {
        self.data.insert(Slice(header_name::<H>()), Typed(box value as Box<Header>));
    }

    /// Get a clone of the header field's value, if it exists.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let content_type = headers.get::<ContentType>();
    /// ```
    pub fn get<H: Header + Clone>(&mut self) -> Option<H> {
        self.get_ref().map(|v: &H| v.clone())
    }

    /// Access the raw value of a header, if it exists and has not
    /// been already parsed.
    ///
    /// If the header field has already been parsed into a typed header,
    /// then you *must* access it through that representation.
    ///
    /// Example:
    /// ```
    /// # use hyper::header::Headers;
    /// # let mut headers = Headers::new();
    /// let raw_content_type = unsafe { headers.get_raw("content-type") };
    /// ```
    pub unsafe fn get_raw(&self, name: &'static str) -> Option<&[Vec<u8>]> {
        self.data.find(&Slice(name)).and_then(|item| {
            match *item {
                Raw(ref raw) => Some(raw.as_slice()),
                _ => None
            }
        })
    }

    /// Get a reference to the header field's value, if it exists.
    pub fn get_ref<H: Header>(&mut self) -> Option<&H> {
        self.data.find_mut(&Slice(header_name::<H>())).and_then(|item| {
            debug!("get_ref, name={}, val={}", header_name::<H>(), item);
            let header = match *item {
                // Huge borrowck hack here, should be refactored to just return here.
                Typed(ref typed) if typed.is::<H>() => None,
                // Typed, wrong type
                Typed(_) => return None,
                Raw(ref raw) => match Header::parse_header(raw.as_slice()) {
                    Some::<H>(h) => {
                        Some(h)
                    },
                    None => return None
                },
            };

            match header {
                Some(header) => {
                    *item = Typed(box header as Box<Header>);
                    Some(item)
                },
                None => {
                    Some(item)
                }
            }
        }).and_then(|item| {
            debug!("downcasting {}", item);
            let ret = match *item {
                Typed(ref val) => {
                    unsafe { Some(val.downcast_ref_unchecked()) }
                },
                _ => unreachable!()
            };
            ret
        })
    }

    /// Returns a boolean of whether a certain header is in the map.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let has_type = headers.has::<ContentType>();
    /// ```
    pub fn has<H: Header>(&self) -> bool {
        self.data.contains_key(&Slice(header_name::<H>()))
    }

    /// Removes a header from the map, if one existed.
    /// Returns true if a header has been removed.
    pub fn remove<H: Header>(&mut self) -> bool {
        self.data.remove(&Slice(Header::header_name(None::<H>)))
    }

    /// Returns an iterator over the header fields.
    pub fn iter<'a>(&'a self) -> HeadersItems<'a> {
        HeadersItems {
            inner: self.data.iter()
        }
    }
}

impl fmt::Show for Headers {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!("Headers {\n".fmt(fmt));
        for (k, v) in self.iter() {
            try!(write!(fmt, "\t{}: {}\n", k, v));
        }
        "}".fmt(fmt)
    }
}

/// An `Iterator` over the fields in a `Headers` map.
pub struct HeadersItems<'a> {
    inner: Entries<'a, SendStr, Item>
}

impl<'a> Iterator<(&'a str, HeaderView<'a>)> for HeadersItems<'a> {
    fn next(&mut self) -> Option<(&'a str, HeaderView<'a>)> {
        match self.inner.next() {
            Some((k, v)) => Some((k.as_slice(), HeaderView(v))),
            None => None
        }
    }
}

/// Returned with the `HeadersItems` iterator.
pub struct HeaderView<'a>(&'a Item);

impl<'a> fmt::Show for HeaderView<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let HeaderView(item) = *self;
        item.fmt(fmt)
    }
}

impl Collection for Headers {
    fn len(&self) -> uint {
        self.data.len()
    }
}

impl Mutable for Headers {
    fn clear(&mut self) {
        self.data.clear()
    }
}

enum Item {
    Raw(Vec<Vec<u8>>),
    Typed(Box<Header>)
}

impl fmt::Show for Item {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Typed(ref h) => h.fmt_header(fmt),
            Raw(ref raw) => {
                for part in raw.iter() {
                    try!(fmt.write(part.as_slice()));
                }
                Ok(())
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io::MemReader;
    use std::fmt;
    use mime::{Mime, Text, Plain};
    use super::{Headers, Header};
    use super::common::{ContentLength, ContentType};

    fn mem(s: &str) -> MemReader {
        MemReader::new(s.as_bytes().to_vec())
    }

    #[test]
    fn test_from_raw() {
        let mut headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        assert_eq!(headers.get_ref(), Some(&ContentLength(10)));
    }

    #[test]
    fn test_content_type() {
        let content_type = Header::parse_header(["text/plain".as_bytes().to_vec()].as_slice());
        assert_eq!(content_type, Some(ContentType(Mime(Text, Plain, vec![]))));
    }

    #[deriving(Clone)]
    struct CrazyLength(Option<bool>, uint);

    impl Header for CrazyLength {
        fn header_name(_: Option<CrazyLength>) -> &'static str {
            "content-length"
        }
        fn parse_header(raw: &[Vec<u8>]) -> Option<CrazyLength> {
            use std::str::from_utf8;
            use std::from_str::FromStr;

            if raw.len() != 1 {
                return None;
            }
            // we JUST checked that raw.len() == 1, so raw[0] WILL exist.
            match from_utf8(unsafe { raw.as_slice().unsafe_get(0).as_slice() }) {
                Some(s) => FromStr::from_str(s),
                None => None
            }.map(|u| CrazyLength(Some(false), u))
        }
        fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            use std::fmt::Show;
            let CrazyLength(_, ref value) = *self;
            value.fmt(fmt)
        }
    }

    #[test]
    fn test_different_structs_for_same_header() {
        let mut headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        let ContentLength(num) = headers.get::<ContentLength>().unwrap();
        let CrazyLength(_, crazy_num) = headers.get::<CrazyLength>().unwrap();
        assert_eq!(num, crazy_num);
    }
}
<|endoftext|>


<commit_before>use dispatch_table::{DispatchTable, DispatchFn};
use spin::RwLock;
use isr;

#[derive(Copy, Clone, Default)]
#[repr(packed)]
struct IDTEntry {
    base_low: u16,
    selector: u16,
    always0: u8,
    flags: u8,
    base_high: u16,
    base_highest: u32,
    _reserved: u32,
}

pub struct IDT([IDTEntry; 256]);

lazy_static! {
    static ref INTERRUPT_TABLE: RwLock<DispatchTable<u64, InterruptCPUState>> =
        RwLock::new(DispatchTable::new(256));
    static ref DESCRIPTOR_TABLE: RwLock<IDT> = RwLock::new(IDT([Default::default(); 256]));
}

impl IDT {
    fn set_entry(&mut self, num: usize, base: u64, selector: u16, flags: u8) {
        self.0[num].base_low = (base & 0xffff) as u16;
        self.0[num].base_high = ((base >> 16) & 0xffff) as u16;
        self.0[num].base_highest = (base >> 32) as u32;
        self.0[num].always0 = 0;
        self.0[num].selector = selector;
        self.0[num].flags = flags;
    }
}

#[repr(C)]
pub struct InterruptCPUState {
    ds: u64,
    r15: u64,
    r14: u64,
    r13: u64,
    r12: u64,
    r11: u64,
    r10: u64,
    r9: u64,
    r8: u64,
    rdi: u64,
    rsi: u64,
    rbp: u64,
    rdx: u64,
    rcx: u64,
    rbx: u64,
    rax: u64,
    interrupt_number: u64,
    error_code: u64,
    rip: u64,
    cs: u64,
    rflags: u64,
    rsp: u64,
    ss: u64,
}

pub fn register_interrupt_handler(interrupt: u64,
                                  stub: isr::InterruptServiceRoutine,
                                  handler: DispatchFn<u64, InterruptCPUState>) {
    INTERRUPT_TABLE.write().register(interrupt, handler);
    DESCRIPTOR_TABLE.write().set_entry(interrupt as usize, stub as u64, 0x08, 0x8e);
}

pub fn unregister_interrupt_handler(interrupt: u64) {
    INTERRUPT_TABLE.write().unregister(interrupt);
}

#[no_mangle]
pub extern "C" fn dispatch_interrupt(state: &mut InterruptCPUState) {
    INTERRUPT_TABLE.read().dispatch(state.interrupt_number, state);
}

fn default_handler(_interrupt_number: u64, _regs: &mut InterruptCPUState) -> bool {
    true
}

pub fn init_interrupt_handlers() {
    for i in 0..20 {
        register_interrupt_handler(i, isr::ISR[i as usize], default_handler);
    }
}

#[cfg(feature = "runtime_tests")]
pub mod runtime_tests {

    use interrupts;
    use vmx;
    use cli;
    use isr;
    use core::mem;

    extern "C" {
        fn _test_division_by_zero_routine() -> bool;

        // DO NOT CALL THIS FUNCTION. YOU WILL MESS UP THE STACK.
        fn _after_division() -> bool;
    }

    fn new_host_idt_descriptor() -> vmx::CPUTableDescriptor {
        let base = (*interrupts::DESCRIPTOR_TABLE.write()).0.as_ptr() as u64;
        vmx::CPUTableDescriptor {
            base: base,
            limit: (mem::size_of::<interrupts::IDT>() - 1) as u16,
        }
    }

    pub fn run() {
        test_load_and_restore_idt();
        test_divide_by_zero_interrupt();
    }

    fn test_load_and_restore_idt() {
        cli::ClearLocalInterruptsGuard::new();
        let idt_desc = new_host_idt_descriptor();
        let mut orig_idt_desc: vmx::CPUTableDescriptor = Default::default();
        vmx::sidt(&mut orig_idt_desc);
        vmx::lidt(&idt_desc);
        vmx::lidt(&orig_idt_desc);
    }

    fn division_by_zero_handler(interrupt_number: u64,
                                regs: &mut interrupts::InterruptCPUState)
                                -> bool {
        assert_eq!(interrupt_number, 0);
        info!("Handling division by zero interrupt.");
        // A div instruction is three bytes long. If we return without
        // advancing the rip we'll execute the same instruction again and wind
        // up in a fault loop.
        regs.rip = _after_division as u64;
        true
    }

    #[allow(unused_variables)]
    fn test_divide_by_zero_interrupt() {
        let mut orig_idt_desc: vmx::CPUTableDescriptor = Default::default();
        interrupts::register_interrupt_handler(0, isr::_isr0, division_by_zero_handler);

        {
            cli::ClearLocalInterruptsGuard::new();
            let idt_desc = new_host_idt_descriptor();
            vmx::sidt(&mut orig_idt_desc);
            vmx::lidt(&idt_desc);
        }

        info!("Here we go!");

        unsafe {
            assert!(_test_division_by_zero_routine());
        }

        info!("Successfully returned from a division by zero interrupt.");

        {
            cli::ClearLocalInterruptsGuard::new();
            vmx::lidt(&orig_idt_desc);
        }

    }
}
<commit_msg>Delete comment<commit_after>use dispatch_table::{DispatchTable, DispatchFn};
use spin::RwLock;
use isr;

#[derive(Copy, Clone, Default)]
#[repr(packed)]
struct IDTEntry {
    base_low: u16,
    selector: u16,
    always0: u8,
    flags: u8,
    base_high: u16,
    base_highest: u32,
    _reserved: u32,
}

pub struct IDT([IDTEntry; 256]);

lazy_static! {
    static ref INTERRUPT_TABLE: RwLock<DispatchTable<u64, InterruptCPUState>> =
        RwLock::new(DispatchTable::new(256));
    static ref DESCRIPTOR_TABLE: RwLock<IDT> = RwLock::new(IDT([Default::default(); 256]));
}

impl IDT {
    fn set_entry(&mut self, num: usize, base: u64, selector: u16, flags: u8) {
        self.0[num].base_low = (base & 0xffff) as u16;
        self.0[num].base_high = ((base >> 16) & 0xffff) as u16;
        self.0[num].base_highest = (base >> 32) as u32;
        self.0[num].always0 = 0;
        self.0[num].selector = selector;
        self.0[num].flags = flags;
    }
}

#[repr(C)]
pub struct InterruptCPUState {
    ds: u64,
    r15: u64,
    r14: u64,
    r13: u64,
    r12: u64,
    r11: u64,
    r10: u64,
    r9: u64,
    r8: u64,
    rdi: u64,
    rsi: u64,
    rbp: u64,
    rdx: u64,
    rcx: u64,
    rbx: u64,
    rax: u64,
    interrupt_number: u64,
    error_code: u64,
    rip: u64,
    cs: u64,
    rflags: u64,
    rsp: u64,
    ss: u64,
}

pub fn register_interrupt_handler(interrupt: u64,
                                  stub: isr::InterruptServiceRoutine,
                                  handler: DispatchFn<u64, InterruptCPUState>) {
    INTERRUPT_TABLE.write().register(interrupt, handler);
    DESCRIPTOR_TABLE.write().set_entry(interrupt as usize, stub as u64, 0x08, 0x8e);
}

pub fn unregister_interrupt_handler(interrupt: u64) {
    INTERRUPT_TABLE.write().unregister(interrupt);
}

#[no_mangle]
pub extern "C" fn dispatch_interrupt(state: &mut InterruptCPUState) {
    INTERRUPT_TABLE.read().dispatch(state.interrupt_number, state);
}

fn default_handler(_interrupt_number: u64, _regs: &mut InterruptCPUState) -> bool {
    true
}

pub fn init_interrupt_handlers() {
    for i in 0..20 {
        register_interrupt_handler(i, isr::ISR[i as usize], default_handler);
    }
}

#[cfg(feature = "runtime_tests")]
pub mod runtime_tests {

    use interrupts;
    use vmx;
    use cli;
    use isr;
    use core::mem;

    extern "C" {
        fn _test_division_by_zero_routine() -> bool;

        // DO NOT CALL THIS FUNCTION. YOU WILL MESS UP THE STACK.
        fn _after_division() -> bool;
    }

    fn new_host_idt_descriptor() -> vmx::CPUTableDescriptor {
        let base = (*interrupts::DESCRIPTOR_TABLE.write()).0.as_ptr() as u64;
        vmx::CPUTableDescriptor {
            base: base,
            limit: (mem::size_of::<interrupts::IDT>() - 1) as u16,
        }
    }

    pub fn run() {
        test_load_and_restore_idt();
        test_divide_by_zero_interrupt();
    }

    fn test_load_and_restore_idt() {
        cli::ClearLocalInterruptsGuard::new();
        let idt_desc = new_host_idt_descriptor();
        let mut orig_idt_desc: vmx::CPUTableDescriptor = Default::default();
        vmx::sidt(&mut orig_idt_desc);
        vmx::lidt(&idt_desc);
        vmx::lidt(&orig_idt_desc);
    }

    fn division_by_zero_handler(interrupt_number: u64,
                                regs: &mut interrupts::InterruptCPUState)
                                -> bool {
        assert_eq!(interrupt_number, 0);
        info!("Handling division by zero interrupt.");
        regs.rip = _after_division as u64;
        true
    }

    #[allow(unused_variables)]
    fn test_divide_by_zero_interrupt() {
        let mut orig_idt_desc: vmx::CPUTableDescriptor = Default::default();
        interrupts::register_interrupt_handler(0, isr::_isr0, division_by_zero_handler);

        {
            cli::ClearLocalInterruptsGuard::new();
            let idt_desc = new_host_idt_descriptor();
            vmx::sidt(&mut orig_idt_desc);
            vmx::lidt(&idt_desc);
        }

        info!("Here we go!");

        unsafe {
            assert!(_test_division_by_zero_routine());
        }

        info!("Successfully returned from a division by zero interrupt.");

        {
            cli::ClearLocalInterruptsGuard::new();
            vmx::lidt(&orig_idt_desc);
        }

    }
}
<|endoftext|>


<commit_before>// CITA
// Copyright 2016-2019 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use crate::cita_protocol::network_message_to_pubsub_message;
use crate::network::{NetworkClient, RemoteMessage};
use crate::node_manager::{AddConnectedNodeReq, InitMsg, NetworkInitReq, NodesManagerClient};
use bytes::BytesMut;
use libproto::{Message as ProtoMessage, TryFrom, TryInto};
use logger::{info, warn};
use tentacle::{
    builder::MetaBuilder,
    context::{ProtocolContext, ProtocolContextMutRef},
    service::{ProtocolHandle, ProtocolMeta},
    traits::ServiceProtocol,
    ProtocolId, SessionId,
};
use tokio::codec::length_delimited::LengthDelimitedCodec;

// Quota (1 byte) = 200,
// Max 20 block in one transfer.
// 512M can support BQL set to 2 ** 32 - 1
pub const MAX_FRAME_LENGTH: usize = 512 * 1024 * 1204;
pub const TRANSFER_PROTOCOL_ID: ProtocolId = ProtocolId::new(1);

struct TransferProtocol {
    proto_id: ProtocolId,
    connected_session_ids: Vec<SessionId>,
    network_client: NetworkClient,
    nodes_mgr_client: NodesManagerClient,
}

impl ServiceProtocol for TransferProtocol {
    fn init(&mut self, _control: &mut ProtocolContext) {}

    fn connected(&mut self, control: ProtocolContextMutRef, version: &str) {
        info!(
            "[Transfer] Connected proto id [{}] open on session [{}], address: [{}], type: [{:?}], version: {}",
            self.proto_id, control.session.id, control.session.address, control.session.ty, version
        );
        self.connected_session_ids.push(control.session.id);

        let req = NetworkInitReq::new(control.session.id);
        self.nodes_mgr_client.network_init(req);

        info!(
            "[Transfer] Connected sessions: {:?}",
            self.connected_session_ids
        );
    }

    fn disconnected(&mut self, control: ProtocolContextMutRef) {
        let new_list = self
            .connected_session_ids
            .iter()
            .filter(|&id| id != &control.session.id)
            .cloned()
            .collect();
        self.connected_session_ids = new_list;

        info!(
            "[Transfer] Disconnected proto id [{}] close on session [{}]",
            self.proto_id, control.session.id
        );
    }

    fn received(&mut self, env: ProtocolContextMutRef, data: bytes::Bytes) {
        let mut data = BytesMut::from(data);

        if let Some((key, message)) = network_message_to_pubsub_message(&mut data) {
            if key.eq(&"network.init".to_string()) {
                let msg = InitMsg::from(message);
                let req = AddConnectedNodeReq::new(env.session.id, env.session.ty, msg);
                self.nodes_mgr_client.add_connected_node(req);
                return;
            }

            let mut msg = ProtoMessage::try_from(&message).unwrap();
            msg.set_origin(env.session.id.value() as u32);
            self.network_client
                .handle_remote_message(RemoteMessage::new(key, msg.try_into().unwrap()));
        } else {
            warn!("[Transfer] Cannot convert network message to pubsub message!");
        }
    }
}

pub fn create_transfer_meta(
    network_client: NetworkClient,
    nodes_mgr_client: NodesManagerClient,
) -> ProtocolMeta {
    MetaBuilder::default()
        .id(TRANSFER_PROTOCOL_ID)
        .codec(|| Box::new(LengthDelimitedCodec::new()))
        .service_handle(move || {
            let handle = Box::new(TransferProtocol {
                proto_id: TRANSFER_PROTOCOL_ID,
                connected_session_ids: Vec::default(),
                network_client: network_client.clone(),
                nodes_mgr_client: nodes_mgr_client.clone(),
            });
            ProtocolHandle::Callback(handle)
        })
        .build()
}
<commit_msg>add max frame limit<commit_after>// CITA
// Copyright 2016-2019 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use crate::cita_protocol::network_message_to_pubsub_message;
use crate::network::{NetworkClient, RemoteMessage};
use crate::node_manager::{AddConnectedNodeReq, InitMsg, NetworkInitReq, NodesManagerClient};
use bytes::BytesMut;
use libproto::{Message as ProtoMessage, TryFrom, TryInto};
use logger::{info, warn};
use tentacle::{
    builder::MetaBuilder,
    context::{ProtocolContext, ProtocolContextMutRef},
    service::{ProtocolHandle, ProtocolMeta},
    traits::ServiceProtocol,
    ProtocolId, SessionId,
};
use tokio::codec::length_delimited::LengthDelimitedCodec;

// Quota (1 byte) = 200,
// Max 20 block in one transfer.
// 512M can support BQL set to 2 ** 32 - 1
pub const MAX_FRAME_LENGTH: usize = 512 * 1024 * 1204;
pub const TRANSFER_PROTOCOL_ID: ProtocolId = ProtocolId::new(1);

struct TransferProtocol {
    proto_id: ProtocolId,
    connected_session_ids: Vec<SessionId>,
    network_client: NetworkClient,
    nodes_mgr_client: NodesManagerClient,
}

impl ServiceProtocol for TransferProtocol {
    fn init(&mut self, _control: &mut ProtocolContext) {}

    fn connected(&mut self, control: ProtocolContextMutRef, version: &str) {
        info!(
            "[Transfer] Connected proto id [{}] open on session [{}], address: [{}], type: [{:?}], version: {}",
            self.proto_id, control.session.id, control.session.address, control.session.ty, version
        );
        self.connected_session_ids.push(control.session.id);

        let req = NetworkInitReq::new(control.session.id);
        self.nodes_mgr_client.network_init(req);

        info!(
            "[Transfer] Connected sessions: {:?}",
            self.connected_session_ids
        );
    }

    fn disconnected(&mut self, control: ProtocolContextMutRef) {
        let new_list = self
            .connected_session_ids
            .iter()
            .filter(|&id| id != &control.session.id)
            .cloned()
            .collect();
        self.connected_session_ids = new_list;

        info!(
            "[Transfer] Disconnected proto id [{}] close on session [{}]",
            self.proto_id, control.session.id
        );
    }

    fn received(&mut self, env: ProtocolContextMutRef, data: bytes::Bytes) {
        let mut data = BytesMut::from(data);

        if let Some((key, message)) = network_message_to_pubsub_message(&mut data) {
            if key.eq(&"network.init".to_string()) {
                let msg = InitMsg::from(message);
                let req = AddConnectedNodeReq::new(env.session.id, env.session.ty, msg);
                self.nodes_mgr_client.add_connected_node(req);
                return;
            }

            let mut msg = ProtoMessage::try_from(&message).unwrap();
            msg.set_origin(env.session.id.value() as u32);
            self.network_client
                .handle_remote_message(RemoteMessage::new(key, msg.try_into().unwrap()));
        } else {
            warn!("[Transfer] Cannot convert network message to pubsub message!");
        }
    }
}

pub fn create_transfer_meta(
    network_client: NetworkClient,
    nodes_mgr_client: NodesManagerClient,
) -> ProtocolMeta {
    MetaBuilder::default()
        .id(TRANSFER_PROTOCOL_ID)
        .codec(|| {
            let mut lcodec = LengthDelimitedCodec::new();
            lcodec.set_max_frame_length(MAX_FRAME_LENGTH);
            Box::new(lcodec)
        })
        .service_handle(move || {
            let handle = Box::new(TransferProtocol {
                proto_id: TRANSFER_PROTOCOL_ID,
                connected_session_ids: Vec::default(),
                network_client: network_client.clone(),
                nodes_mgr_client: nodes_mgr_client.clone(),
            });
            ProtocolHandle::Callback(handle)
        })
        .build()
}
<|endoftext|>