<commit_before>use wire::peer_info::PeerState;
use metainfo::MetaInfo;
use wire::action::PeerAction;
use wire::msg::PeerMsg;
use wire::action::PeerStreamAction;
use std::collections::HashMap;
use bit_vec::BitVec;
use file::PartialFile;
use file::PartialFileTrait;
use wire::action::PeerId;

pub trait Strategy {
    fn query(&mut self, pending: Vec<&Order>, done: Vec<OrderResult>, peers: Vec<&PeerState>, file: &PartialFile) -> Vec<Order>;
    fn on_handshake(&mut self, id: PeerId) -> Vec<Order>;
    fn on_choke(&mut self, id: PeerId) -> Vec<Order>;
    fn on_unchoke(&mut self, id: PeerId) -> Vec<Order>;
    fn on_interested(&mut self, id: PeerId) -> Vec<Order>;
    fn on_not_interested(&mut self, id: PeerId) -> Vec<Order>;
    fn on_have(&mut self, id: PeerId, piece_index: usize) -> Vec<Order>;
    fn on_bitfield(&mut self, id: PeerId, bitfield: BitVec) ->  Vec<Order>;
    fn on_request(&mut self, id: PeerId, index: u32, begin: u32, length: u32) -> Vec<Order>;
    fn on_piece(&mut self, id: PeerId, index: u32, begin: u32, block: Vec<u8>) -> Vec<Order>;
    fn on_cancel(&mut self, id: PeerId, index: u32, begin: u32, block: Vec<u8>) -> Vec<Order>;
    fn on_port(&mut self, id: PeerId, port: u16) -> Vec<Order>;
}

const MAX_BLOCK_SIZE: u64 = 2 << 14;
const MAX_BYTES_PER_REQUEST: u64 = 1024 * 512;
const MAX_PIECES_PEER: usize = 10;

pub struct NormalStrategy {
    orders: HashMap<OrderId, OrderInfo>,
    peers: HashMap<PeerId, PeerState>,
    pieces_to_request: BitVec,
    next_order_id: usize,
    num_pieces: usize,
    piece_length: u64,
    partial_file: PartialFile
}

impl NormalStrategy {
    pub fn new (metainfo: MetaInfo) -> NormalStrategy {
        let num_pieces = metainfo.info.pieces.len();
        let partial_file = PartialFile::new(&metainfo.info);
        let piece_length = partial_file.piece_length();

        NormalStrategy {
            orders: HashMap::new(),
            peers: HashMap::new(),
            pieces_to_request: BitVec::from_elem(num_pieces, true),
            next_order_id: 0,
            partial_file: partial_file,
            num_pieces: num_pieces,
            piece_length: piece_length,
        }
    }

    pub fn request_pieces<F: PartialFileTrait>(&mut self, peers: Vec<&PeerState>, partial_file: &F) -> Vec<PeerAction> {
        let mut actions = Vec::new();
        let ready_peers = peers.iter().filter(|peer| !peer.peer_choking && !peer.am_choking && peer.has_handshake);
        for peer in ready_peers {
            let id = peer.peer_id;
            let mut missing = partial_file.bit_array();

            missing.negate();
            let mut them = peer.file.bit_array();
            missing.intersect(&them);
            missing.intersect(&self.pieces_to_request);

            //now have eligible pieces to request
            let mut pieces = missing.into_iter().enumerate().filter(|&(_, x)| x).map(|(i, _)| i as u64).collect::<Vec<u64>>();
            let piece_len = self.piece_length;
            let mut bytes_requested = 0;
            let mut pieces_request = 0;

            let mut msgs = Vec::new();
            for (piece_count, piece_index) in pieces.into_iter().enumerate() {
                if bytes_requested > MAX_BYTES_PER_REQUEST || piece_count > MAX_PIECES_PEER {
                    break;
                }
                let mut pieces = NormalStrategy::piece_request(piece_index, piece_len, MAX_BLOCK_SIZE);
                self.pieces_to_request.set(piece_index as usize, false);
                msgs.append(&mut pieces);
            }

            let req_actions = PeerAction(id, PeerStreamAction::SendMessages(msgs));
            actions.push(req_actions);
        }
        actions
    }

    fn piece_request(piece_index: u64, piece_len: u64, max_block_size: u64) -> Vec<PeerMsg> {
        let mut msgs = Vec::new();
        let mut bytes_requested = 0;

        if piece_len > max_block_size {
            let mut offset = 0;
            while offset < piece_len {
                if (offset + max_block_size > piece_len) {
                    msgs.push(PeerMsg::Request(piece_index as u32, offset as u32,
                        max_block_size as u32));
                } else {
                    msgs.push(PeerMsg::Request(piece_index as u32, offset as u32,
                        max_block_size as u32));
                }
                offset += max_block_size;
            }
        } else {
            msgs.push(PeerMsg::Request(piece_index as u32, 0, piece_len as u32));
        }

        msgs
    }

    fn _get_piece_from_req(&mut self, index: usize, begin: u32, offset: u32) -> Option<PeerMsg> {
        if self.partial_file.has_piece(index as usize) {
            let piece = self.partial_file.get_piece_mut(index as usize);
            return match piece.get_offset(begin as usize, offset as usize) {
                Some(piece_data) => {
                    let msg = PeerMsg::Piece(begin, offset, Vec::from(piece_data));
                    Some(msg)
                }
                _ => None,
            };
        }
        None
    }
}

impl Strategy for NormalStrategy {
    fn on_handshake(&mut self, id: PeerId) -> Vec<Order> {
        let peer = PeerState::new(self.num_pieces, id);
        self.peers.insert(id, peer);
        vec![]

    }
    fn on_choke(&mut self, id: PeerId) -> Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => peer.peer_choking = true,
            None => {}
        };
        vec![]
    }
    fn on_unchoke(&mut self, id: PeerId) -> Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => peer.peer_choking = false,
            None => {}
        };
        vec![]

    }
    fn on_interested(&mut self, id: PeerId) -> Vec<Order>  {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => peer.peer_interested = true,
            None => {}
        };
        vec![]

    }
    fn on_not_interested(&mut self, id: PeerId) -> Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => peer.peer_interested = false,
            None => {}
        };
        vec![]
    }

    fn on_have(&mut self, id: PeerId, piece_index: usize) -> Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => {
                peer.file.set(piece_index as usize, true);
                if !peer.partial_file.get(piece_index) {
                    let p_msgs = NormalStrategy::piece_request(piece_index, piece_len, MAX_BLOCK_SIZE);
                }
            }
            None => {}
        };
        vec![]
    }

    fn on_bitfield(&mut self, id: PeerId, bitfield: BitVec) ->  Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => {
                    let limit = peer.file.bit_array().len();
                    for (i, bit) in bitfield.iter().enumerate()  {
                        if i >= limit {
                            break;
                        }
                        peer.file.set(i, bit);
                    }
                },
            None => {}
        };
        vec![]
    }
    fn on_request(&mut self, id: PeerId, index: u32, begin: u32, length: u32) -> Vec<Order> {
        let piece_result = self._get_piece_from_req(index as usize, begin, length);
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => {
                let response = piece_result;
                match response {
                    Some(r) => unimplemented!(),
                    _ => Vec::new(),
                }
            },
            _ => Vec::new()
        }
    }

    fn on_piece(&mut self, id: PeerId, index: u32, begin: u32, block: Vec<u8>) -> Vec<Order> {
        self.partial_file.add_piece(index as usize, begin as usize, block);
        Vec::new()
    }

    fn on_cancel(&mut self, id: PeerId, index: u32, begin: u32, block: Vec<u8>) -> Vec<Order> {
        Vec::new()
    }

    fn on_port(&mut self, id: PeerId, port: u16) -> Vec<Order> {
        Vec::new()
    }

    fn query(&mut self, pending: Vec<&Order>, done: Vec<OrderResult>, peers: Vec<&PeerState>, file: &PartialFile)
        -> Vec<Order> {
        let actions = self.request_pieces(peers, file);
        let mut orders = Vec::new();

        for action in actions {
            orders.push(make_order(action));
            self.next_order_id += 1;
        }

        orders
    }

    fn _make_order(&mut self, action: PeerStreamAction) {
        Order {order_id: self.next_order_id, action: action, status: OrderStatus::NotStarted}
    }

}

struct OrderInfo;
type OrderId = usize;

pub struct OrderResult {
    status: OrderStatus,
    order_id: OrderId
}

pub struct Order {
    status: OrderStatus,
    order_id: OrderId,
    pub action: PeerAction
}

impl Order {
    pub fn complete(&self, status: OrderStatus) -> OrderResult {
        OrderResult { order_id: self.order_id, status: status}
    }

    pub fn id(&self) -> OrderId {
        self.order_id
    }

    pub fn status(&self) -> OrderStatus {
        self.status
    }

    pub fn set_status(&mut self, status: OrderStatus) {
        self.status = status;
    }
}

#[derive(Eq, PartialEq, Clone, Copy)]
pub enum OrderStatus {
    NotStarted,
    InProgress,
    Failed,
    Done
}
<commit_msg>Fix on_have and make code compile<commit_after>use wire::peer_info::PeerState;
use metainfo::MetaInfo;
use wire::action::PeerAction;
use wire::msg::PeerMsg;
use wire::action::PeerStreamAction;
use std::collections::HashMap;
use bit_vec::BitVec;
use file::PartialFile;
use file::PartialFileTrait;
use wire::action::PeerId;
use file::PeerFile;

pub trait Strategy {
    fn query(&mut self, pending: Vec<&Order>, done: Vec<OrderResult>, peers: Vec<&PeerState>, file: &PartialFile) -> Vec<Order>;
    fn on_handshake(&mut self, id: PeerId) -> Vec<Order>;
    fn on_choke(&mut self, id: PeerId) -> Vec<Order>;
    fn on_unchoke(&mut self, id: PeerId) -> Vec<Order>;
    fn on_interested(&mut self, id: PeerId) -> Vec<Order>;
    fn on_not_interested(&mut self, id: PeerId) -> Vec<Order>;
    fn on_have(&mut self, id: PeerId, piece_index: usize) -> Vec<Order>;
    fn on_bitfield(&mut self, id: PeerId, bitfield: BitVec) ->  Vec<Order>;
    fn on_request(&mut self, id: PeerId, index: u32, begin: u32, length: u32) -> Vec<Order>;
    fn on_piece(&mut self, id: PeerId, index: u32, begin: u32, block: Vec<u8>) -> Vec<Order>;
    fn on_cancel(&mut self, id: PeerId, index: u32, begin: u32, block: Vec<u8>) -> Vec<Order>;
    fn on_port(&mut self, id: PeerId, port: u16) -> Vec<Order>;
}

const MAX_BLOCK_SIZE: u64 = 2 << 14;
const MAX_BYTES_PER_REQUEST: u64 = 1024 * 512;
const MAX_PIECES_PEER: usize = 10;

pub struct NormalStrategy {
    orders: HashMap<OrderId, OrderInfo>,
    peers: HashMap<PeerId, PeerState>,
    pieces_to_request: BitVec,
    next_order_id: usize,
    num_pieces: usize,
    piece_length: u64,
    partial_file: PartialFile
}

impl NormalStrategy {
    pub fn new (metainfo: MetaInfo) -> NormalStrategy {
        let num_pieces = metainfo.info.pieces.len();
        let partial_file = PartialFile::new(&metainfo.info);
        let piece_length = partial_file.piece_length();

        NormalStrategy {
            orders: HashMap::new(),
            peers: HashMap::new(),
            pieces_to_request: BitVec::from_elem(num_pieces, true),
            next_order_id: 0,
            partial_file: partial_file,
            num_pieces: num_pieces,
            piece_length: piece_length,
        }
    }

    pub fn request_pieces<F: PartialFileTrait>(&mut self, peers: Vec<&PeerState>, partial_file: &F) -> Vec<PeerAction> {
        let mut actions = Vec::new();
        let ready_peers = peers.iter().filter(|peer| !peer.peer_choking && !peer.am_choking && peer.has_handshake);
        for peer in ready_peers {
            let id = peer.peer_id;
            let missing = self._get_missing(&peer.file);
            //now have eligible pieces to request
            //let mut pieces = missing.into_iter().enumerate().filter(|&(_, x)| x).map(|(i, _)| i as u64).collect::<Vec<u64>>();
            //let piece_len = self.piece_length;
            //let mut bytes_requested = 0;
            //let mut pieces_request = 0;

            let mut msgs = Vec::new();
            let missing = self._get_missing(&peer.file);
            for (piece_index, _) in missing.into_iter().enumerate().filter(|&(_, val)| val){
                let mut pieces = NormalStrategy::piece_request(piece_index as u64, self.piece_length, MAX_BLOCK_SIZE);
                self.pieces_to_request.set(piece_index as usize, false);
                msgs.append(&mut pieces);
            }

            let req_actions = PeerAction(id, PeerStreamAction::SendMessages(msgs));
            actions.push(req_actions);
        }
        actions
    }

    fn piece_request(piece_index: u64, piece_len: u64, max_block_size: u64) -> Vec<PeerMsg> {
        let mut msgs = Vec::new();
        let mut bytes_requested = 0;

        if piece_len > max_block_size {
            let mut offset = 0;
            while offset < piece_len {
                if (offset + max_block_size > piece_len) {
                    msgs.push(PeerMsg::Request(piece_index as u32, offset as u32,
                        max_block_size as u32));
                } else {
                    msgs.push(PeerMsg::Request(piece_index as u32, offset as u32,
                        max_block_size as u32));
                }
                offset += max_block_size;
            }
        } else {
            msgs.push(PeerMsg::Request(piece_index as u32, 0, piece_len as u32));
        }

        msgs
    }

    fn _get_piece_from_req(&mut self, index: usize, begin: u32, offset: u32) -> Option<PeerMsg> {
        if self.partial_file.has_piece(index as usize) {
            let piece = self.partial_file.get_piece_mut(index as usize);
            return match piece.get_offset(begin as usize, offset as usize) {
                Some(piece_data) => {
                    let msg = PeerMsg::Piece(begin, offset, Vec::from(piece_data));
                    Some(msg)
                }
                _ => None,
            };
        }
        None
    }

    fn _make_order(&mut self, action: PeerAction) -> Order {
        self.next_order_id += 1;
        Order {order_id: self.next_order_id, action: action, status: OrderStatus::NotStarted}
    }

    fn _make_msg_order(&mut self, id: PeerId, msgs: Vec<PeerMsg>) -> Order {
        self.next_order_id += 1;
        let action = PeerAction(id, PeerStreamAction::SendMessages(msgs));
        Order {order_id: self.next_order_id, action: action, status: OrderStatus::NotStarted}
    }

    fn _get_missing(&self, peer_file: &PeerFile) -> BitVec {
        let mut missing = self.partial_file.bit_array();
        missing.negate();
        let mut them = peer_file.bit_array();
        missing.intersect(&them);
        missing.intersect(&self.pieces_to_request);
        missing
    }
}

impl Strategy for NormalStrategy {
    fn on_handshake(&mut self, id: PeerId) -> Vec<Order> {
        let peer = PeerState::new(self.num_pieces, id);
        self.peers.insert(id, peer);
        vec![]

    }
    fn on_choke(&mut self, id: PeerId) -> Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => peer.peer_choking = true,
            None => {}
        };
        vec![]
    }
    fn on_unchoke(&mut self, id: PeerId) -> Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => peer.peer_choking = false,
            None => {}
        };
        vec![]

    }
    fn on_interested(&mut self, id: PeerId) -> Vec<Order>  {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => peer.peer_interested = true,
            None => {}
        };
        vec![]

    }
    fn on_not_interested(&mut self, id: PeerId) -> Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => peer.peer_interested = false,
            None => {}
        };
        vec![]
    }

    fn on_have(&mut self, id: PeerId, piece_index: usize) -> Vec<Order> {
        let msgs = {
            match self.peers.get_mut(&id) {
                Some(ref mut peer) => {
                    peer.file.set(piece_index as usize, true);
                    let file_vec = peer.file.bit_array();
                    if let Some(true) = file_vec.get(piece_index) {
                        let p_msgs = NormalStrategy::piece_request(piece_index as u64, self.piece_length, MAX_BLOCK_SIZE);
                        p_msgs
                    } else {
                        return Vec::new();
                    }
                }
                None => return Vec::new()
            }
        };
        let p_orders = self._make_msg_order(id, msgs);
        return vec![p_orders];
    }

    fn on_bitfield(&mut self, id: PeerId, bitfield: BitVec) ->  Vec<Order> {
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => {
                    let limit = peer.file.bit_array().len();
                    for (i, bit) in bitfield.iter().enumerate()  {
                        if i >= limit {
                            break;
                        }
                        peer.file.set(i, bit);
                    }
                },
            None => {}
        };
        vec![]
    }
    fn on_request(&mut self, id: PeerId, index: u32, begin: u32, length: u32) -> Vec<Order> {
        let piece_result = self._get_piece_from_req(index as usize, begin, length);
        match self.peers.get_mut(&id) {
            Some(ref mut peer) => {
                let response = piece_result;
                match response {
                    Some(r) => unimplemented!(),
                    _ => Vec::new(),
                }
            },
            _ => Vec::new()
        }
    }

    fn on_piece(&mut self, id: PeerId, index: u32, begin: u32, block: Vec<u8>) -> Vec<Order> {
        self.partial_file.add_piece(index as usize, begin as usize, block);
        Vec::new()
    }

    fn on_cancel(&mut self, id: PeerId, index: u32, begin: u32, block: Vec<u8>) -> Vec<Order> {
        Vec::new()
    }

    fn on_port(&mut self, id: PeerId, port: u16) -> Vec<Order> {
        Vec::new()
    }

    fn query(&mut self, pending: Vec<&Order>, done: Vec<OrderResult>, peers: Vec<&PeerState>, file: &PartialFile)
        -> Vec<Order> {
        let actions = self.request_pieces(peers, file);
        let mut orders = Vec::new();

        for action in actions {
            orders.push(self._make_order(action));
            self.next_order_id += 1;
        }

        orders
    }

}

struct OrderInfo;
type OrderId = usize;

pub struct OrderResult {
    status: OrderStatus,
    order_id: OrderId
}

pub struct Order {
    status: OrderStatus,
    order_id: OrderId,
    pub action: PeerAction
}

impl Order {
    pub fn complete(&self, status: OrderStatus) -> OrderResult {
        OrderResult { order_id: self.order_id, status: status}
    }

    pub fn id(&self) -> OrderId {
        self.order_id
    }

    pub fn status(&self) -> OrderStatus {
        self.status
    }

    pub fn set_status(&mut self, status: OrderStatus) {
        self.status = status;
    }
}

#[derive(Eq, PartialEq, Clone, Copy)]
pub enum OrderStatus {
    NotStarted,
    InProgress,
    Failed,
    Done
}
<|endoftext|>


<commit_before>use ::{DeterministicRandomId, PersistentTypeId, ListedType, PersistentlyIdentifiedType, SimulationStateData, DataHandleTrait, DataTimelineCellTrait, ExtendedTime};
use ::stewards::{simple_full as steward_module};
use self::steward_module::{TimeSteward, Event, DataTimelineCellReadGuard, DataHandle, DataTimelineCell, Accessor, EventAccessor, FutureCleanupAccessor, SnapshotAccessor, simple_timeline};
use self::simple_timeline::{SimpleTimeline, GetVarying, tracking_query, tracking_query_ref, set, unset};

pub type Coordinate = u32;
pub type NumDimensions = u32;

pub trait BoundingBoxCollisionDetectable: PersistentlyIdentifiedType {
  type Steward: TimeSteward;
  type Object: SimulationStateData + PersistentlyIdentifiedType;
  type Space; // a way to distinguish if the same object can be put in multiple collision detectors of the same type. Can easily be () if not.

  const DIMENSIONS: NumDimensions;

  // An Object generally has to store some opaque data for the collision detector.
  // It would normally include a DataHandle to a tree node.
  // These are getter and setter methods for that data.
  fn get_collision_detector_data<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, object: &DataHandle<Self::Object>, space: &Self::Space)->Option<DataTimelineCellReadGuard<ObjectVarying<Self>>>;
  fn set_collision_detector_data<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, object: &DataHandle<Self::Object>, space: &Self::Space, data: Option<ObjectVarying<Self>>);

  fn calculate_current_bounding_box<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, object: &DataHandle<Self::Object>, space: &Self::Space)->BoundingBox;
  fn when_escapes<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, object: &DataHandle<Self::Object>, space: &Self::Space, BoundingBox)-><Self::Steward as TimeSteward>::Basics::Time;

  fn become_nearby<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, objects: [&DataHandle<Self::Object>; 2], space: &Self::Space) {}
  fn stop_being_nearby<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, objects: [&DataHandle<Self::Object>; 2], space: &Self::Space) {}
}

pub struct BoundingBox<B: BoundingBoxCollisionDetectable> {
  pub bounds: [[Coordinate; 2]; B::DIMENSIONS],
}

#[derive (Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
struct Node<B: BoundingBoxCollisionDetectable> {
  size_shift: u32,
  center: [Coordinate; 2],
  parent: Option<DataHandle <Node <B>>>,
  larger_cousins: [[Option<DataHandle <Node <B>>>; 2]; B::DIMENSIONS],
  varying: NodeVarying <B>,
}
impl<B: BoundingBoxCollisionDetectable> PersistentlyIdentifiedType for Node<B> {
  const ID: PersistentTypeId = PersistentTypeId(B::ID.0 ^ 0x7c4c8993671ba023);
}
#[derive (Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
struct NodeVarying<B: BoundingBoxCollisionDetectable> {
  children: [Option<DataHandle <Node <B>>>; 1<<B::DIMENSIONS],
  overlapping_live_nodes: Vec<DataHandle <B::Object>>,
  objects: Vec<DataHandle <B::Object>>,
}

pub struct ObjectVarying<B: BoundingBoxCollisionDetectable> {
  node: DataHandle <Node <B>>,
}
pub struct BoundingBoxCollisionDetector<B: BoundingBoxCollisionDetectable> {
  root: DataHandle <Node <B>>,
}

impl<B: BoundingBoxCollisionDetectable> BoundingBoxCollisionDetector<B> {
  fn insert<A: EventAccessor <Steward = B::Steward>>(accessor: &A, object: &DataHandle<B::Object>, space: &B::Space, location_hint: Option <& DataHandle<B::Object>>) {

  }
  fn remove<A: EventAccessor <Steward = B::Steward>>(accessor: &A, object: &DataHandle<B::Object>, space: &B::Space) {

  }
  fn neighbors<A: EventAccessor <Steward = B::Steward>>(accessor: &A, object: &DataHandle<B::Object>, space: &B::Space) -> Iter {

  }
}

#[derive (Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct EscapesBounds<B: BoundingBoxCollisionDetectable> {}
impl<B: BoundingBoxCollisionDetectable> PersistentlyIdentifiedType for EscapesBounds<B> {
  const ID: PersistentTypeId = PersistentTypeId(B::ID.0 ^ 0xb0cdbe951b688b70);
}
impl<B: BoundingBoxCollisionDetectable> Event for EscapesBounds<B> {
  type Steward = B::Steward;
  type ExecutionData = ();
  fn execute <Accessor: EventAccessor <Steward = Self::Steward>> (&self, accessor: &mut Accessor) {

  }

  fn undo <Accessor: FutureCleanupAccessor <Steward = Self::Steward>> (&self, accessor: &mut Accessor, _: ()) {
    unimplemented!()
  }
}

<commit_msg>More work on collision detection<commit_after>use ::{DeterministicRandomId, PersistentTypeId, ListedType, PersistentlyIdentifiedType, SimulationStateData, DataHandleTrait, DataTimelineCellTrait, ExtendedTime};
use ::stewards::{simple_full as steward_module};
use self::steward_module::{TimeSteward, Event, DataTimelineCellReadGuard, DataHandle, DataTimelineCell, Accessor, EventAccessor, FutureCleanupAccessor, SnapshotAccessor, simple_timeline};
use self::simple_timeline::{SimpleTimeline, GetVarying, tracking_query, tracking_query_ref, set, unset};

pub type Coordinate = u32;
pub type NumDimensions = u32;

pub trait BoundingBoxCollisionDetectable: PersistentlyIdentifiedType {
  type Steward: TimeSteward;
  type Object: SimulationStateData + PersistentlyIdentifiedType;
  type Space; // a way to distinguish if the same object can be put in multiple collision detectors of the same type. Can easily be () if not.

  const DIMENSIONS: NumDimensions;

  // An Object generally has to store some opaque data for the collision detector.
  // It would normally include a DataHandle to a tree node.
  // These are getter and setter methods for that data.
  fn get_collision_detector_data<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, object: &DataHandle<Self::Object>, space: &Self::Space)->Option<&ObjectData<Self>>>;
  fn set_collision_detector_data<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, object: &DataHandle<Self::Object>, space: &Self::Space, data: Option<ObjectData<Self>>);

  fn calculate_current_bounding_box<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, object: &DataHandle<Self::Object>, space: &Self::Space)->BoundingBox;
  fn when_escapes<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, object: &DataHandle<Self::Object>, space: &Self::Space, BoundingBox)-><Self::Steward as TimeSteward>::Basics::Time;

  fn become_nearby<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, objects: [&DataHandle<Self::Object>; 2], space: &Self::Space) {}
  fn stop_being_nearby<A: EventAccessor <Steward = Self::Steward>>(accessor: &A, objects: [&DataHandle<Self::Object>; 2], space: &Self::Space) {}
}

pub struct BoundingBox<B: BoundingBoxCollisionDetectable> {
  pub bounds: [[Coordinate; 2]; B::DIMENSIONS],
}
struct NodeBounds<B: BoundingBoxCollisionDetectable> {
  half_size_shift: u32,
  center: [Coordinate; B::DIMENSIONS],
}
fn smallest_containing_node_bounds <B: BoundingBoxCollisionDetectable> (bounds: & BoundingBox<B>)->NodeBounds <B> {
  unimplemented!()
}

#[derive (Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
struct Node<B: BoundingBoxCollisionDetectable> {
  bounds: NodeBounds<B>,
  parent: Option<DataHandle <Node <B>>>,
  larger_cousins: [[Option<DataHandle <Node <B>>>; 2]; B::DIMENSIONS],
  varying: NodeVarying <B>,
}
impl<B: BoundingBoxCollisionDetectable> PersistentlyIdentifiedType for Node<B> {
  const ID: PersistentTypeId = PersistentTypeId(B::ID.0 ^ 0x7c4c8993671ba023);
}
#[derive (Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
struct NodeVarying<B: BoundingBoxCollisionDetectable> {
  children: [Option<DataHandle <Node <B>>>; 1<<B::DIMENSIONS],
  overlapping_live_nodes: Vec<DataHandle <B::Object>>,
  objects: Vec<DataHandle <B::Object>>,
}

pub struct ObjectData<B: BoundingBoxCollisionDetectable> {
  varying: ObjectVarying<B>,
}
struct ObjectVarying<B: BoundingBoxCollisionDetectable> {
  node: DataHandle <Node <B>>,
}
pub struct BoundingBoxCollisionDetector<B: BoundingBoxCollisionDetectable> {
  root: DataHandle <Node <B>>,
}

impl<B: BoundingBoxCollisionDetectable> BoundingBoxCollisionDetector<B> {
  pub fn insert<A: EventAccessor <Steward = B::Steward>>(accessor: &A, object: &DataHandle<B::Object>, space: &B::Space, location_hint: Option <& DataHandle<B::Object>>) {

  }
  pub fn remove<A: EventAccessor <Steward = B::Steward>>(accessor: &A, object: &DataHandle<B::Object>, space: &B::Space) {

  }
  pub fn neighbors<A: EventAccessor <Steward = B::Steward>>(accessor: &A, object: &DataHandle<B::Object>, space: &B::Space) -> Iter {

  }
}

#[derive (Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct EscapesBounds<B: BoundingBoxCollisionDetectable> {}
impl<B: BoundingBoxCollisionDetectable> PersistentlyIdentifiedType for EscapesBounds<B> {
  const ID: PersistentTypeId = PersistentTypeId(B::ID.0 ^ 0xb0cdbe951b688b70);
}
impl<B: BoundingBoxCollisionDetectable> Event for EscapesBounds<B> {
  type Steward = B::Steward;
  type ExecutionData = ();
  fn execute <Accessor: EventAccessor <Steward = Self::Steward>> (&self, accessor: &mut Accessor) {

  }

  fn undo <Accessor: FutureCleanupAccessor <Steward = Self::Steward>> (&self, accessor: &mut Accessor, _: ()) {
    unimplemented!()
  }
}

impl<B: BoundingBoxCollisionDetectable> BoundingBoxCollisionDetector<B> {
  fn reposition <A: EventAccessor <Steward = B::Steward>> (accessor: &A, object: &DataHandle<B::Object>) {
    let varying = tracking_query (accessor, object.varying);
    let mut current_node = varying.node;
    let new_bounds = B::calculate_current_bounding_box (object);
    let destination_node_bounds = smallest_containing_node_bounds (new_bounds) ;
    let bigger_shift = max (current_node.bounds.half_size_shift, destination_node_bounds.half_size_shift);

    while current_node.bounds.half_size_shift < bigger_shift {
      current_node = current_node.parent.expect("All nodes except the root node have to have a parent, and we should never be trying to navigate to a node bigger than the root");
    }

    let mut destination_ancestor_bounds = destination_node_bounds;
    while destination_ancestor_bounds.half_size_shift < bigger_shift {
      destination_ancestor_bounds = parent_bounds(destination_ancestor_bounds);
    }

    while largest_single_dimension_distance (current_node.bounds, destination_ancestor_bounds) > (1 << destination_ancestor_bounds.half_size_shift) {
      destination_ancestor_bounds = parent_bounds(destination_ancestor_bounds);
      current_node = current_node.parent.expect("All nodes except the root node have to have a parent, and we should never be trying to navigate to a node bigger than the root");
    }

    if current_node.bounds != destination_ancestor_bounds {
      // they should now be the same size and half- or all-overlapping in each dimension.
    }
  }
}
<|endoftext|>


<commit_before>extern crate colored;
extern crate conllx;
extern crate dpar;
#[macro_use]
extern crate dpar_utils;
extern crate getopts;
extern crate stdinout;

use std::env::args;
use std::io::{BufRead, BufWriter, Write};
use std::process;

use colored::*;
use conllx::{HeadProjectivizer, Projectivize, ReadSentence};
use dpar::guide::Guide;
use dpar::system::{sentence_to_dependencies, ParserState, Transition, TransitionSystem};
use dpar::systems::{
    ArcEagerSystem, ArcHybridSystem, ArcStandardSystem, StackProjectiveSystem, StackSwapSystem,
};
use getopts::Options;
use stdinout::{Input, Output};

use dpar_utils::{OrExit, Result};

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] SYSTEM [INPUT]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help menu");
    let matches = opts.parse(&args[1..]).or_exit();

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    if matches.free.len() < 1 || matches.free.len() > 3 {
        print_usage(&program, opts);
        return;
    }

    let input = Input::from(matches.free.get(1));
    let reader = conllx::Reader::new(input.buf_read().or_exit());

    let output = Output::from(matches.free.get(2));
    let writer = BufWriter::new(output.write().or_exit());

    parse(&matches.free[0], reader, writer).or_exit();
}

fn parse<R, W>(system: &str, reader: conllx::Reader<R>, writer: BufWriter<W>) -> Result<()>
where
    R: BufRead,
    W: Write,
{
    match system {
        "arceager" => parse_with_system::<R, W, ArcEagerSystem>(reader, writer),
        "archybrid" => parse_with_system::<R, W, ArcHybridSystem>(reader, writer),
        "arcstandard" => parse_with_system::<R, W, ArcStandardSystem>(reader, writer),
        "stackproj" => parse_with_system::<R, W, StackProjectiveSystem>(reader, writer),
        "stackswap" => parse_with_system::<R, W, StackSwapSystem>(reader, writer),
        _ => {
            stderr!("Unsupported transition system: {}", system);
            process::exit(1);
        }
    }
}

fn parse_with_system<R, W, S>(reader: conllx::Reader<R>, mut writer: BufWriter<W>) -> Result<()>
where
    R: BufRead,
    W: Write,
    S: TransitionSystem,
{
    let projectivizer = HeadProjectivizer::new();

    for sentence in reader.sentences() {
        //let sentence = sentence;
        let sentence = projectivizer.projectivize(&sentence?)?;

        let gold_dependencies = sentence_to_dependencies(&sentence).or_exit();
        let mut oracle = S::oracle(&gold_dependencies);

        let mut state = ParserState::new(&sentence);
        while !S::is_terminal(&state) {
            let next_transition = oracle.best_transition(&state);
            writeln!(writer, "{}", format!("{:?}", next_transition).purple())?;
            writeln!(
                writer,
                "Stack: {}",
                state
                    .stack()
                    .iter()
                    .map(|&idx| state.tokens()[idx])
                    .collect::<Vec<_>>()
                    .join(", ")
            )?;
            writeln!(
                writer,
                "Buffer: {}",
                state
                    .buffer()
                    .iter()
                    .map(|&idx| state.tokens()[idx])
                    .collect::<Vec<_>>()
                    .join(", ")
            )?;
            next_transition.apply(&mut state);
        }
    }

    Ok(())
}
<commit_msg>Factor out printing code, print initial state.<commit_after>extern crate colored;
extern crate conllx;
extern crate dpar;
#[macro_use]
extern crate dpar_utils;
extern crate getopts;
extern crate stdinout;

use std::env::args;
use std::io::{BufRead, BufWriter, Write};
use std::process;

use colored::*;
use conllx::{HeadProjectivizer, Projectivize, ReadSentence};
use dpar::guide::Guide;
use dpar::system::{sentence_to_dependencies, ParserState, Transition, TransitionSystem};
use dpar::systems::{
    ArcEagerSystem, ArcHybridSystem, ArcStandardSystem, StackProjectiveSystem, StackSwapSystem,
};
use getopts::Options;
use stdinout::{Input, Output};

use dpar_utils::{OrExit, Result};

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] SYSTEM [INPUT]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help menu");
    let matches = opts.parse(&args[1..]).or_exit();

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    if matches.free.len() < 1 || matches.free.len() > 3 {
        print_usage(&program, opts);
        return;
    }

    let input = Input::from(matches.free.get(1));
    let reader = conllx::Reader::new(input.buf_read().or_exit());

    let output = Output::from(matches.free.get(2));
    let writer = BufWriter::new(output.write().or_exit());

    parse(&matches.free[0], reader, writer).or_exit();
}

fn parse<R, W>(system: &str, reader: conllx::Reader<R>, writer: BufWriter<W>) -> Result<()>
where
    R: BufRead,
    W: Write,
{
    match system {
        "arceager" => parse_with_system::<R, W, ArcEagerSystem>(reader, writer),
        "archybrid" => parse_with_system::<R, W, ArcHybridSystem>(reader, writer),
        "arcstandard" => parse_with_system::<R, W, ArcStandardSystem>(reader, writer),
        "stackproj" => parse_with_system::<R, W, StackProjectiveSystem>(reader, writer),
        "stackswap" => parse_with_system::<R, W, StackSwapSystem>(reader, writer),
        _ => {
            stderr!("Unsupported transition system: {}", system);
            process::exit(1);
        }
    }
}

fn parse_with_system<R, W, S>(reader: conllx::Reader<R>, mut writer: BufWriter<W>) -> Result<()>
where
    R: BufRead,
    W: Write,
    S: TransitionSystem,
{
    let projectivizer = HeadProjectivizer::new();

    for sentence in reader.sentences() {
        //let sentence = sentence;
        let sentence = projectivizer.projectivize(&sentence?)?;

        let gold_dependencies = sentence_to_dependencies(&sentence).or_exit();
        let mut oracle = S::oracle(&gold_dependencies);

        let mut state = ParserState::new(&sentence);

        // Print initial state.
        print_tokens(&mut writer, &state, Source::Stack)?;
        print_tokens(&mut writer, &state, Source::Buffer)?;

        while !S::is_terminal(&state) {
            let next_transition = oracle.best_transition(&state);
            next_transition.apply(&mut state);

            // Print transition and state.
            writeln!(writer, "{}", format!("{:?}", next_transition).purple())?;
            print_tokens(&mut writer, &state, Source::Stack)?;
            print_tokens(&mut writer, &state, Source::Buffer)?;
        }
    }

    Ok(())
}

enum Source {
    Buffer,
    Stack,
}

fn print_tokens<W>(writer: &mut W, state: &ParserState, source: Source) -> Result<()>
where
    W: Write,
{
    let prefix = match source {
        Source::Buffer => "Buffer",
        Source::Stack => "Stack",
    };

    let indices = match source {
        Source::Buffer => state.buffer(),
        Source::Stack => state.stack(),
    };

    writeln!(
        writer,
        "{}: {}",
        prefix,
        indices
            .iter()
            .map(|&idx| state.tokens()[idx])
            .collect::<Vec<_>>()
            .join(", ")
    )?;

    Ok(())
}
<|endoftext|>


<commit_before>use regex::Regex;

#[derive(Debug, PartialEq)]
pub struct Message {
    pub data: String,
}

impl Message {
    pub fn new(data: &str) -> Message {
        Message { data: data.to_string() }
    }

    pub fn decompress_v1(&self) -> u64 {
        let marker_finder: Regex = Regex::new(r"\((\d+)x(\d+)\)").unwrap();

        decompressed_string_length_v1(&self.data, marker_finder)
    }

    pub fn decompress_v2(&self) -> u64 {
        let marker_finder: Regex = Regex::new(r"\((\d+)x(\d+)\)").unwrap();

        decompress_string_v2(&self.data, &marker_finder)
    }
}

fn decompressed_string_length_v1(message: &str, marker_regex: Regex) -> u64 {
    let mut decompressed_length: u64 = 0;
    let mut str_index: usize = 0;

    while let Some(matched) = marker_regex.find(&message[str_index..]) {
        let captured = marker_regex.captures(&message[str_index..]).unwrap();

        decompressed_length += matched.start() as u64;

        let number_of_chars: usize = (&captured[1]).parse().unwrap();
        let number_of_repeats: usize = (&captured[2]).parse().unwrap();

        str_index += matched.end() + number_of_chars;

        decompressed_length += (number_of_repeats * number_of_chars) as u64;
    }

    if str_index < message.len() {
        decompressed_length += (message.len() - str_index) as u64;
    }

    decompressed_length
}

fn decompress_string_v2(message: &str, marker_regex: &Regex) -> u64 {
    let mut decompressed_length: u64 = 0;
    let mut str_index: usize = 0;

    while let Some(matched) = marker_regex.find(&message[str_index..]) {
        let captured = marker_regex.captures(&message[str_index..]).unwrap();

        decompressed_length += matched.start() as u64;

        let number_of_chars: usize = (&captured[1]).parse().unwrap();
        let number_of_repeats: u64 = (&captured[2]).parse().unwrap();

        str_index += matched.end() + number_of_chars;

        let number_to_repeat: u64 =
            decompress_string_v2(&message[(str_index - number_of_chars)..str_index],
                                 marker_regex);

        match number_of_repeats.checked_mul(number_to_repeat) {
            Some(num) => decompressed_length += num,
            None => println!("{}, {}", number_of_repeats, number_to_repeat),
        };
    }

    if str_index < message.len() {
        decompressed_length += (message.len() - str_index) as u64;
    }

    decompressed_length
}

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

    #[test]
    fn test_decompress_v1() {
        let test_data = vec![Message::new("ADVENT").decompress_v1(),
                             Message::new("A(1x5)BC").decompress_v1(),
                             Message::new("(3x3)XYZ").decompress_v1(),
                             Message::new("A(2x2)BCD(2x2)EFG").decompress_v1(),
                             Message::new("(6x1)(1x3)A").decompress_v1(),
                             Message::new("X(8x2)(3x3)ABCY").decompress_v1()];

        assert_eq!(test_data, vec![6, 7, 9, 11, 6, 18]);
    }

    #[test]
    fn test_decompress_v2() {
        let test_data =
            vec![Message::new("(3x3)XYZ").decompress_v2(),
                 Message::new("X(8x2)(3x3)ABCY").decompress_v2(),
                 Message::new("(27x12)(20x12)(13x14)(7x10)(1x12)A").decompress_v2(),
                 Message::new("(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN")
                     .decompress_v2()];

        assert_eq!(test_data, vec![9, 20, 241920, 445]);
    }
}<commit_msg>Changed it all to u64.<commit_after>use regex::Regex;

#[derive(Debug, PartialEq)]
pub struct Message {
    pub data: String,
}

impl Message {
    pub fn new(data: &str) -> Message {
        Message { data: data.to_string() }
    }

    pub fn decompress_v1(&self) -> u64 {
        let marker_finder: Regex = Regex::new(r"\((\d+)x(\d+)\)").unwrap();

        decompressed_string_length_v1(&self.data, marker_finder)
    }

    pub fn decompress_v2(&self) -> u64 {
        let marker_finder: Regex = Regex::new(r"\((\d+)x(\d+)\)").unwrap();

        decompress_string_v2(&self.data, &marker_finder)
    }
}

fn decompressed_string_length_v1(message: &str, marker_regex: Regex) -> u64 {
    let mut decompressed_length: u64 = 0;
    let mut str_index: usize = 0;

    while let Some(matched) = marker_regex.find(&message[str_index..]) {
        let captured = marker_regex.captures(&message[str_index..]).unwrap();

        decompressed_length += matched.start() as u64;

        let number_of_chars: usize = (&captured[1]).parse().unwrap();
        let number_of_repeats: usize = (&captured[2]).parse().unwrap();

        str_index += matched.end() + number_of_chars;

        decompressed_length += (number_of_repeats * number_of_chars) as u64;
    }

    if str_index < message.len() {
        decompressed_length += (message.len() - str_index) as u64;
    }

    decompressed_length
}

fn decompress_string_v2(message: &str, marker_regex: &Regex) -> u64 {
    let mut decompressed_length: u64 = 0;
    let mut str_index: usize = 0;

    while let Some(matched) = marker_regex.find(&message[str_index..]) {
        let captured = marker_regex.captures(&message[str_index..]).unwrap();

        decompressed_length += matched.start() as u64;

        let number_of_chars: usize = (&captured[1]).parse().unwrap();
        let number_of_repeats: u64 = (&captured[2]).parse().unwrap();

        str_index += matched.end() + number_of_chars;

        let number_to_repeat: u64 =
            decompress_string_v2(&message[(str_index - number_of_chars)..str_index],
                                 marker_regex);

        match number_of_repeats.checked_mul(number_to_repeat) {
            Some(num) => decompressed_length += num,
            None => println!("{}, {}", number_of_repeats, number_to_repeat),
        };
    }

    if str_index < message.len() {
        decompressed_length += (message.len() - str_index) as u64;
    }

    decompressed_length
}

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

    #[test]
    fn test_decompress_v1() {
        let test_data = vec![Message::new("ADVENT").decompress_v1(),
                             Message::new("A(1x5)BC").decompress_v1(),
                             Message::new("(3x3)XYZ").decompress_v1(),
                             Message::new("A(2x2)BCD(2x2)EFG").decompress_v1(),
                             Message::new("(6x1)(1x3)A").decompress_v1(),
                             Message::new("X(8x2)(3x3)ABCY").decompress_v1()];

        assert_eq!(test_data, vec![6, 7, 9, 11, 6, 18]);
    }

    #[test]
    fn test_decompress_v2() {
        let test_data =
            vec![Message::new("(3X3)XYZ").decompress_v2(),
                 Message::new("X(8x2)(3x3)ABCY").decompress_v2(),
                 Message::new("(27x12)(20x12)(13x14)(7x10)(1x12)A").decompress_v2(),
                 Message::new("(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN")
                     .decompress_v2()];

        assert_eq!(test_data, vec![9, 20, 241920, 445]);
    }
}<|endoftext|>


<commit_before>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(clippy::stutter))]

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(clippy::stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let eax;
    let ebx;
    let ecx;
    let edx;
    #[cfg(target_arch = "x86")]
    {
        asm!("cpuid"
             : "={eax}"(eax), "={ebx}"(ebx), "={ecx}"(ecx), "={edx}"(edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    }
    #[cfg(target_arch = "x86_64")]
    {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(eax), "={ebx}"(ebx), "={ecx}"(ecx), "={edx}"(edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    CpuidResult { eax, ebx, ecx, edx }
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_env = "sgx")]
    {
        false
    }
    #[cfg(all(not(target_env = "sgx"), target_arch = "x86_64"))]
    {
        true
    }
    #[cfg(all(not(target_env = "sgx"), target_arch = "x86"))]
    {
        // Optimization for i586 and i686 Rust targets which SSE enabled
        // and support cpuid:
        #[cfg(target_feature = "sse")]
        {
            true
        }

        // If SSE is not enabled, detect whether cpuid is available:
        #[cfg(not(target_feature = "sse"))]
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether
            // the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            let _temp: u32;
            asm!(r#"
                 # Read eflags into $0 and copy it into $1:
                 pushfd
                 pop     $0
                 mov     $1, $0
                 # Flip 21st bit of $0.
                 xor     $0, 0x200000
                 # Set eflags to the value of $0
                 #
                 # Bit 21st can only be modified if cpuid is available
                 push    $0
                 popfd          # A
                 # Read eflags into $0:
                 pushfd         # B
                 pop     $0
                 # xor with the original eflags sets the bits that
                 # have been modified:
                 xor     $0, $1
                 "#
                 : "=r"(result), "=r"(_temp)
                 :
                 : "cc", "memory"
                 : "intel");
            // There is a race between popfd (A) and pushfd (B)
            // where other bits beyond 21st may have been modified due to
            // interrupts, a debugger stepping through the asm, etc.
            //
            // Therefore, explicitly check whether the 21st bit
            // was modified or not.
            //
            // If the result is zero, the cpuid bit was not modified.
            // If the result is 0x200000 (non-zero), then the cpuid
            // was correctly modified and the CPU supports the cpuid
            // instruction:
            (result & 0x200000) != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

#[cfg(test)]
mod tests {
    use coresimd::x86::*;

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<commit_msg>Derive Debug for CpuidResult (#615)<commit_after>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(clippy::stutter))]

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(clippy::stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let eax;
    let ebx;
    let ecx;
    let edx;
    #[cfg(target_arch = "x86")]
    {
        asm!("cpuid"
             : "={eax}"(eax), "={ebx}"(ebx), "={ecx}"(ecx), "={edx}"(edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    }
    #[cfg(target_arch = "x86_64")]
    {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(eax), "={ebx}"(ebx), "={ecx}"(ecx), "={edx}"(edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    CpuidResult { eax, ebx, ecx, edx }
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_env = "sgx")]
    {
        false
    }
    #[cfg(all(not(target_env = "sgx"), target_arch = "x86_64"))]
    {
        true
    }
    #[cfg(all(not(target_env = "sgx"), target_arch = "x86"))]
    {
        // Optimization for i586 and i686 Rust targets which SSE enabled
        // and support cpuid:
        #[cfg(target_feature = "sse")]
        {
            true
        }

        // If SSE is not enabled, detect whether cpuid is available:
        #[cfg(not(target_feature = "sse"))]
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether
            // the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            let _temp: u32;
            asm!(r#"
                 # Read eflags into $0 and copy it into $1:
                 pushfd
                 pop     $0
                 mov     $1, $0
                 # Flip 21st bit of $0.
                 xor     $0, 0x200000
                 # Set eflags to the value of $0
                 #
                 # Bit 21st can only be modified if cpuid is available
                 push    $0
                 popfd          # A
                 # Read eflags into $0:
                 pushfd         # B
                 pop     $0
                 # xor with the original eflags sets the bits that
                 # have been modified:
                 xor     $0, $1
                 "#
                 : "=r"(result), "=r"(_temp)
                 :
                 : "cc", "memory"
                 : "intel");
            // There is a race between popfd (A) and pushfd (B)
            // where other bits beyond 21st may have been modified due to
            // interrupts, a debugger stepping through the asm, etc.
            //
            // Therefore, explicitly check whether the 21st bit
            // was modified or not.
            //
            // If the result is zero, the cpuid bit was not modified.
            // If the result is 0x200000 (non-zero), then the cpuid
            // was correctly modified and the CPU supports the cpuid
            // instruction:
            (result & 0x200000) != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

#[cfg(test)]
mod tests {
    use coresimd::x86::*;

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<|endoftext|>


<commit_before>#[macro_use]
pub mod types;

use self::types::*;
use common::combinator::Parser;
use common::util::*;
use std::iter::FromIterator;

pub fn tokenize<T: Iterator<Item = char>>(input: T) -> Result<Vec<Token>> {
    let mut l = Lexer::new(input);

    let mut result = Vec::default();

    loop {
        let _ = skip_whitespaces(&mut l);
        match l.preview() {
            None => break,
            _ => {
                result.push(try!(lex_token(&mut l)));
            }
        }
    }

    Ok(result)
}

fn skip_whitespaces(l: &mut Lexer) -> Result<Vec<char>> {
    l.many(|l| l.predicate(|x| [' ', '\t', '\n', '\r'].contains(x)))
}

fn lex_token(l: &mut Lexer) -> Result<Token> {
    l.choose(&[&lex_operator,
               &lex_punctuation,
               &lex_string,
               &lex_reserved_or_ident,
               &lex_integer,
               &lex_illegal])
}

macro_rules! parse_map {
    ($pat:expr, $tok:ident) => {
        &|l| {
            let pos = l.current_pos();
            let lit: String = try!(l.string($pat.chars()));
            Ok(token!($tok, pos.0, pos.1, lit))
        }
    }
}

fn lex_operator(l: &mut Lexer) -> Result<Token> {
    l.choose(&[parse_map!("==", Eq),
               parse_map!("=", Assign),
               parse_map!("+", Plus),
               parse_map!("-", Minus),
               parse_map!("*", Multiply),
               parse_map!("/", Divide),
               parse_map!("!=", NotEq),
               parse_map!("!", Not),
               parse_map!(">", GreaterThan),
               parse_map!("<", LessThan)])
}

fn lex_punctuation(l: &mut Lexer) -> Result<Token> {
    l.choose(&[parse_map!(":", Colon),
               parse_map!(";", SemiColon),
               parse_map!(",", Comma),
               parse_map!("(", LParen),
               parse_map!(")", RParen),
               parse_map!("{", LBrace),
               parse_map!("}", RBrace),
               parse_map!("[", LBracket),
               parse_map!("]", RBracket)])
}

fn lex_string(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let mut result = Vec::default();

    result.push(try!(l.atom('"')));
    loop {
        let c = try!(l.next());
        result.push(c);
        match c {
            '\\' => result.push(try!(l.next())),
            '"' => break,
            _ => continue,
        }
    }

    Ok(token!(StringLiteral, pos.0, pos.1, String::from_iter(result)))
}

fn lex_reserved_or_ident(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let fst = try!(l.predicate(is_letter)).to_string();
    let rest: String = try!(l.many(|l| l.predicate(is_letter_or_digit)));
    let name = fst + &rest;

    Ok(match name.as_ref() {
           "let" => token!(Let, pos.0, pos.1, name),
           "fn" => token!(Function, pos.0, pos.1, name),
           "if" => token!(If, pos.0, pos.1, name),
           "else" => token!(Else, pos.0, pos.1, name),
           "return" => token!(Return, pos.0, pos.1, name),
           "true" => token!(BoolLiteral, pos.0, pos.1, name),
           "false" => token!(BoolLiteral, pos.0, pos.1, name),
           _ => token!(Ident, pos.0, pos.1, name),
       })
}

fn lex_integer(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let lit: String = try!(l.many(|l| l.predicate(is_digit)));
    Ok(token!(IntLiteral, pos.0, pos.1, lit))
}

fn lex_illegal(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    Ok(token!(Illegal, pos.0, pos.1, try!(l.next())))
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fmt::Debug;

    fn lex(input: &str) -> Vec<Token> {
        tokenize(String::from(input).chars()).unwrap()
    }

    fn vec_eq<T: PartialEq + Debug>(xs: &Vec<T>, ys: &Vec<T>) {
        if xs.len() != ys.len() {
            panic!("{:?} != {:?}", xs, ys);
        }
        for i in 0..xs.len() {
            if xs[i] != ys[i] {
                panic!("{:?} != {:?}", xs, ys);
            }
        }
    }

    #[test]
    fn special_chars() {
        vec_eq(&lex("=+(){},;"),
               &vec![token!(Assign, 1, 1, '='),
                     token!(Plus, 1, 2, '+'),
                     token!(LParen, 1, 3, '('),
                     token!(RParen, 1, 4, ')'),
                     token!(LBrace, 1, 5, '{'),
                     token!(RBrace, 1, 6, '}'),
                     token!(Comma, 1, 7, ','),
                     token!(SemiColon, 1, 8, ';')]);
    }

    #[test]
    fn complex_code() {
        vec_eq(&lex("
let five = 5;
let ten = 10;
let add = fn(x, y) {
    x + y;
};
let result = add(five, ten);
               "),
               &vec![token!(Let, 2, 1, "let"),
                     token!(Ident, 2, 5, "five"),
                     token!(Assign, 2, 10, "="),
                     token!(IntLiteral, 2, 12, "5"),
                     token!(SemiColon, 2, 13, ";"),
                     token!(Let, 3, 1, "let"),
                     token!(Ident, 3, 5, "ten"),
                     token!(Assign, 3, 9, "="),
                     token!(IntLiteral, 3, 11, "10"),
                     token!(SemiColon, 3, 13, ";"),
                     token!(Let, 4, 1, "let"),
                     token!(Ident, 4, 5, "add"),
                     token!(Assign, 4, 9, "="),
                     token!(Function, 4, 11, "fn"),
                     token!(LParen, 4, 13, "("),
                     token!(Ident, 4, 14, "x"),
                     token!(Comma, 4, 15, ","),
                     token!(Ident, 4, 17, "y"),
                     token!(RParen, 4, 18, ")"),
                     token!(LBrace, 4, 20, "{"),
                     token!(Ident, 5, 5, "x"),
                     token!(Plus, 5, 7, "+"),
                     token!(Ident, 5, 9, "y"),
                     token!(SemiColon, 5, 10, ";"),
                     token!(RBrace, 6, 1, "}"),
                     token!(SemiColon, 6, 2, ";"),
                     token!(Let, 7, 1, "let"),
                     token!(Ident, 7, 5, "result"),
                     token!(Assign, 7, 12, "="),
                     token!(Ident, 7, 14, "add"),
                     token!(LParen, 7, 17, "("),
                     token!(Ident, 7, 18, "five"),
                     token!(Comma, 7, 22, ","),
                     token!(Ident, 7, 24, "ten"),
                     token!(RParen, 7, 27, ")"),
                     token!(SemiColon, 7, 28, ";")]);
    }

    #[test]
    fn complex_code2() {
        vec_eq(&lex("
if (a == 10) {
  return a;
} else if (a != 20) {
  return !a;
} else if (a > 20) {
  return -30 / 40 * 50;
} else if (a < 30) {
  return true;
}
return false;
                    "),
               &vec![token!(If, 2, 1, "if"),
                     token!(LParen, 2, 4, "("),
                     token!(Ident, 2, 5, "a"),
                     token!(Eq, 2, 7, "=="),
                     token!(IntLiteral, 2, 10, "10"),
                     token!(RParen, 2, 12, ")"),
                     token!(LBrace, 2, 14, "{"),
                     token!(Return, 3, 3, "return"),
                     token!(Ident, 3, 10, "a"),
                     token!(SemiColon, 3, 11, ";"),
                     token!(RBrace, 4, 1, "}"),
                     token!(Else, 4, 3, "else"),
                     token!(If, 4, 8, "if"),
                     token!(LParen, 4, 11, "("),
                     token!(Ident, 4, 12, "a"),
                     token!(NotEq, 4, 14, "!="),
                     token!(IntLiteral, 4, 17, "20"),
                     token!(RParen, 4, 19, ")"),
                     token!(LBrace, 4, 21, "{"),
                     token!(Return, 5, 3, "return"),
                     token!(Not, 5, 10, "!"),
                     token!(Ident, 5, 11, "a"),
                     token!(SemiColon, 5, 12, ";"),
                     token!(RBrace, 6, 1, "}"),
                     token!(Else, 6, 3, "else"),
                     token!(If, 6, 8, "if"),
                     token!(LParen, 6, 11, "("),
                     token!(Ident, 6, 12, "a"),
                     token!(GreaterThan, 6, 14, ">"),
                     token!(IntLiteral, 6, 16, "20"),
                     token!(RParen, 6, 18, ")"),
                     token!(LBrace, 6, 20, "{"),
                     token!(Return, 7, 3, "return"),
                     token!(Minus, 7, 10, "-"),
                     token!(IntLiteral, 7, 11, "30"),
                     token!(Divide, 7, 14, "/"),
                     token!(IntLiteral, 7, 16, "40"),
                     token!(Multiply, 7, 19, "*"),
                     token!(IntLiteral, 7, 21, "50"),
                     token!(SemiColon, 7, 23, ";"),
                     token!(RBrace, 8, 1, "}"),
                     token!(Else, 8, 3, "else"),
                     token!(If, 8, 8, "if"),
                     token!(LParen, 8, 11, "("),
                     token!(Ident, 8, 12, "a"),
                     token!(LessThan, 8, 14, "<"),
                     token!(IntLiteral, 8, 16, "30"),
                     token!(RParen, 8, 18, ")"),
                     token!(LBrace, 8, 20, "{"),
                     token!(Return, 9, 3, "return"),
                     token!(BoolLiteral, 9, 10, "true"),
                     token!(SemiColon, 9, 14, ";"),
                     token!(RBrace, 10, 1, "}"),
                     token!(Return, 11, 1, "return"),
                     token!(BoolLiteral, 11, 8, "false"),
                     token!(SemiColon, 11, 13, ";")]);
    }

    #[test]
    fn id_with_numbers() {
        vec_eq(&lex("hello2 hel301oo120"),
               &vec![token!(Ident, 1, 1, "hello2"),
                     token!(Ident, 1, 8, "hel301oo120")]);
    }

    #[test]
    fn string_literals() {
        vec_eq(&lex("\"foobar\""),
               &vec![token!(StringLiteral, 1, 1, "\"foobar\"")]);
        vec_eq(&lex("\"foo bar\""),
               &vec![token!(StringLiteral, 1, 1, "\"foo bar\"")]);
        vec_eq(&lex("\"foo\\nbar\""),
               &vec![token!(StringLiteral, 1, 1, "\"foo\\nbar\"")]);
        vec_eq(&lex("\"foo\\tbar\""),
               &vec![token!(StringLiteral, 1, 1, "\"foo\\tbar\"")]);
        vec_eq(&lex("\"foo\\\"bar\""),
               &vec![token!(StringLiteral, 1, 1, "\"foo\\\"bar\"")]);
    }

    #[test]
    fn array_tokens() {
        vec_eq(&lex("[1, 2];"),
               &vec![token!(LBracket, 1, 1, "["),
                     token!(IntLiteral, 1, 2, "1"),
                     token!(Comma, 1, 3, ","),
                     token!(IntLiteral, 1, 5, "2"),
                     token!(RBracket, 1, 6, "]"),
                     token!(SemiColon, 1, 7, ";")]);
    }

    #[test]
    fn hash_tokens() {
        vec_eq(&lex("{\"hello\": \"world\"}"),
               &vec![token!(LBrace, 1, 1, "{"),
                    token!(StringLiteral, 1, 2, "\"hello\""),
                    token!(Colon, 1, 9, ":"),
                    token!(StringLiteral, 1, 11, "\"world\""),
                    token!(RBrace, 1, 18, "}")]);
    }
}
<commit_msg>Remove vec_eq in lexer tests<commit_after>#[macro_use]
pub mod types;

use self::types::*;
use common::combinator::Parser;
use common::util::*;
use std::iter::FromIterator;

pub fn tokenize<T: Iterator<Item = char>>(input: T) -> Result<Vec<Token>> {
    let mut l = Lexer::new(input);

    let mut result = Vec::default();

    loop {
        let _ = skip_whitespaces(&mut l);
        match l.preview() {
            None => break,
            _ => {
                result.push(try!(lex_token(&mut l)));
            }
        }
    }

    Ok(result)
}

fn skip_whitespaces(l: &mut Lexer) -> Result<Vec<char>> {
    l.many(|l| l.predicate(|x| [' ', '\t', '\n', '\r'].contains(x)))
}

fn lex_token(l: &mut Lexer) -> Result<Token> {
    l.choose(&[&lex_operator,
               &lex_punctuation,
               &lex_string,
               &lex_reserved_or_ident,
               &lex_integer,
               &lex_illegal])
}

macro_rules! parse_map {
    ($pat:expr, $tok:ident) => {
        &|l| {
            let pos = l.current_pos();
            let lit: String = try!(l.string($pat.chars()));
            Ok(token!($tok, pos.0, pos.1, lit))
        }
    }
}

fn lex_operator(l: &mut Lexer) -> Result<Token> {
    l.choose(&[parse_map!("==", Eq),
               parse_map!("=", Assign),
               parse_map!("+", Plus),
               parse_map!("-", Minus),
               parse_map!("*", Multiply),
               parse_map!("/", Divide),
               parse_map!("!=", NotEq),
               parse_map!("!", Not),
               parse_map!(">", GreaterThan),
               parse_map!("<", LessThan)])
}

fn lex_punctuation(l: &mut Lexer) -> Result<Token> {
    l.choose(&[parse_map!(":", Colon),
               parse_map!(";", SemiColon),
               parse_map!(",", Comma),
               parse_map!("(", LParen),
               parse_map!(")", RParen),
               parse_map!("{", LBrace),
               parse_map!("}", RBrace),
               parse_map!("[", LBracket),
               parse_map!("]", RBracket)])
}

fn lex_string(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let mut result = Vec::default();

    result.push(try!(l.atom('"')));
    loop {
        let c = try!(l.next());
        result.push(c);
        match c {
            '\\' => result.push(try!(l.next())),
            '"' => break,
            _ => continue,
        }
    }

    Ok(token!(StringLiteral, pos.0, pos.1, String::from_iter(result)))
}

fn lex_reserved_or_ident(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let fst = try!(l.predicate(is_letter)).to_string();
    let rest: String = try!(l.many(|l| l.predicate(is_letter_or_digit)));
    let name = fst + &rest;

    Ok(match name.as_ref() {
           "let" => token!(Let, pos.0, pos.1, name),
           "fn" => token!(Function, pos.0, pos.1, name),
           "if" => token!(If, pos.0, pos.1, name),
           "else" => token!(Else, pos.0, pos.1, name),
           "return" => token!(Return, pos.0, pos.1, name),
           "true" => token!(BoolLiteral, pos.0, pos.1, name),
           "false" => token!(BoolLiteral, pos.0, pos.1, name),
           _ => token!(Ident, pos.0, pos.1, name),
       })
}

fn lex_integer(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let lit: String = try!(l.many(|l| l.predicate(is_digit)));
    Ok(token!(IntLiteral, pos.0, pos.1, lit))
}

fn lex_illegal(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    Ok(token!(Illegal, pos.0, pos.1, try!(l.next())))
}

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

    fn lex(input: &str) -> Vec<Token> {
        tokenize(String::from(input).chars()).unwrap()
    }

    #[test]
    fn special_chars() {
        assert_eq!(&lex("=+(){},;"),
                   &vec![token!(Assign, 1, 1, '='),
                         token!(Plus, 1, 2, '+'),
                         token!(LParen, 1, 3, '('),
                         token!(RParen, 1, 4, ')'),
                         token!(LBrace, 1, 5, '{'),
                         token!(RBrace, 1, 6, '}'),
                         token!(Comma, 1, 7, ','),
                         token!(SemiColon, 1, 8, ';')]);
    }

    #[test]
    fn complex_code() {
        assert_eq!(&lex("
let five = 5;
let ten = 10;
let add = fn(x, y) {
    x + y;
};
let result = add(five, ten);
               "),
                   &vec![token!(Let, 2, 1, "let"),
                         token!(Ident, 2, 5, "five"),
                         token!(Assign, 2, 10, "="),
                         token!(IntLiteral, 2, 12, "5"),
                         token!(SemiColon, 2, 13, ";"),
                         token!(Let, 3, 1, "let"),
                         token!(Ident, 3, 5, "ten"),
                         token!(Assign, 3, 9, "="),
                         token!(IntLiteral, 3, 11, "10"),
                         token!(SemiColon, 3, 13, ";"),
                         token!(Let, 4, 1, "let"),
                         token!(Ident, 4, 5, "add"),
                         token!(Assign, 4, 9, "="),
                         token!(Function, 4, 11, "fn"),
                         token!(LParen, 4, 13, "("),
                         token!(Ident, 4, 14, "x"),
                         token!(Comma, 4, 15, ","),
                         token!(Ident, 4, 17, "y"),
                         token!(RParen, 4, 18, ")"),
                         token!(LBrace, 4, 20, "{"),
                         token!(Ident, 5, 5, "x"),
                         token!(Plus, 5, 7, "+"),
                         token!(Ident, 5, 9, "y"),
                         token!(SemiColon, 5, 10, ";"),
                         token!(RBrace, 6, 1, "}"),
                         token!(SemiColon, 6, 2, ";"),
                         token!(Let, 7, 1, "let"),
                         token!(Ident, 7, 5, "result"),
                         token!(Assign, 7, 12, "="),
                         token!(Ident, 7, 14, "add"),
                         token!(LParen, 7, 17, "("),
                         token!(Ident, 7, 18, "five"),
                         token!(Comma, 7, 22, ","),
                         token!(Ident, 7, 24, "ten"),
                         token!(RParen, 7, 27, ")"),
                         token!(SemiColon, 7, 28, ";")]);
    }

    #[test]
    fn complex_code2() {
        assert_eq!(&lex("
if (a == 10) {
  return a;
} else if (a != 20) {
  return !a;
} else if (a > 20) {
  return -30 / 40 * 50;
} else if (a < 30) {
  return true;
}
return false;
                    "),
                   &vec![token!(If, 2, 1, "if"),
                         token!(LParen, 2, 4, "("),
                         token!(Ident, 2, 5, "a"),
                         token!(Eq, 2, 7, "=="),
                         token!(IntLiteral, 2, 10, "10"),
                         token!(RParen, 2, 12, ")"),
                         token!(LBrace, 2, 14, "{"),
                         token!(Return, 3, 3, "return"),
                         token!(Ident, 3, 10, "a"),
                         token!(SemiColon, 3, 11, ";"),
                         token!(RBrace, 4, 1, "}"),
                         token!(Else, 4, 3, "else"),
                         token!(If, 4, 8, "if"),
                         token!(LParen, 4, 11, "("),
                         token!(Ident, 4, 12, "a"),
                         token!(NotEq, 4, 14, "!="),
                         token!(IntLiteral, 4, 17, "20"),
                         token!(RParen, 4, 19, ")"),
                         token!(LBrace, 4, 21, "{"),
                         token!(Return, 5, 3, "return"),
                         token!(Not, 5, 10, "!"),
                         token!(Ident, 5, 11, "a"),
                         token!(SemiColon, 5, 12, ";"),
                         token!(RBrace, 6, 1, "}"),
                         token!(Else, 6, 3, "else"),
                         token!(If, 6, 8, "if"),
                         token!(LParen, 6, 11, "("),
                         token!(Ident, 6, 12, "a"),
                         token!(GreaterThan, 6, 14, ">"),
                         token!(IntLiteral, 6, 16, "20"),
                         token!(RParen, 6, 18, ")"),
                         token!(LBrace, 6, 20, "{"),
                         token!(Return, 7, 3, "return"),
                         token!(Minus, 7, 10, "-"),
                         token!(IntLiteral, 7, 11, "30"),
                         token!(Divide, 7, 14, "/"),
                         token!(IntLiteral, 7, 16, "40"),
                         token!(Multiply, 7, 19, "*"),
                         token!(IntLiteral, 7, 21, "50"),
                         token!(SemiColon, 7, 23, ";"),
                         token!(RBrace, 8, 1, "}"),
                         token!(Else, 8, 3, "else"),
                         token!(If, 8, 8, "if"),
                         token!(LParen, 8, 11, "("),
                         token!(Ident, 8, 12, "a"),
                         token!(LessThan, 8, 14, "<"),
                         token!(IntLiteral, 8, 16, "30"),
                         token!(RParen, 8, 18, ")"),
                         token!(LBrace, 8, 20, "{"),
                         token!(Return, 9, 3, "return"),
                         token!(BoolLiteral, 9, 10, "true"),
                         token!(SemiColon, 9, 14, ";"),
                         token!(RBrace, 10, 1, "}"),
                         token!(Return, 11, 1, "return"),
                         token!(BoolLiteral, 11, 8, "false"),
                         token!(SemiColon, 11, 13, ";")]);
    }

    #[test]
    fn id_with_numbers() {
        assert_eq!(&lex("hello2 hel301oo120"),
                   &vec![token!(Ident, 1, 1, "hello2"),
                         token!(Ident, 1, 8, "hel301oo120")]);
    }

    #[test]
    fn string_literals() {
        assert_eq!(&lex("\"foobar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foobar\"")]);
        assert_eq!(&lex("\"foo bar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo bar\"")]);
        assert_eq!(&lex("\"foo\\nbar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\nbar\"")]);
        assert_eq!(&lex("\"foo\\tbar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\tbar\"")]);
        assert_eq!(&lex("\"foo\\\"bar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\\"bar\"")]);
    }

    #[test]
    fn array_tokens() {
        assert_eq!(&lex("[1, 2];"),
                   &vec![token!(LBracket, 1, 1, "["),
                         token!(IntLiteral, 1, 2, "1"),
                         token!(Comma, 1, 3, ","),
                         token!(IntLiteral, 1, 5, "2"),
                         token!(RBracket, 1, 6, "]"),
                         token!(SemiColon, 1, 7, ";")]);
    }

    #[test]
    fn hash_tokens() {
        assert_eq!(&lex("{\"hello\": \"world\"}"),
                   &vec![token!(LBrace, 1, 1, "{"),
                        token!(StringLiteral, 1, 2, "\"hello\""),
                        token!(Colon, 1, 9, ":"),
                        token!(StringLiteral, 1, 11, "\"world\""),
                        token!(RBrace, 1, 18, "}")]);
    }
}
<|endoftext|>


<commit_before>#![feature(core)]

extern crate iron;
extern crate "handlebars-iron" as hbs;
extern crate "rustc-serialize" as serialize;

use iron::prelude::*;
use iron::{status};
use hbs::{Template, HandlebarsEngine};
use serialize::json::{ToJson, Json};
use std::collections::BTreeMap;

/// this function is for making example data
fn make_data() -> BTreeMap<String, Json> {
    let mut data = BTreeMap::new();

    data.insert("year".to_string(), "2015".to_json());

    let mut teams = Vec::new();

    for v in vec![("Jiangsu", 43u16), ("Beijing", 27u16), ("Guangzhou", 22u16), ("Shandong", 12u16)].iter() {
        let (name, score) = *v;
        let mut t = BTreeMap::new();
        t.insert("name".to_string(), name.to_json());
        t.insert("score".to_string(), score.to_json());
        teams.push(t)
    }

    data.insert("teams".to_string(), teams.to_json());
    data
}

/// the handler
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = make_data();
    resp.set_mut(Template::new("index", data)).set_mut(status::Ok);
    Ok(resp)
}

fn main() {
    let mut chain = Chain::new(hello_world);
    chain.link_after(HandlebarsEngine::new("./examples/templates/", ".hbs"));
    Iron::new(chain).listen("localhost:3000").unwrap();
}
<commit_msg>(fix) rustup: remove feature gate<commit_after>extern crate iron;
extern crate "handlebars-iron" as hbs;
extern crate "rustc-serialize" as serialize;

use iron::prelude::*;
use iron::{status};
use hbs::{Template, HandlebarsEngine};
use serialize::json::{ToJson, Json};
use std::collections::BTreeMap;

/// this function is for making example data
fn make_data() -> BTreeMap<String, Json> {
    let mut data = BTreeMap::new();

    data.insert("year".to_string(), "2015".to_json());

    let mut teams = Vec::new();

    for v in vec![("Jiangsu", 43u16), ("Beijing", 27u16), ("Guangzhou", 22u16), ("Shandong", 12u16)].iter() {
        let (name, score) = *v;
        let mut t = BTreeMap::new();
        t.insert("name".to_string(), name.to_json());
        t.insert("score".to_string(), score.to_json());
        teams.push(t)
    }

    data.insert("teams".to_string(), teams.to_json());
    data
}

/// the handler
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = make_data();
    resp.set_mut(Template::new("index", data)).set_mut(status::Ok);
    Ok(resp)
}

fn main() {
    let mut chain = Chain::new(hello_world);
    chain.link_after(HandlebarsEngine::new("./examples/templates/", ".hbs"));
    Iron::new(chain).listen("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before>use pact_matching::models::{Pact, Interaction, Request, OptionalBody, PactSpecification};
use pact_matching::models::matchingrules::*;
use pact_matching::models::generators::*;
use pact_matching::models::parse_query_string;

use std::collections::{BTreeMap, HashMap};
use log::{log, debug, warn};
use hyper::{Body, Response, Server, Error};
use hyper::header::ToStrError;
use hyper::service::service_fn_ok;
use futures::future;
use futures::future::Future;
use futures::stream::Stream;

enum MockRequestError {
    InvalidHeaderEncoding,
    RequestBodyError
}

fn extract_path(uri: &hyper::Uri) -> String {
    uri.path_and_query()
        .map(|path_and_query| path_and_query.path())
        .unwrap_or("/")
        .into()
}

fn extract_query_string(uri: &hyper::Uri) -> Option<HashMap<String, Vec<String>>> {
    uri.path_and_query()
        .and_then(|path_and_query| path_and_query.query())
        .and_then(|query| parse_query_string(&query.into()))
}

fn extract_headers(headers: &hyper::HeaderMap) -> Result<Option<HashMap<String, String>>, MockRequestError> {
    if headers.len() > 0 {
        let result: Result<HashMap<String, String>, MockRequestError> = headers.keys()
            .map(|name| -> Result<(String, String), MockRequestError> {
                let values = headers.get_all(name);
                let mut iter = values.iter();

                let first_value = iter.next().unwrap();

                if iter.next().is_some() {
                    warn!("Multiple headers associated with '{}', but only the first is used", name);
                }

                Ok((
                    name.as_str().into(),
                    first_value.to_str()
                        .map_err(|err| MockRequestError::InvalidHeaderEncoding)?
                        .into()
                    )
                )
            })
            .collect();

        result.map(|map| Some(map))
    } else {
        Ok(None)
    }
}

pub fn extract_body(chunk: hyper::Chunk) -> OptionalBody {
    let bytes = chunk.into_bytes();
    if bytes.len() > 0 {
        OptionalBody::Present(bytes.to_vec())
    } else {
        OptionalBody::Empty
    }
}

fn hyper_request_to_pact_request(req: hyper::Request<Body>) -> impl Future<Item = Request, Error = MockRequestError> {
    let method = req.method().to_string();
    let path = extract_path(req.uri());
    let query = extract_query_string(req.uri());
    let headers = extract_headers(req.headers());

    future::done(headers)
        .and_then(move |headers| {
            req.into_body()
                .concat2()
                .map_err(|_| MockRequestError::RequestBodyError)
                .map(|body_chunk| (headers, body_chunk))
        })
        .and_then(|(headers, body_chunk)|
            Ok(Request {
                method: method,
                path: path,
                query: query,
                headers: headers,
                body: extract_body(body_chunk),
                matching_rules: MatchingRules::default(),
                generators: Generators::default()
            })
        )
}

pub fn start(
    id: String,
    pact: Pact,
    port: u16,
    shutdown: impl Future<Item = (), Error = ()>,
) -> (impl Future<Item = (), Error = Error>, u16) {
    let addr = ([0, 0, 0, 0], port).into();
    let server = Server::bind(&addr)
        .serve(|| {
            service_fn_ok(|req| {
                debug!("Creating pact request from hyper request");
                let req = hyper_request_to_pact_request(req);
                Response::new(Body::from("Hello World"))
            })
        });

    let port = server.local_addr().port();

    (server.with_graceful_shutdown(shutdown), port)
}
<commit_msg>handle_request function<commit_after>use pact_matching::models::{Pact, Interaction, Request, OptionalBody, PactSpecification};
use pact_matching::models::matchingrules::*;
use pact_matching::models::generators::*;
use pact_matching::models::parse_query_string;

use std::collections::{BTreeMap, HashMap};
use std::sync::Arc;
use log::{log, debug, warn};
use hyper::{Body, Response, Server, Error};
use hyper::service::service_fn;
use futures::future;
use futures::future::Future;
use futures::stream::Stream;

enum MockRequestError {
    InvalidHeaderEncoding,
    RequestBodyError
}

fn extract_path(uri: &hyper::Uri) -> String {
    uri.path_and_query()
        .map(|path_and_query| path_and_query.path())
        .unwrap_or("/")
        .into()
}

fn extract_query_string(uri: &hyper::Uri) -> Option<HashMap<String, Vec<String>>> {
    uri.path_and_query()
        .and_then(|path_and_query| path_and_query.query())
        .and_then(|query| parse_query_string(&query.into()))
}

fn extract_headers(headers: &hyper::HeaderMap) -> Result<Option<HashMap<String, String>>, MockRequestError> {
    if headers.len() > 0 {
        let result: Result<HashMap<String, String>, MockRequestError> = headers.keys()
            .map(|name| -> Result<(String, String), MockRequestError> {
                let values = headers.get_all(name);
                let mut iter = values.iter();

                let first_value = iter.next().unwrap();

                if iter.next().is_some() {
                    warn!("Multiple headers associated with '{}', but only the first is used", name);
                }

                Ok((
                    name.as_str().into(),
                    first_value.to_str()
                        .map_err(|err| MockRequestError::InvalidHeaderEncoding)?
                        .into()
                    )
                )
            })
            .collect();

        result.map(|map| Some(map))
    } else {
        Ok(None)
    }
}

pub fn extract_body(chunk: hyper::Chunk) -> OptionalBody {
    let bytes = chunk.into_bytes();
    if bytes.len() > 0 {
        OptionalBody::Present(bytes.to_vec())
    } else {
        OptionalBody::Empty
    }
}

fn hyper_request_to_pact_request(req: hyper::Request<Body>) -> impl Future<Item = Request, Error = MockRequestError> {
    let method = req.method().to_string();
    let path = extract_path(req.uri());
    let query = extract_query_string(req.uri());
    let headers = extract_headers(req.headers());

    future::done(headers)
        .and_then(move |headers| {
            req.into_body()
                .concat2()
                .map_err(|_| MockRequestError::RequestBodyError)
                .map(|body_chunk| (headers, body_chunk))
        })
        .and_then(|(headers, body_chunk)|
            Ok(Request {
                method: method,
                path: path,
                query: query,
                headers: headers,
                body: extract_body(body_chunk),
                matching_rules: MatchingRules::default(),
                generators: Generators::default()
            })
        )
}

fn handle_request(
    req: hyper::Request<Body>,
    pact: Arc<Pact>,
) -> impl Future<Item = Response<Body>, Error = Error> {
    debug!("Creating pact request from hyper request");
    let req = hyper_request_to_pact_request(req);
    future::ok(Response::new(Body::from("Hello World")))
}

pub fn start(
    id: String,
    pact: Pact,
    port: u16,
    shutdown: impl Future<Item = (), Error = ()>,
) -> (impl Future<Item = (), Error = Error>, u16) {
    let pact = Arc::new(pact);

    let addr = ([0, 0, 0, 0], port).into();
    let server = Server::bind(&addr)
        .serve(move || {
            let pact = pact.clone();
            service_fn(move |req| {
                handle_request(req, pact.clone())
            })
        });

    let port = server.local_addr().port();

    (server.with_graceful_shutdown(shutdown), port)
}
<|endoftext|>


<commit_before>use SymbolProvider;
use addr2line::Context;
use breakpad_symbols::FrameSymbolizer;
use failure::Error;
use gimli::{EndianRcSlice, RunTimeEndian};
use memmap;
use minidump::Module;
use object::{self, Object};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs::File;

#[derive(Default)]
pub struct DwarfSymbolizer {
    /// A mapping of lookups of symbol files, where the key is the path to the binary.
    known_modules: RefCell<HashMap<String, Option<Context<EndianRcSlice<RunTimeEndian>>>>>,
}

fn locate_symbols(path: &str) -> Result<Context<EndianRcSlice<RunTimeEndian>>, Error> {
    let f = File::open(path)?;
    let buf = unsafe { memmap::Mmap::map(&f)? };
    let obj = object::File::parse(&*buf).map_err(|_| format_err!("Failed to parse {}", path))?;
    if obj.has_debug_symbols() {
        let context = Context::new(&obj)
            .map_err(|_| format_err!("Failed to load debug symbols for {}", path))?;
        Ok(context)
    } else {
        //TODO: use moria
        bail!("No debug symbols in {}", path)
    }
}

impl DwarfSymbolizer {
    pub fn new() -> DwarfSymbolizer {
        Default::default()
    }
}

impl SymbolProvider for DwarfSymbolizer {
    fn fill_symbol(&self, module: &Module, frame: &mut FrameSymbolizer) {
        let path = module.code_file();
        let k = path.as_ref();
        if !self.known_modules.borrow().contains_key(k) {
            self.known_modules
                .borrow_mut()
                .insert(path.clone().into_owned(), locate_symbols(&path).ok());
        }
        if let Some(&mut Some(ref mut map)) = self.known_modules.borrow_mut().get_mut(k) {
            let addr = frame.get_instruction();
            if let Ok(Some((source_file, line, func))) = map.locate(addr) {
                //TODO: get base address for line
                frame.set_source_file(&source_file.to_string_lossy(), line.unwrap_or(0) as u32, 0);
                if let Some(ref func) = func {
                    //TODO: get base address for function
                    frame.set_function(&func, 0);
                }
            }
        }
    }
}
<commit_msg>More addr2line 0.7 fixes<commit_after>use SymbolProvider;
use addr2line::{Context, Frame, Location};
use breakpad_symbols::FrameSymbolizer;
use failure::Error;
use gimli::{EndianRcSlice, RunTimeEndian};
use memmap;
use minidump::Module;
use object::{self, Object};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs::File;

#[derive(Default)]
pub struct DwarfSymbolizer {
    /// A mapping of lookups of symbol files, where the key is the path to the binary.
    known_modules: RefCell<HashMap<String, Option<Context<EndianRcSlice<RunTimeEndian>>>>>,
}

fn locate_symbols(path: &str) -> Result<Context<EndianRcSlice<RunTimeEndian>>, Error> {
    let f = File::open(path)?;
    let buf = unsafe { memmap::Mmap::map(&f)? };
    let obj = object::File::parse(&*buf).map_err(|_| format_err!("Failed to parse {}", path))?;
    if obj.has_debug_symbols() {
        let context = Context::new(&obj)
            .map_err(|_| format_err!("Failed to load debug symbols for {}", path))?;
        Ok(context)
    } else {
        //TODO: use moria
        bail!("No debug symbols in {}", path)
    }
}

impl DwarfSymbolizer {
    pub fn new() -> DwarfSymbolizer {
        Default::default()
    }
}

impl SymbolProvider for DwarfSymbolizer {
    fn fill_symbol(&self, module: &Module, frame: &mut FrameSymbolizer) {
        let path = module.code_file();
        let k = path.as_ref();
        if !self.known_modules.borrow().contains_key(k) {
            self.known_modules
                .borrow_mut()
                .insert(path.clone().into_owned(), locate_symbols(&path).ok());
        }
        if let Some(&mut Some(ref mut map)) = self.known_modules.borrow_mut().get_mut(k) {
            let addr = frame.get_instruction();
            if let Ok(mut iter) = map.find_frames(addr) {
                while let Ok(Some(Frame { function: Some(func), location: Some(Location { file: Some(source_file), line, .. }) })) = iter.next() {
                    //TODO: get base address for line
                    frame.set_source_file(&source_file, line.unwrap_or(0) as u32, 0);
                    //TODO: get base address for function
                    if let Ok(name) = func.demangle() {
                        frame.set_function(&name, 0);
                        break;
                    }
                }
            }
        }
    }
}
<|endoftext|>