<commit_before>use crate::HashStableContext;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::AtomicRef;
use rustc_index::vec::Idx;
use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decoder, Encoder};
use std::borrow::Borrow;
use std::fmt;

rustc_index::newtype_index! {
    pub struct CrateId {
        ENCODABLE = custom
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CrateNum {
    /// A special `CrateNum` that we use for the `tcx.rcache` when decoding from
    /// the incr. comp. cache.
    ReservedForIncrCompCache,
    Index(CrateId),
}

/// Item definitions in the currently-compiled crate would have the `CrateNum`
/// `LOCAL_CRATE` in their `DefId`.
pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0));

impl Idx for CrateNum {
    #[inline]
    fn new(value: usize) -> Self {
        CrateNum::Index(Idx::new(value))
    }

    #[inline]
    fn index(self) -> usize {
        match self {
            CrateNum::Index(idx) => Idx::index(idx),
            _ => panic!("Tried to get crate index of {:?}", self),
        }
    }
}

impl CrateNum {
    pub fn new(x: usize) -> CrateNum {
        CrateNum::from_usize(x)
    }

    pub fn from_usize(x: usize) -> CrateNum {
        CrateNum::Index(CrateId::from_usize(x))
    }

    pub fn from_u32(x: u32) -> CrateNum {
        CrateNum::Index(CrateId::from_u32(x))
    }

    pub fn as_usize(self) -> usize {
        match self {
            CrateNum::Index(id) => id.as_usize(),
            _ => panic!("tried to get index of non-standard crate {:?}", self),
        }
    }

    pub fn as_u32(self) -> u32 {
        match self {
            CrateNum::Index(id) => id.as_u32(),
            _ => panic!("tried to get index of non-standard crate {:?}", self),
        }
    }

    pub fn as_def_id(&self) -> DefId {
        DefId { krate: *self, index: CRATE_DEF_INDEX }
    }
}

impl fmt::Display for CrateNum {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
            CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
        }
    }
}

/// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
/// Therefore, make sure to include the context when encode a `CrateNum`.
impl rustc_serialize::UseSpecializedEncodable for CrateNum {
    fn default_encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
        e.emit_u32(self.as_u32())
    }
}
impl rustc_serialize::UseSpecializedDecodable for CrateNum {
    fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
        Ok(CrateNum::from_u32(d.read_u32()?))
    }
}

impl ::std::fmt::Debug for CrateNum {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        match self {
            CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
            CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
        }
    }
}

#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)]
#[derive(HashStable_Generic)]
pub struct DefPathHash(pub Fingerprint);

impl Borrow<Fingerprint> for DefPathHash {
    #[inline]
    fn borrow(&self) -> &Fingerprint {
        &self.0
    }
}

rustc_index::newtype_index! {
    /// A DefIndex is an index into the hir-map for a crate, identifying a
    /// particular definition. It should really be considered an interned
    /// shorthand for a particular DefPath.
    pub struct DefIndex {
        DEBUG_FORMAT = "DefIndex({})",

        /// The crate root is always assigned index 0 by the AST Map code,
        /// thanks to `NodeCollector::new`.
        const CRATE_DEF_INDEX = 0,
    }
}

impl rustc_serialize::UseSpecializedEncodable for DefIndex {}
impl rustc_serialize::UseSpecializedDecodable for DefIndex {}

/// A `DefId` identifies a particular *definition*, by combining a crate
/// index and a def index.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
pub struct DefId {
    pub krate: CrateNum,
    pub index: DefIndex,
}

impl DefId {
    /// Makes a local `DefId` from the given `DefIndex`.
    #[inline]
    pub fn local(index: DefIndex) -> DefId {
        DefId { krate: LOCAL_CRATE, index }
    }

    #[inline]
    pub fn is_local(self) -> bool {
        self.krate == LOCAL_CRATE
    }

    #[inline]
    pub fn as_local(self) -> Option<LocalDefId> {
        if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None }
    }

    #[inline]
    pub fn expect_local(self) -> LocalDefId {
        self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self))
    }

    pub fn is_top_level_module(self) -> bool {
        self.is_local() && self.index == CRATE_DEF_INDEX
    }
}

impl rustc_serialize::UseSpecializedEncodable for DefId {
    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        let krate = u64::from(self.krate.as_u32());
        let index = u64::from(self.index.as_u32());
        s.emit_u64((krate << 32) | index)
    }
}
impl rustc_serialize::UseSpecializedDecodable for DefId {
    fn default_decode<D: Decoder>(d: &mut D) -> Result<DefId, D::Error> {
        let def_id = d.read_u64()?;
        let krate = CrateNum::from_u32((def_id >> 32) as u32);
        let index = DefIndex::from_u32((def_id & 0xffffffff) as u32);
        Ok(DefId { krate, index })
    }
}

pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()
}

pub static DEF_ID_DEBUG: AtomicRef<fn(DefId, &mut fmt::Formatter<'_>) -> fmt::Result> =
    AtomicRef::new(&(default_def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));

impl fmt::Debug for DefId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (*DEF_ID_DEBUG)(*self, f)
    }
}

rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId);

/// A LocalDefId is equivalent to a DefId with `krate == LOCAL_CRATE`. Since
/// we encode this information in the type, we can ensure at compile time that
/// no DefIds from upstream crates get thrown into the mix. There are quite a
/// few cases where we know that only DefIds from the local crate are expected
/// and a DefId from a different crate would signify a bug somewhere. This
/// is when LocalDefId comes in handy.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LocalDefId {
    pub local_def_index: DefIndex,
}

impl Idx for LocalDefId {
    #[inline]
    fn new(idx: usize) -> Self {
        LocalDefId { local_def_index: Idx::new(idx) }
    }
    #[inline]
    fn index(self) -> usize {
        self.local_def_index.index()
    }
}

impl LocalDefId {
    #[inline]
    pub fn to_def_id(self) -> DefId {
        DefId { krate: LOCAL_CRATE, index: self.local_def_index }
    }

    #[inline]
    pub fn is_top_level_module(self) -> bool {
        self.local_def_index == CRATE_DEF_INDEX
    }
}

impl fmt::Debug for LocalDefId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.to_def_id().fmt(f)
    }
}

impl rustc_serialize::UseSpecializedEncodable for LocalDefId {}
impl rustc_serialize::UseSpecializedDecodable for LocalDefId {}

impl<CTX: HashStableContext> HashStable<CTX> for DefId {
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
        hcx.hash_def_id(*self, hasher)
    }
}
<commit_msg>Impl `From<LocalDefId>` for `DefId`<commit_after>use crate::HashStableContext;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::AtomicRef;
use rustc_index::vec::Idx;
use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decoder, Encoder};
use std::borrow::Borrow;
use std::fmt;

rustc_index::newtype_index! {
    pub struct CrateId {
        ENCODABLE = custom
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CrateNum {
    /// A special `CrateNum` that we use for the `tcx.rcache` when decoding from
    /// the incr. comp. cache.
    ReservedForIncrCompCache,
    Index(CrateId),
}

/// Item definitions in the currently-compiled crate would have the `CrateNum`
/// `LOCAL_CRATE` in their `DefId`.
pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0));

impl Idx for CrateNum {
    #[inline]
    fn new(value: usize) -> Self {
        CrateNum::Index(Idx::new(value))
    }

    #[inline]
    fn index(self) -> usize {
        match self {
            CrateNum::Index(idx) => Idx::index(idx),
            _ => panic!("Tried to get crate index of {:?}", self),
        }
    }
}

impl CrateNum {
    pub fn new(x: usize) -> CrateNum {
        CrateNum::from_usize(x)
    }

    pub fn from_usize(x: usize) -> CrateNum {
        CrateNum::Index(CrateId::from_usize(x))
    }

    pub fn from_u32(x: u32) -> CrateNum {
        CrateNum::Index(CrateId::from_u32(x))
    }

    pub fn as_usize(self) -> usize {
        match self {
            CrateNum::Index(id) => id.as_usize(),
            _ => panic!("tried to get index of non-standard crate {:?}", self),
        }
    }

    pub fn as_u32(self) -> u32 {
        match self {
            CrateNum::Index(id) => id.as_u32(),
            _ => panic!("tried to get index of non-standard crate {:?}", self),
        }
    }

    pub fn as_def_id(&self) -> DefId {
        DefId { krate: *self, index: CRATE_DEF_INDEX }
    }
}

impl fmt::Display for CrateNum {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
            CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
        }
    }
}

/// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
/// Therefore, make sure to include the context when encode a `CrateNum`.
impl rustc_serialize::UseSpecializedEncodable for CrateNum {
    fn default_encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
        e.emit_u32(self.as_u32())
    }
}
impl rustc_serialize::UseSpecializedDecodable for CrateNum {
    fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
        Ok(CrateNum::from_u32(d.read_u32()?))
    }
}

impl ::std::fmt::Debug for CrateNum {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        match self {
            CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
            CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
        }
    }
}

#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)]
#[derive(HashStable_Generic)]
pub struct DefPathHash(pub Fingerprint);

impl Borrow<Fingerprint> for DefPathHash {
    #[inline]
    fn borrow(&self) -> &Fingerprint {
        &self.0
    }
}

rustc_index::newtype_index! {
    /// A DefIndex is an index into the hir-map for a crate, identifying a
    /// particular definition. It should really be considered an interned
    /// shorthand for a particular DefPath.
    pub struct DefIndex {
        DEBUG_FORMAT = "DefIndex({})",

        /// The crate root is always assigned index 0 by the AST Map code,
        /// thanks to `NodeCollector::new`.
        const CRATE_DEF_INDEX = 0,
    }
}

impl rustc_serialize::UseSpecializedEncodable for DefIndex {}
impl rustc_serialize::UseSpecializedDecodable for DefIndex {}

/// A `DefId` identifies a particular *definition*, by combining a crate
/// index and a def index.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
pub struct DefId {
    pub krate: CrateNum,
    pub index: DefIndex,
}

impl DefId {
    /// Makes a local `DefId` from the given `DefIndex`.
    #[inline]
    pub fn local(index: DefIndex) -> DefId {
        DefId { krate: LOCAL_CRATE, index }
    }

    #[inline]
    pub fn is_local(self) -> bool {
        self.krate == LOCAL_CRATE
    }

    #[inline]
    pub fn as_local(self) -> Option<LocalDefId> {
        if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None }
    }

    #[inline]
    pub fn expect_local(self) -> LocalDefId {
        self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self))
    }

    pub fn is_top_level_module(self) -> bool {
        self.is_local() && self.index == CRATE_DEF_INDEX
    }
}

impl rustc_serialize::UseSpecializedEncodable for DefId {
    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        let krate = u64::from(self.krate.as_u32());
        let index = u64::from(self.index.as_u32());
        s.emit_u64((krate << 32) | index)
    }
}
impl rustc_serialize::UseSpecializedDecodable for DefId {
    fn default_decode<D: Decoder>(d: &mut D) -> Result<DefId, D::Error> {
        let def_id = d.read_u64()?;
        let krate = CrateNum::from_u32((def_id >> 32) as u32);
        let index = DefIndex::from_u32((def_id & 0xffffffff) as u32);
        Ok(DefId { krate, index })
    }
}

pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()
}

pub static DEF_ID_DEBUG: AtomicRef<fn(DefId, &mut fmt::Formatter<'_>) -> fmt::Result> =
    AtomicRef::new(&(default_def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));

impl fmt::Debug for DefId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (*DEF_ID_DEBUG)(*self, f)
    }
}

rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId);

/// A LocalDefId is equivalent to a DefId with `krate == LOCAL_CRATE`. Since
/// we encode this information in the type, we can ensure at compile time that
/// no DefIds from upstream crates get thrown into the mix. There are quite a
/// few cases where we know that only DefIds from the local crate are expected
/// and a DefId from a different crate would signify a bug somewhere. This
/// is when LocalDefId comes in handy.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LocalDefId {
    pub local_def_index: DefIndex,
}

impl Idx for LocalDefId {
    #[inline]
    fn new(idx: usize) -> Self {
        LocalDefId { local_def_index: Idx::new(idx) }
    }
    #[inline]
    fn index(self) -> usize {
        self.local_def_index.index()
    }
}

impl LocalDefId {
    #[inline]
    pub fn to_def_id(self) -> DefId {
        DefId { krate: LOCAL_CRATE, index: self.local_def_index }
    }

    #[inline]
    pub fn is_top_level_module(self) -> bool {
        self.local_def_index == CRATE_DEF_INDEX
    }
}

impl fmt::Debug for LocalDefId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.to_def_id().fmt(f)
    }
}

impl From<LocalDefId> for DefId {
    fn from(v: LocalDefId) -> Self {
        v.to_def_id()
    }
}

impl rustc_serialize::UseSpecializedEncodable for LocalDefId {}
impl rustc_serialize::UseSpecializedDecodable for LocalDefId {}

impl<CTX: HashStableContext> HashStable<CTX> for DefId {
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
        hcx.hash_def_id(*self, hasher)
    }
}
<|endoftext|>


<commit_before>use database::models::AutoReply;
use filters::Filter;
use error::*;

use diesel::prelude::*;

use serenity::client::{Context, EventHandler};
use serenity::model::id::{ChannelId, GuildId, UserId};
use serenity::model::channel::{Channel, Message};
use serenity::model::guild::{Role, Member};
use serenity::model::misc::Mentionable;

use chrono::Utc;

use std::sync::Mutex;
use std::collections::HashMap;

#[derive(Default)]
pub struct AutoReplyListener {
  last_sends: Mutex<HashMap<(UserId, i32), i64>>
}

enum UserIdOrMember {
  UserId(UserId),
  Member(Member)
}

impl EventHandler for AutoReplyListener {
  fn guild_member_addition(&self, _: Context, guild: GuildId, member: Member) {
    let inner = move || {
      let replies: Vec<AutoReply> = ::bot::CONNECTION.with(|c| {
        use database::schema::auto_replies::dsl;
        dsl::auto_replies
          .filter(dsl::server_id.eq(guild.0.to_string())
            .and(dsl::on_join.eq(true)))
          .load(c)
          .chain_err(|| "could not load auto_replies")
      })?;
      let user = UserIdOrMember::Member(member.clone());
      self.receive(replies, user, guild)
    };
    if let Err(e) = inner() {
      warn!("error in AutoReplyListener: {}", e);
    }
  }

  fn message(&self, _: Context, m: Message) {
    let inner = move || {
      let replies: Vec<AutoReply> = ::bot::CONNECTION.with(|c| {
        use database::schema::auto_replies::dsl;
        dsl::auto_replies
          .filter(dsl::channel_id.eq(m.channel_id.0.to_string())
            .and(dsl::on_join.eq(false)))
          .load(c)
          .chain_err(|| "could not load auto_replies")
      })?;
      let user = UserIdOrMember::UserId(m.author.id);
      let guild = match m.channel_id.get() {
        Ok(Channel::Guild(c)) => c.read().guild_id,
        Ok(_) => bail!("wrong type of channel for auto reply"),
        Err(e) => bail!("could not get channel for auto reply: {}", e)
      };
      self.receive(replies, user, guild)
    };
    if let Err(e) = inner() {
      warn!("error in AutoReplyListener: {}", e);
      return;
    }
  }
}

impl AutoReplyListener {
  fn receive(&self, replies: Vec<AutoReply>, user: UserIdOrMember, guild: GuildId) -> Result<()> {
    let live_server = match guild.find() {
      Some(g) => g.read().clone(),
      None => bail!("could not get guild from cache")
    };
    let member = match user {
      UserIdOrMember::Member(m) => m,
      UserIdOrMember::UserId(u) => match live_server.members.iter().find(|&(id, _)| *id == u) {
        Some((_, m)) => m.clone(),
        None => bail!("could not find member for auto reply")
      }
    };
    let user_id = member.user.read().id;
    let roles: Vec<Role> = live_server.roles.values().cloned().collect();
    let mut last_sends = self.last_sends.lock().unwrap();
    for reply in replies {
      if let Some(ref filters_string) = reply.filters {
        match filters_string.split(' ').map(Filter::parse).collect::<Option<Vec<_>>>() {
          Some(filters) => if !filters.iter().all(|f| f.matches(&member, &roles)) {
            continue;
          },
          None => warn!("invalid filters: `{}`", filters_string)
        }
      }
      let last_send = last_sends.entry((user_id, reply.id)).or_insert(0);
      if *last_send + i64::from(reply.delay) >= Utc::now().timestamp() {
        continue;
      }
      ChannelId(*reply.channel_id).send_message(|c| c.embed(|e| e.description(&reply.message.replace("{mention}", &member.mention())))).ok();
      *last_send = Utc::now().timestamp();
    }
    Ok(())
  }
}
<commit_msg>fix: don't reply to self<commit_after>use database::models::AutoReply;
use filters::Filter;
use error::*;

use diesel::prelude::*;

use serenity::client::{Context, EventHandler};
use serenity::model::id::{ChannelId, GuildId, UserId};
use serenity::model::channel::{Channel, Message};
use serenity::model::guild::{Role, Member};
use serenity::model::misc::Mentionable;

use chrono::Utc;

use std::sync::Mutex;
use std::collections::HashMap;

#[derive(Default)]
pub struct AutoReplyListener {
  last_sends: Mutex<HashMap<(UserId, i32), i64>>
}

enum UserIdOrMember {
  UserId(UserId),
  Member(Member)
}

impl EventHandler for AutoReplyListener {
  fn guild_member_addition(&self, _: Context, guild: GuildId, member: Member) {
    let inner = move || {
      let replies: Vec<AutoReply> = ::bot::CONNECTION.with(|c| {
        use database::schema::auto_replies::dsl;
        dsl::auto_replies
          .filter(dsl::server_id.eq(guild.0.to_string())
            .and(dsl::on_join.eq(true)))
          .load(c)
          .chain_err(|| "could not load auto_replies")
      })?;
      let user = UserIdOrMember::Member(member.clone());
      self.receive(replies, user, guild)
    };
    if let Err(e) = inner() {
      warn!("error in AutoReplyListener: {}", e);
    }
  }

  fn message(&self, _: Context, m: Message) {
    if m.author.id == ::serenity::CACHE.read().user.id {
      return;
    }
    let inner = move || {
      let replies: Vec<AutoReply> = ::bot::CONNECTION.with(|c| {
        use database::schema::auto_replies::dsl;
        dsl::auto_replies
          .filter(dsl::channel_id.eq(m.channel_id.0.to_string())
            .and(dsl::on_join.eq(false)))
          .load(c)
          .chain_err(|| "could not load auto_replies")
      })?;
      let user = UserIdOrMember::UserId(m.author.id);
      let guild = match m.channel_id.get() {
        Ok(Channel::Guild(c)) => c.read().guild_id,
        Ok(_) => bail!("wrong type of channel for auto reply"),
        Err(e) => bail!("could not get channel for auto reply: {}", e)
      };
      self.receive(replies, user, guild)
    };
    if let Err(e) = inner() {
      warn!("error in AutoReplyListener: {}", e);
      return;
    }
  }
}

impl AutoReplyListener {
  fn receive(&self, replies: Vec<AutoReply>, user: UserIdOrMember, guild: GuildId) -> Result<()> {
    let live_server = match guild.find() {
      Some(g) => g.read().clone(),
      None => bail!("could not get guild from cache")
    };
    let member = match user {
      UserIdOrMember::Member(m) => m,
      UserIdOrMember::UserId(u) => match live_server.members.iter().find(|&(id, _)| *id == u) {
        Some((_, m)) => m.clone(),
        None => bail!("could not find member for auto reply")
      }
    };
    let user_id = member.user.read().id;
    let roles: Vec<Role> = live_server.roles.values().cloned().collect();
    let mut last_sends = self.last_sends.lock().unwrap();
    for reply in replies {
      if let Some(ref filters_string) = reply.filters {
        match filters_string.split(' ').map(Filter::parse).collect::<Option<Vec<_>>>() {
          Some(filters) => if !filters.iter().all(|f| f.matches(&member, &roles)) {
            continue;
          },
          None => warn!("invalid filters: `{}`", filters_string)
        }
      }
      let last_send = last_sends.entry((user_id, reply.id)).or_insert(0);
      if *last_send + i64::from(reply.delay) >= Utc::now().timestamp() {
        continue;
      }
      ChannelId(*reply.channel_id).send_message(|c| c.embed(|e| e.description(&reply.message.replace("{mention}", &member.mention())))).ok();
      *last_send = Utc::now().timestamp();
    }
    Ok(())
  }
}
<|endoftext|>


<commit_before>#[cfg(test)]
#[macro_use]
extern crate matches;

pub mod error;
pub mod pdu;
<commit_msg>Added documentation for the ul crate.<commit_after>//! This crates contains the types and methods needed to interact with the DICOM upper-layer protocol.
//!
//! It is very low level and not usable as is.
//!
//! Eventually, a finite-state-machine and higher-level SCU/SCP helpers will be added that will make
//! interacting with these types more idiomatic and friendly.

#[cfg(test)]
#[macro_use]
extern crate matches;

pub mod error;
pub mod pdu;
<|endoftext|>


<commit_before>use super::super::message::*;
use super::*;
use bytes::{Buf, BufMut, BytesMut, BigEndian, IntoBuf};
use tokio_io::codec::Decoder;

use std::io::{ Error, ErrorKind, Result };

pub struct SquiddyDecoder;

impl Decoder for SquiddyDecoder {
    type Item = Message;
    type Error = Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Message>> {
        if buf.len() == 0 {
            return Err(Error::new(ErrorKind::InvalidData, "Received empty message"))
        }

        let mut local_buf = buf.split_to(OPCODE_LENGTH).into_buf();
        //
        if buf.len() > 1 {
            let opcode = local_buf.get_u16::<BigEndian>();

            match OpCode::from(opcode) {
                OpCode::ServerHello => match SquiddyDecoder::decode_protocol_version(buf) {
                    // Everything is alright, let's return the protocol version
                    Some(version) => Ok(Some(Message::ServerHello(version))),
                    // Protocol version is not right, whole message is rejected
                    None => Err(Error::from(ErrorKind::InvalidData))
                },
                OpCode::ClientHello => match SquiddyDecoder::decode_client_name(buf) {
                    Ok(client_name) => Ok(Some(Message::ClientHello(client_name))),
                    Err(error) => Err(error)
                },
                // We don't even know what message this was
                OpCode::Invalid => Err(Error::new(ErrorKind::InvalidData, format!("Unknown opcode: {}", opcode)))
            }
        } else {
            // We've requested reading from the buffer but there are no more bytes left :(
            Err(Error::from(ErrorKind::UnexpectedEof))
        }
    }
}

impl SquiddyDecoder {

    // TODO refactor return type to generate meaningful error messages instead of None
    fn decode_protocol_version(buf: &mut BytesMut) -> Option<ProtocolVersion> {
        if buf.len() >= 1 {
            let mut version_buf = buf.split_to(2).into_buf();

            Some((version_buf.get_u8(), version_buf.get_u8()))
        } else {
            None
        }
     }

     // TODO refactor return type to generate meaningful error messages instead of None
     fn decode_client_name(buf: &mut BytesMut) -> Result<ClientName> {
         if buf.len() > 0 {
            let name_len = buf.split_to(1).into_buf().get_u8() as usize;

            if name_len <= MAX_CLIENT_NAME_LENGTH as usize && buf.len() >= name_len {
                let name_bytes = buf.split_to(name_len);

                String::from_utf8(name_bytes.as_ref().to_vec()).map_err(|e| Error::new(ErrorKind::Other, e))
            } else {
                Err(Error::new(ErrorKind::InvalidData, format!("Client name length exceeds maximum value: {} MAX: {}", name_len, MAX_CLIENT_NAME_LENGTH)))
            }
        } else {
            Err(Error::new(ErrorKind::InvalidData, "Empty buffer"))
        }
     }
}
<commit_msg>Fixed some clippy warnings and improved some error handling<commit_after>use super::super::message::*;
use super::*;
use bytes::{Buf, BytesMut, BigEndian, IntoBuf};
use tokio_io::codec::Decoder;

use std::io::{ Error, ErrorKind, Result };

pub struct SquiddyDecoder;

impl Decoder for SquiddyDecoder {
    type Item = Message;
    type Error = Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Message>> {
        if buf.is_empty() {
            return Err(Error::new(ErrorKind::InvalidData, "Received empty message"))
        }

        let mut local_buf = buf.split_to(OPCODE_LENGTH).into_buf();
        //
        if buf.len() > 1 {
            let opcode = local_buf.get_u16::<BigEndian>();

            match OpCode::from(opcode) {
                OpCode::ServerHello => match SquiddyDecoder::decode_protocol_version(buf) {
                    // Everything is alright, let's return the protocol version
                    Some(version) => Ok(Some(Message::ServerHello(version))),
                    // Protocol version is not right, whole message is rejected
                    None => Err(Error::from(ErrorKind::InvalidData))
                },
                OpCode::ClientHello => match SquiddyDecoder::decode_client_name(buf) {
                    Ok(client_name) => Ok(Some(Message::ClientHello(client_name))),
                    Err(error) => Err(error)
                },
                // We don't even know what message this was
                OpCode::Invalid => Err(Error::new(ErrorKind::InvalidData, format!("Unknown opcode: {}", opcode)))
            }
        } else {
            // We've requested reading from the buffer but there are no more bytes left :(
            Err(Error::from(ErrorKind::UnexpectedEof))
        }
    }
}

impl SquiddyDecoder {

    // TODO refactor return type to generate meaningful error messages instead of None
    fn decode_protocol_version(buf: &mut BytesMut) -> Option<ProtocolVersion> {
        if !buf.is_empty() {
            let mut version_buf = buf.split_to(2).into_buf();

            Some((version_buf.get_u8(), version_buf.get_u8()))
        } else {
            None
        }
     }

     fn decode_client_name(buf: &mut BytesMut) -> Result<ClientName> {
         if !buf.is_empty() {
            let name_len = buf.split_to(1).into_buf().get_u8() as usize;

            if name_len <= MAX_CLIENT_NAME_LENGTH as usize && buf.len() >= name_len {
                let name_bytes = buf.split_to(name_len);

                String::from_utf8(name_bytes.as_ref().to_vec()).map_err(|e| Error::new(ErrorKind::Other, e))
            } else {
                Err(Error::new(ErrorKind::InvalidData, format!("Client name length exceeds maximum value: {} MAX: {}", name_len, MAX_CLIENT_NAME_LENGTH)))
            }
        } else {
            Err(Error::new(ErrorKind::UnexpectedEof, "Empty buffer"))
        }
     }
}
<|endoftext|>


<commit_before>//! Mock request dispatcher and credentials for unit testing rusoto AWS service clients
//!
//! All rusoto generated service clients come with a constuctor function named `new_with` which
//! accepts three arguments
//!
//! * A `rusoto_core::DispatchSignedRequest` implementation
//! * A `rusoto_core::credential::ProvideAwsCredentials` implementation
//! * A `rusoto_core::Region`
//!
//! This crate provides mock implementations to satisfy the first two.
//!
//! # Example
//!
//! The following is an example for the `rusoto_s3` crate but should
//! work for all service crates just the same. The code is commented
//! out for illustration but also to avoid a cyclic dependency in this crate.
//!
//! ```rust
//! extern crate rusoto_mock;
//! // extern crate rusoto_s3;
//!
//! use rusoto_mock::{MockCredentialsProvider, MockRequestDispatcher, MockResponseReader};
//!
//! fn main() {
//!    // let s3 = rusoto_s3::S3Client::new_with(
//!    //   MockRequestDispatcher::default().with_body(
//!    //      MockResponseReader::read_response("test-data", "s3-response.json")
//!    //   ),
//!    //   MockCredentialsProvider,
//!    //   Default::default()
//!    // );
//! }
//! ```
#![deny(missing_docs)]
extern crate chrono;
extern crate futures;
extern crate http;
extern crate rusoto_core;
extern crate serde;
extern crate serde_json;

use std::fs::File;
use std::io::Read;
use std::time::Duration;

use futures::future::{ok, err, FutureResult};
use http::{HeaderMap, header::HeaderName, HttpTryFrom, StatusCode};
use rusoto_core::credential::{AwsCredentials, CredentialsError, ProvideAwsCredentials};
use rusoto_core::request::HttpResponse;
use rusoto_core::signature::SignedRequest;
use rusoto_core::{ByteStream, DispatchSignedRequest, HttpDispatchError};
use serde::Serialize;

/// Provides a set of credentials that always resolve
/// successfully
pub struct MockCredentialsProvider;

impl ProvideAwsCredentials for MockCredentialsProvider {
    type Future = FutureResult<AwsCredentials, CredentialsError>;

    fn credentials(&self) -> Self::Future {
        ok(AwsCredentials::new("mock_key", "mock_secret", None, None))
    }
}

/// Composes mock API responses
///
/// A Default is provided which returns an successful response with an empty body
///
/// These can be constructed using either a Default implementation or
///  with the [with_status](method.with_status) function.
///
#[derive(Default)]
pub struct MockRequestDispatcher {
    outcome: RequestOutcome,
    body: Vec<u8>,
    headers: HeaderMap<String>,
    request_checker: Option<Box<Fn(&SignedRequest) + Send + Sync>>,
}

enum RequestOutcome {
  Performed(StatusCode),
  Failed(HttpDispatchError),
}

impl Default for RequestOutcome {
  fn default() -> RequestOutcome {
    RequestOutcome::Performed(StatusCode::default())
  }
}

impl MockRequestDispatcher {
    /// Returns a instance that mocks the status code that would
    /// be returned from AWS
    pub fn with_status(status: u16) -> MockRequestDispatcher {
        MockRequestDispatcher {
            outcome: RequestOutcome::Performed(StatusCode::try_from(status).unwrap()),
            ..MockRequestDispatcher::default()
        }
    }

    /// Mocks the service request failing with a communications error
    pub fn with_dispatch_error(error: HttpDispatchError) -> MockRequestDispatcher {
      MockRequestDispatcher {
          outcome: RequestOutcome::Failed(error),
          ..MockRequestDispatcher::default()
      }
    }

    /// Mocks the service response body what would be
    /// returned from AWS
    pub fn with_body(mut self, body: &str) -> MockRequestDispatcher {
        self.body = body.as_bytes().to_vec();
        self
    }

    /// Mocks the json serialized response body what would be
    /// returned from AWS
    pub fn with_json_body<B>(mut self, body: B) -> MockRequestDispatcher
    where
        B: Serialize,
    {
        self.body = serde_json::to_vec(&body).expect("failed to deserialize into json");
        self
    }

    /// Mocks the signed request checking applied to a request before sending
    /// to AWS
    pub fn with_request_checker<F>(mut self, checker: F) -> MockRequestDispatcher
    where
        F: Fn(&SignedRequest) + Send + Sync + 'static,
    {
        self.request_checker = Some(Box::new(checker));
        self
    }

    /// Mocks a single service header that would be returned from AWS
    pub fn with_header(mut self, key: &str, value: &str) -> MockRequestDispatcher {
        self.headers.insert(key.parse::<HeaderName>().unwrap(), value.into());
        self
    }
}

impl DispatchSignedRequest for MockRequestDispatcher {
    type Future = FutureResult<HttpResponse, HttpDispatchError>;

    fn dispatch(&self, request: SignedRequest, _timeout: Option<Duration>) -> Self::Future {
        if self.request_checker.is_some() {
            self.request_checker.as_ref().unwrap()(&request);
        }
        match self.outcome {
          RequestOutcome::Performed(ref status) => ok(HttpResponse {
            status: *status,
            body: ByteStream::from(self.body.clone()),
            headers: self.headers.clone()
          }),
          RequestOutcome::Failed(ref error) => err(error.clone()),
        }
    }
}

/// An interface for producing response body content
pub trait ReadMockResponse {
    /// Return a response body string for a given directory and file name
    fn read_response(dir_name: &str, file_name: &str) -> String;
}

/// Reads response body content from disk
pub struct MockResponseReader;

impl ReadMockResponse for MockResponseReader {
    fn read_response(dir_name: &str, response_name: &str) -> String {
        let file_name = format!("{}/{}", dir_name, response_name);

        let mut input_file = File::open(&file_name).expect("couldn't find file");

        let mut mock_response = String::new();

        input_file
            .read_to_string(&mut mock_response)
            .unwrap_or_else(|_| panic!("Failed to read {:?}", file_name));

        mock_response
    }
}
<commit_msg>This gets a dyn too<commit_after>//! Mock request dispatcher and credentials for unit testing rusoto AWS service clients
//!
//! All rusoto generated service clients come with a constuctor function named `new_with` which
//! accepts three arguments
//!
//! * A `rusoto_core::DispatchSignedRequest` implementation
//! * A `rusoto_core::credential::ProvideAwsCredentials` implementation
//! * A `rusoto_core::Region`
//!
//! This crate provides mock implementations to satisfy the first two.
//!
//! # Example
//!
//! The following is an example for the `rusoto_s3` crate but should
//! work for all service crates just the same. The code is commented
//! out for illustration but also to avoid a cyclic dependency in this crate.
//!
//! ```rust
//! extern crate rusoto_mock;
//! // extern crate rusoto_s3;
//!
//! use rusoto_mock::{MockCredentialsProvider, MockRequestDispatcher, MockResponseReader};
//!
//! fn main() {
//!    // let s3 = rusoto_s3::S3Client::new_with(
//!    //   MockRequestDispatcher::default().with_body(
//!    //      MockResponseReader::read_response("test-data", "s3-response.json")
//!    //   ),
//!    //   MockCredentialsProvider,
//!    //   Default::default()
//!    // );
//! }
//! ```
#![deny(missing_docs)]
extern crate chrono;
extern crate futures;
extern crate http;
extern crate rusoto_core;
extern crate serde;
extern crate serde_json;

use std::fs::File;
use std::io::Read;
use std::time::Duration;

use futures::future::{ok, err, FutureResult};
use http::{HeaderMap, header::HeaderName, HttpTryFrom, StatusCode};
use rusoto_core::credential::{AwsCredentials, CredentialsError, ProvideAwsCredentials};
use rusoto_core::request::HttpResponse;
use rusoto_core::signature::SignedRequest;
use rusoto_core::{ByteStream, DispatchSignedRequest, HttpDispatchError};
use serde::Serialize;

/// Provides a set of credentials that always resolve
/// successfully
pub struct MockCredentialsProvider;

impl ProvideAwsCredentials for MockCredentialsProvider {
    type Future = FutureResult<AwsCredentials, CredentialsError>;

    fn credentials(&self) -> Self::Future {
        ok(AwsCredentials::new("mock_key", "mock_secret", None, None))
    }
}

/// Composes mock API responses
///
/// A Default is provided which returns an successful response with an empty body
///
/// These can be constructed using either a Default implementation or
///  with the [with_status](method.with_status) function.
///
#[derive(Default)]
pub struct MockRequestDispatcher {
    outcome: RequestOutcome,
    body: Vec<u8>,
    headers: HeaderMap<String>,
    request_checker: Option<Box<dyn Fn(&SignedRequest) + Send + Sync>>,
}

enum RequestOutcome {
  Performed(StatusCode),
  Failed(HttpDispatchError),
}

impl Default for RequestOutcome {
  fn default() -> RequestOutcome {
    RequestOutcome::Performed(StatusCode::default())
  }
}

impl MockRequestDispatcher {
    /// Returns a instance that mocks the status code that would
    /// be returned from AWS
    pub fn with_status(status: u16) -> MockRequestDispatcher {
        MockRequestDispatcher {
            outcome: RequestOutcome::Performed(StatusCode::try_from(status).unwrap()),
            ..MockRequestDispatcher::default()
        }
    }

    /// Mocks the service request failing with a communications error
    pub fn with_dispatch_error(error: HttpDispatchError) -> MockRequestDispatcher {
      MockRequestDispatcher {
          outcome: RequestOutcome::Failed(error),
          ..MockRequestDispatcher::default()
      }
    }

    /// Mocks the service response body what would be
    /// returned from AWS
    pub fn with_body(mut self, body: &str) -> MockRequestDispatcher {
        self.body = body.as_bytes().to_vec();
        self
    }

    /// Mocks the json serialized response body what would be
    /// returned from AWS
    pub fn with_json_body<B>(mut self, body: B) -> MockRequestDispatcher
    where
        B: Serialize,
    {
        self.body = serde_json::to_vec(&body).expect("failed to deserialize into json");
        self
    }

    /// Mocks the signed request checking applied to a request before sending
    /// to AWS
    pub fn with_request_checker<F>(mut self, checker: F) -> MockRequestDispatcher
    where
        F: Fn(&SignedRequest) + Send + Sync + 'static,
    {
        self.request_checker = Some(Box::new(checker));
        self
    }

    /// Mocks a single service header that would be returned from AWS
    pub fn with_header(mut self, key: &str, value: &str) -> MockRequestDispatcher {
        self.headers.insert(key.parse::<HeaderName>().unwrap(), value.into());
        self
    }
}

impl DispatchSignedRequest for MockRequestDispatcher {
    type Future = FutureResult<HttpResponse, HttpDispatchError>;

    fn dispatch(&self, request: SignedRequest, _timeout: Option<Duration>) -> Self::Future {
        if self.request_checker.is_some() {
            self.request_checker.as_ref().unwrap()(&request);
        }
        match self.outcome {
          RequestOutcome::Performed(ref status) => ok(HttpResponse {
            status: *status,
            body: ByteStream::from(self.body.clone()),
            headers: self.headers.clone()
          }),
          RequestOutcome::Failed(ref error) => err(error.clone()),
        }
    }
}

/// An interface for producing response body content
pub trait ReadMockResponse {
    /// Return a response body string for a given directory and file name
    fn read_response(dir_name: &str, file_name: &str) -> String;
}

/// Reads response body content from disk
pub struct MockResponseReader;

impl ReadMockResponse for MockResponseReader {
    fn read_response(dir_name: &str, response_name: &str) -> String {
        let file_name = format!("{}/{}", dir_name, response_name);

        let mut input_file = File::open(&file_name).expect("couldn't find file");

        let mut mock_response = String::new();

        input_file
            .read_to_string(&mut mock_response)
            .unwrap_or_else(|_| panic!("Failed to read {:?}", file_name));

        mock_response
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use libc::c_int;
use fcntl::Fd;
use errno::{SysResult, SysError, from_ffi};

mod ffi {
    use libc::{c_int};
    use super::EpollEvent;

    extern {
        pub fn epoll_create(size: c_int) -> c_int;
        pub fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *const EpollEvent) -> c_int;
        pub fn epoll_wait(epfd: c_int, events: *mut EpollEvent, max_events: c_int, timeout: c_int) -> c_int;
    }
}

bitflags!(
    flags EpollEventKind: u32 {
        static EPOLLIN = 0x001,
        static EPOLLPRI = 0x002,
        static EPOLLOUT = 0x004,
        static EPOLLRDNORM = 0x040,
        static EPOLLRDBAND = 0x080,
        static EPOLLWRNORM = 0x100,
        static EPOLLWRBAND = 0x200,
        static EPOLLMSG = 0x400,
        static EPOLLERR = 0x008,
        static EPOLLHUP = 0x010,
        static EPOLLRDHUP = 0x2000,
        static EPOLLWAKEUP = 1 << 29,
        static EPOLLONESHOT = 1 << 30,
        static EPOLLET = 1 << 31
    }
)

impl fmt::Show for EpollEventKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let variants = [
            (EPOLLIN,       "EPOLLIN"),
            (EPOLLPRI,      "EPOLLPRI"),
            (EPOLLOUT,      "EPOLLOUT"),
            (EPOLLRDNORM,   "EPOLLRDNORM"),
            (EPOLLRDBAND,   "EPOLLRDBAND"),
            (EPOLLWRNORM,   "EPOLLWRNORM"),
            (EPOLLWRBAND,   "EPOLLWRBAND"),
            (EPOLLMSG,      "EPOLLMSG"),
            (EPOLLERR,      "EPOLLERR"),
            (EPOLLHUP,      "EPOLLHUP"),
            (EPOLLRDHUP,    "EPOLLRDHUP"),
            (EPOLLWAKEUP,   "EPOLLWAKEUP"),
            (EPOLLONESHOT,  "EPOLLONESHOT"),
            (EPOLLET,       "EPOLLET")];

        let mut first = true;

        for &(val, name) in variants.iter() {
            if self.contains(val) {
                if first {
                    first = false;
                    try!(write!(fmt, "{}", name));
                } else {
                    try!(write!(fmt, "|{}", name));
                }
            }
        }

        Ok(())
    }
}

#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

#[repr(C)]
pub struct EpollEvent {
    pub events: EpollEventKind,
    pub data: u64
}

#[inline]
pub fn epoll_create() -> SysResult<Fd> {
    let res = unsafe { ffi::epoll_create(1024) };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(res)
}

#[inline]
pub fn epoll_ctl(epfd: Fd, op: EpollOp, fd: Fd, event: &EpollEvent) -> SysResult<()> {
    let res = unsafe { ffi::epoll_ctl(epfd, op as c_int, fd, event as *const EpollEvent) };
    from_ffi(res)
}

#[inline]
pub fn epoll_wait(epfd: Fd, events: &mut [EpollEvent], timeout_ms: uint) -> SysResult<uint> {
    let res = unsafe {
        ffi::epoll_wait(epfd, events.as_mut_ptr(), events.len() as c_int, timeout_ms as c_int)
    };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(res as uint)
}
<commit_msg>EpollEvent is a packed struct<commit_after>use std::fmt;
use libc::c_int;
use fcntl::Fd;
use errno::{SysResult, SysError, from_ffi};

mod ffi {
    use libc::{c_int};
    use super::EpollEvent;

    extern {
        pub fn epoll_create(size: c_int) -> c_int;
        pub fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *const EpollEvent) -> c_int;
        pub fn epoll_wait(epfd: c_int, events: *mut EpollEvent, max_events: c_int, timeout: c_int) -> c_int;
    }
}

bitflags!(
    flags EpollEventKind: u32 {
        static EPOLLIN = 0x001,
        static EPOLLPRI = 0x002,
        static EPOLLOUT = 0x004,
        static EPOLLRDNORM = 0x040,
        static EPOLLRDBAND = 0x080,
        static EPOLLWRNORM = 0x100,
        static EPOLLWRBAND = 0x200,
        static EPOLLMSG = 0x400,
        static EPOLLERR = 0x008,
        static EPOLLHUP = 0x010,
        static EPOLLRDHUP = 0x2000,
        static EPOLLWAKEUP = 1 << 29,
        static EPOLLONESHOT = 1 << 30,
        static EPOLLET = 1 << 31
    }
)

impl fmt::Show for EpollEventKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let variants = [
            (EPOLLIN,       "EPOLLIN"),
            (EPOLLPRI,      "EPOLLPRI"),
            (EPOLLOUT,      "EPOLLOUT"),
            (EPOLLRDNORM,   "EPOLLRDNORM"),
            (EPOLLRDBAND,   "EPOLLRDBAND"),
            (EPOLLWRNORM,   "EPOLLWRNORM"),
            (EPOLLWRBAND,   "EPOLLWRBAND"),
            (EPOLLMSG,      "EPOLLMSG"),
            (EPOLLERR,      "EPOLLERR"),
            (EPOLLHUP,      "EPOLLHUP"),
            (EPOLLRDHUP,    "EPOLLRDHUP"),
            (EPOLLWAKEUP,   "EPOLLWAKEUP"),
            (EPOLLONESHOT,  "EPOLLONESHOT"),
            (EPOLLET,       "EPOLLET")];

        let mut first = true;

        for &(val, name) in variants.iter() {
            if self.contains(val) {
                if first {
                    first = false;
                    try!(write!(fmt, "{}", name));
                } else {
                    try!(write!(fmt, "|{}", name));
                }
            }
        }

        Ok(())
    }
}

#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

#[repr(C, packed)]
pub struct EpollEvent {
    pub events: EpollEventKind,
    pub data: u64
}

#[inline]
pub fn epoll_create() -> SysResult<Fd> {
    let res = unsafe { ffi::epoll_create(1024) };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(res)
}

#[inline]
pub fn epoll_ctl(epfd: Fd, op: EpollOp, fd: Fd, event: &EpollEvent) -> SysResult<()> {
    let res = unsafe { ffi::epoll_ctl(epfd, op as c_int, fd, event as *const EpollEvent) };
    from_ffi(res)
}

#[inline]
pub fn epoll_wait(epfd: Fd, events: &mut [EpollEvent], timeout_ms: uint) -> SysResult<uint> {
    let res = unsafe {
        ffi::epoll_wait(epfd, events.as_mut_ptr(), events.len() as c_int, timeout_ms as c_int)
    };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(res as uint)
}
<|endoftext|>


<commit_before>use crate::generate::grammars::{LexicalGrammar, Production, ProductionStep, SyntaxGrammar};
use crate::generate::rules::{Associativity, Precedence, Symbol, SymbolType, TokenSet};
use lazy_static::lazy_static;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::u32;

lazy_static! {
    static ref START_PRODUCTION: Production = Production {
        dynamic_precedence: 0,
        steps: vec![ProductionStep {
            symbol: Symbol {
                index: 0,
                kind: SymbolType::NonTerminal,
            },
            precedence: Precedence::None,
            associativity: None,
            alias: None,
            field_name: None,
        }],
    };
}

/// A ParseItem represents an in-progress match of a single production in a grammar.
#[derive(Clone, Copy, Debug)]
pub(crate) struct ParseItem<'a> {
    /// The index of the parent rule within the grammar.
    pub variable_index: u32,
    /// The number of symbols that have already been matched.
    pub step_index: u32,
    /// The production being matched.
    pub production: &'a Production,
    /// A boolean indicating whether any of the already-matched children were
    /// hidden nodes and had fields. Ordinarily, a parse item's behavior is not
    /// affected by the symbols of its preceding children; it only needs to
    /// keep track of their fields and aliases.
    ///
    /// Take for example these two items:
    ///   X -> a b • c
    ///   X -> a g • c
    ///
    /// They can be considered equivalent, for the purposes of parse table
    /// generation, because they entail the same actions. But if this flag is
    /// true, then the item's set of inherited fields may depend on the specific
    /// symbols of its preceding children.
    pub has_preceding_inherited_fields: bool,
}

/// A ParseItemSet represents a set of in-progress matches of productions in a
/// grammar, and for each in-progress match, a set of "lookaheads" - tokens that
/// are allowed to *follow* the in-progress rule. This object corresponds directly
/// to a state in the final parse table.
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct ParseItemSet<'a> {
    pub entries: Vec<(ParseItem<'a>, TokenSet)>,
}

/// A ParseItemSetCore is like a ParseItemSet, but without the lookahead
/// information. Parse states with the same core are candidates for merging.
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct ParseItemSetCore<'a> {
    pub entries: Vec<ParseItem<'a>>,
}

pub(crate) struct ParseItemDisplay<'a>(
    pub &'a ParseItem<'a>,
    pub &'a SyntaxGrammar,
    pub &'a LexicalGrammar,
);

pub(crate) struct TokenSetDisplay<'a>(
    pub &'a TokenSet,
    pub &'a SyntaxGrammar,
    pub &'a LexicalGrammar,
);

#[allow(dead_code)]
pub(crate) struct ParseItemSetDisplay<'a>(
    pub &'a ParseItemSet<'a>,
    pub &'a SyntaxGrammar,
    pub &'a LexicalGrammar,
);

impl<'a> ParseItem<'a> {
    pub fn start() -> Self {
        ParseItem {
            variable_index: u32::MAX,
            production: &START_PRODUCTION,
            step_index: 0,
            has_preceding_inherited_fields: false,
        }
    }

    pub fn step(&self) -> Option<&'a ProductionStep> {
        self.production.steps.get(self.step_index as usize)
    }

    pub fn symbol(&self) -> Option<Symbol> {
        self.step().map(|step| step.symbol)
    }

    pub fn associativity(&self) -> Option<Associativity> {
        self.prev_step().and_then(|step| step.associativity)
    }

    pub fn precedence(&self) -> &Precedence {
        self.prev_step()
            .map_or(&Precedence::None, |step| &step.precedence)
    }

    pub fn prev_step(&self) -> Option<&'a ProductionStep> {
        if self.step_index > 0 {
            Some(&self.production.steps[self.step_index as usize - 1])
        } else {
            None
        }
    }

    pub fn is_done(&self) -> bool {
        self.step_index as usize == self.production.steps.len()
    }

    pub fn is_augmented(&self) -> bool {
        self.variable_index == u32::MAX
    }

    /// Create an item like this one, but advanced by one step.
    pub fn successor(&self) -> ParseItem<'a> {
        ParseItem {
            variable_index: self.variable_index,
            production: self.production,
            step_index: self.step_index + 1,
            has_preceding_inherited_fields: self.has_preceding_inherited_fields,
        }
    }

    /// Create an item identical to this one, but with a different production.
    /// This is used when dynamically "inlining" certain symbols in a production.
    pub fn substitute_production(&self, production: &'a Production) -> ParseItem<'a> {
        let mut result = self.clone();
        result.production = production;
        result
    }
}

impl<'a> ParseItemSet<'a> {
    pub fn with(elements: impl IntoIterator<Item = (ParseItem<'a>, TokenSet)>) -> Self {
        let mut result = Self::default();
        for (item, lookaheads) in elements {
            result.insert(item, &lookaheads);
        }
        result
    }

    pub fn insert(&mut self, item: ParseItem<'a>, lookaheads: &TokenSet) -> &mut TokenSet {
        match self.entries.binary_search_by(|(i, _)| i.cmp(&item)) {
            Err(i) => {
                self.entries.insert(i, (item, lookaheads.clone()));
                &mut self.entries[i].1
            }
            Ok(i) => {
                self.entries[i].1.insert_all(lookaheads);
                &mut self.entries[i].1
            }
        }
    }

    pub fn core(&self) -> ParseItemSetCore<'a> {
        ParseItemSetCore {
            entries: self.entries.iter().map(|e| e.0).collect(),
        }
    }
}

impl<'a> Default for ParseItemSet<'a> {
    fn default() -> Self {
        Self {
            entries: Vec::new(),
        }
    }
}

#[allow(dead_code)]
impl<'a> fmt::Display for ParseItemDisplay<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.0.is_augmented() {
            write!(f, "START →")?;
        } else {
            write!(
                f,
                "{} →",
                &self.1.variables[self.0.variable_index as usize].name
            )?;
        }

        for (i, step) in self.0.production.steps.iter().enumerate() {
            if i == self.0.step_index as usize {
                write!(f, " •")?;
                if let Some(associativity) = step.associativity {
                    if !step.precedence.is_none() {
                        write!(f, " ({} {:?})", step.precedence, associativity)?;
                    } else {
                        write!(f, " ({:?})", associativity)?;
                    }
                } else if !step.precedence.is_none() {
                    write!(f, " ({})", step.precedence)?;
                }
            }

            write!(f, " ")?;
            if step.symbol.is_terminal() {
                if let Some(variable) = self.2.variables.get(step.symbol.index) {
                    write!(f, "{}", &variable.name)?;
                } else {
                    write!(f, "{}-{}", "terminal", step.symbol.index)?;
                }
            } else if step.symbol.is_external() {
                write!(f, "{}", &self.1.external_tokens[step.symbol.index].name)?;
            } else {
                write!(f, "{}", &self.1.variables[step.symbol.index].name)?;
            }

            if let Some(alias) = &step.alias {
                write!(f, "@{}", alias.value)?;
            }
        }

        if self.0.is_done() {
            write!(f, " •")?;
            if let Some(step) = self.0.production.steps.last() {
                if let Some(associativity) = step.associativity {
                    if !step.precedence.is_none() {
                        write!(f, " ({} {:?})", step.precedence, associativity)?;
                    } else {
                        write!(f, " ({:?})", associativity)?;
                    }
                } else if !step.precedence.is_none() {
                    write!(f, " ({})", step.precedence)?;
                }
            }
        }

        Ok(())
    }
}

impl<'a> fmt::Display for TokenSetDisplay<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "[")?;
        for (i, symbol) in self.0.iter().enumerate() {
            if i > 0 {
                write!(f, ", ")?;
            }

            if symbol.is_terminal() {
                if let Some(variable) = self.2.variables.get(symbol.index) {
                    write!(f, "{}", &variable.name)?;
                } else {
                    write!(f, "{}-{}", "terminal", symbol.index)?;
                }
            } else if symbol.is_external() {
                write!(f, "{}", &self.1.external_tokens[symbol.index].name)?;
            } else {
                write!(f, "{}", &self.1.variables[symbol.index].name)?;
            }
        }
        write!(f, "]")?;
        Ok(())
    }
}

impl<'a> fmt::Display for ParseItemSetDisplay<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        for (item, lookaheads) in self.0.entries.iter() {
            writeln!(
                f,
                "{}\t{}",
                ParseItemDisplay(item, self.1, self.2),
                TokenSetDisplay(lookaheads, self.1, self.2)
            )?;
        }
        Ok(())
    }
}

impl<'a> Hash for ParseItem<'a> {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.variable_index);
        hasher.write_u32(self.step_index);
        hasher.write_i32(self.production.dynamic_precedence);
        hasher.write_usize(self.production.steps.len());
        self.precedence().hash(hasher);
        self.associativity().hash(hasher);

        // The already-matched children don't play any role in the parse state for
        // this item, unless any of the following are true:
        //   * the children have fields
        //   * the children have aliases
        //   * the children are hidden and
        // See the docs for `has_preceding_inherited_fields`.
        for step in &self.production.steps[0..self.step_index as usize] {
            step.alias.hash(hasher);
            step.field_name.hash(hasher);
            if self.has_preceding_inherited_fields {
                step.symbol.hash(hasher);
            }
        }
        for step in &self.production.steps[self.step_index as usize..] {
            step.hash(hasher);
        }
    }
}

impl<'a> PartialEq for ParseItem<'a> {
    fn eq(&self, other: &Self) -> bool {
        if self.variable_index != other.variable_index
            || self.step_index != other.step_index
            || self.production.dynamic_precedence != other.production.dynamic_precedence
            || self.production.steps.len() != other.production.steps.len()
            || self.precedence() != other.precedence()
            || self.associativity() != other.associativity()
            || self.has_preceding_inherited_fields != other.has_preceding_inherited_fields
        {
            return false;
        }

        for (i, step) in self.production.steps.iter().enumerate() {
            // See the previous comment (in the `Hash::hash` impl) regarding comparisons
            // of parse items' already-completed steps.
            if i < self.step_index as usize {
                if step.alias != other.production.steps[i].alias {
                    return false;
                }
                if step.field_name != other.production.steps[i].field_name {
                    return false;
                }
                if self.has_preceding_inherited_fields
                    && step.symbol != other.production.steps[i].symbol
                {
                    return false;
                }
            } else if *step != other.production.steps[i] {
                return false;
            }
        }

        return true;
    }
}

impl<'a> Ord for ParseItem<'a> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.step_index
            .cmp(&other.step_index)
            .then_with(|| self.variable_index.cmp(&other.variable_index))
            .then_with(|| {
                self.production
                    .dynamic_precedence
                    .cmp(&other.production.dynamic_precedence)
            })
            .then_with(|| {
                self.production
                    .steps
                    .len()
                    .cmp(&other.production.steps.len())
            })
            .then_with(|| self.precedence().cmp(&other.precedence()))
            .then_with(|| self.associativity().cmp(&other.associativity()))
            .then_with(|| {
                for (i, step) in self.production.steps.iter().enumerate() {
                    // See the previous comment (in the `Hash::hash` impl) regarding comparisons
                    // of parse items' already-completed steps.
                    let o = if i < self.step_index as usize {
                        step.alias
                            .cmp(&other.production.steps[i].alias)
                            .then_with(|| {
                                step.field_name.cmp(&other.production.steps[i].field_name)
                            })
                    } else {
                        step.cmp(&other.production.steps[i])
                    };
                    if o != Ordering::Equal {
                        return o;
                    }
                }
                return Ordering::Equal;
            })
    }
}

impl<'a> PartialOrd for ParseItem<'a> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a> Eq for ParseItem<'a> {}

impl<'a> Hash for ParseItemSet<'a> {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_usize(self.entries.len());
        for (item, lookaheads) in self.entries.iter() {
            item.hash(hasher);
            lookaheads.hash(hasher);
        }
    }
}

impl<'a> Hash for ParseItemSetCore<'a> {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_usize(self.entries.len());
        for item in &self.entries {
            item.hash(hasher);
        }
    }
}
<commit_msg>Include has_preceding_inherited_fields in Item's hash impl<commit_after>use crate::generate::grammars::{LexicalGrammar, Production, ProductionStep, SyntaxGrammar};
use crate::generate::rules::{Associativity, Precedence, Symbol, SymbolType, TokenSet};
use lazy_static::lazy_static;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::u32;

lazy_static! {
    static ref START_PRODUCTION: Production = Production {
        dynamic_precedence: 0,
        steps: vec![ProductionStep {
            symbol: Symbol {
                index: 0,
                kind: SymbolType::NonTerminal,
            },
            precedence: Precedence::None,
            associativity: None,
            alias: None,
            field_name: None,
        }],
    };
}

/// A ParseItem represents an in-progress match of a single production in a grammar.
#[derive(Clone, Copy, Debug)]
pub(crate) struct ParseItem<'a> {
    /// The index of the parent rule within the grammar.
    pub variable_index: u32,
    /// The number of symbols that have already been matched.
    pub step_index: u32,
    /// The production being matched.
    pub production: &'a Production,
    /// A boolean indicating whether any of the already-matched children were
    /// hidden nodes and had fields. Ordinarily, a parse item's behavior is not
    /// affected by the symbols of its preceding children; it only needs to
    /// keep track of their fields and aliases.
    ///
    /// Take for example these two items:
    ///   X -> a b • c
    ///   X -> a g • c
    ///
    /// They can be considered equivalent, for the purposes of parse table
    /// generation, because they entail the same actions. But if this flag is
    /// true, then the item's set of inherited fields may depend on the specific
    /// symbols of its preceding children.
    pub has_preceding_inherited_fields: bool,
}

/// A ParseItemSet represents a set of in-progress matches of productions in a
/// grammar, and for each in-progress match, a set of "lookaheads" - tokens that
/// are allowed to *follow* the in-progress rule. This object corresponds directly
/// to a state in the final parse table.
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct ParseItemSet<'a> {
    pub entries: Vec<(ParseItem<'a>, TokenSet)>,
}

/// A ParseItemSetCore is like a ParseItemSet, but without the lookahead
/// information. Parse states with the same core are candidates for merging.
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct ParseItemSetCore<'a> {
    pub entries: Vec<ParseItem<'a>>,
}

pub(crate) struct ParseItemDisplay<'a>(
    pub &'a ParseItem<'a>,
    pub &'a SyntaxGrammar,
    pub &'a LexicalGrammar,
);

pub(crate) struct TokenSetDisplay<'a>(
    pub &'a TokenSet,
    pub &'a SyntaxGrammar,
    pub &'a LexicalGrammar,
);

#[allow(dead_code)]
pub(crate) struct ParseItemSetDisplay<'a>(
    pub &'a ParseItemSet<'a>,
    pub &'a SyntaxGrammar,
    pub &'a LexicalGrammar,
);

impl<'a> ParseItem<'a> {
    pub fn start() -> Self {
        ParseItem {
            variable_index: u32::MAX,
            production: &START_PRODUCTION,
            step_index: 0,
            has_preceding_inherited_fields: false,
        }
    }

    pub fn step(&self) -> Option<&'a ProductionStep> {
        self.production.steps.get(self.step_index as usize)
    }

    pub fn symbol(&self) -> Option<Symbol> {
        self.step().map(|step| step.symbol)
    }

    pub fn associativity(&self) -> Option<Associativity> {
        self.prev_step().and_then(|step| step.associativity)
    }

    pub fn precedence(&self) -> &Precedence {
        self.prev_step()
            .map_or(&Precedence::None, |step| &step.precedence)
    }

    pub fn prev_step(&self) -> Option<&'a ProductionStep> {
        if self.step_index > 0 {
            Some(&self.production.steps[self.step_index as usize - 1])
        } else {
            None
        }
    }

    pub fn is_done(&self) -> bool {
        self.step_index as usize == self.production.steps.len()
    }

    pub fn is_augmented(&self) -> bool {
        self.variable_index == u32::MAX
    }

    /// Create an item like this one, but advanced by one step.
    pub fn successor(&self) -> ParseItem<'a> {
        ParseItem {
            variable_index: self.variable_index,
            production: self.production,
            step_index: self.step_index + 1,
            has_preceding_inherited_fields: self.has_preceding_inherited_fields,
        }
    }

    /// Create an item identical to this one, but with a different production.
    /// This is used when dynamically "inlining" certain symbols in a production.
    pub fn substitute_production(&self, production: &'a Production) -> ParseItem<'a> {
        let mut result = self.clone();
        result.production = production;
        result
    }
}

impl<'a> ParseItemSet<'a> {
    pub fn with(elements: impl IntoIterator<Item = (ParseItem<'a>, TokenSet)>) -> Self {
        let mut result = Self::default();
        for (item, lookaheads) in elements {
            result.insert(item, &lookaheads);
        }
        result
    }

    pub fn insert(&mut self, item: ParseItem<'a>, lookaheads: &TokenSet) -> &mut TokenSet {
        match self.entries.binary_search_by(|(i, _)| i.cmp(&item)) {
            Err(i) => {
                self.entries.insert(i, (item, lookaheads.clone()));
                &mut self.entries[i].1
            }
            Ok(i) => {
                self.entries[i].1.insert_all(lookaheads);
                &mut self.entries[i].1
            }
        }
    }

    pub fn core(&self) -> ParseItemSetCore<'a> {
        ParseItemSetCore {
            entries: self.entries.iter().map(|e| e.0).collect(),
        }
    }
}

impl<'a> Default for ParseItemSet<'a> {
    fn default() -> Self {
        Self {
            entries: Vec::new(),
        }
    }
}

#[allow(dead_code)]
impl<'a> fmt::Display for ParseItemDisplay<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.0.is_augmented() {
            write!(f, "START →")?;
        } else {
            write!(
                f,
                "{} →",
                &self.1.variables[self.0.variable_index as usize].name
            )?;
        }

        for (i, step) in self.0.production.steps.iter().enumerate() {
            if i == self.0.step_index as usize {
                write!(f, " •")?;
                if let Some(associativity) = step.associativity {
                    if !step.precedence.is_none() {
                        write!(f, " ({} {:?})", step.precedence, associativity)?;
                    } else {
                        write!(f, " ({:?})", associativity)?;
                    }
                } else if !step.precedence.is_none() {
                    write!(f, " ({})", step.precedence)?;
                }
            }

            write!(f, " ")?;
            if step.symbol.is_terminal() {
                if let Some(variable) = self.2.variables.get(step.symbol.index) {
                    write!(f, "{}", &variable.name)?;
                } else {
                    write!(f, "{}-{}", "terminal", step.symbol.index)?;
                }
            } else if step.symbol.is_external() {
                write!(f, "{}", &self.1.external_tokens[step.symbol.index].name)?;
            } else {
                write!(f, "{}", &self.1.variables[step.symbol.index].name)?;
            }

            if let Some(alias) = &step.alias {
                write!(f, "@{}", alias.value)?;
            }
        }

        if self.0.is_done() {
            write!(f, " •")?;
            if let Some(step) = self.0.production.steps.last() {
                if let Some(associativity) = step.associativity {
                    if !step.precedence.is_none() {
                        write!(f, " ({} {:?})", step.precedence, associativity)?;
                    } else {
                        write!(f, " ({:?})", associativity)?;
                    }
                } else if !step.precedence.is_none() {
                    write!(f, " ({})", step.precedence)?;
                }
            }
        }

        Ok(())
    }
}

impl<'a> fmt::Display for TokenSetDisplay<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "[")?;
        for (i, symbol) in self.0.iter().enumerate() {
            if i > 0 {
                write!(f, ", ")?;
            }

            if symbol.is_terminal() {
                if let Some(variable) = self.2.variables.get(symbol.index) {
                    write!(f, "{}", &variable.name)?;
                } else {
                    write!(f, "{}-{}", "terminal", symbol.index)?;
                }
            } else if symbol.is_external() {
                write!(f, "{}", &self.1.external_tokens[symbol.index].name)?;
            } else {
                write!(f, "{}", &self.1.variables[symbol.index].name)?;
            }
        }
        write!(f, "]")?;
        Ok(())
    }
}

impl<'a> fmt::Display for ParseItemSetDisplay<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        for (item, lookaheads) in self.0.entries.iter() {
            writeln!(
                f,
                "{}\t{}",
                ParseItemDisplay(item, self.1, self.2),
                TokenSetDisplay(lookaheads, self.1, self.2)
            )?;
        }
        Ok(())
    }
}

impl<'a> Hash for ParseItem<'a> {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.variable_index);
        hasher.write_u32(self.step_index);
        hasher.write_i32(self.production.dynamic_precedence);
        hasher.write_usize(self.production.steps.len());
        hasher.write_i32(self.has_preceding_inherited_fields as i32);
        self.precedence().hash(hasher);
        self.associativity().hash(hasher);

        // The already-matched children don't play any role in the parse state for
        // this item, unless any of the following are true:
        //   * the children have fields
        //   * the children have aliases
        //   * the children are hidden and
        // See the docs for `has_preceding_inherited_fields`.
        for step in &self.production.steps[0..self.step_index as usize] {
            step.alias.hash(hasher);
            step.field_name.hash(hasher);
            if self.has_preceding_inherited_fields {
                step.symbol.hash(hasher);
            }
        }
        for step in &self.production.steps[self.step_index as usize..] {
            step.hash(hasher);
        }
    }
}

impl<'a> PartialEq for ParseItem<'a> {
    fn eq(&self, other: &Self) -> bool {
        if self.variable_index != other.variable_index
            || self.step_index != other.step_index
            || self.production.dynamic_precedence != other.production.dynamic_precedence
            || self.production.steps.len() != other.production.steps.len()
            || self.precedence() != other.precedence()
            || self.associativity() != other.associativity()
            || self.has_preceding_inherited_fields != other.has_preceding_inherited_fields
        {
            return false;
        }

        for (i, step) in self.production.steps.iter().enumerate() {
            // See the previous comment (in the `Hash::hash` impl) regarding comparisons
            // of parse items' already-completed steps.
            if i < self.step_index as usize {
                if step.alias != other.production.steps[i].alias {
                    return false;
                }
                if step.field_name != other.production.steps[i].field_name {
                    return false;
                }
                if self.has_preceding_inherited_fields
                    && step.symbol != other.production.steps[i].symbol
                {
                    return false;
                }
            } else if *step != other.production.steps[i] {
                return false;
            }
        }

        return true;
    }
}

impl<'a> Ord for ParseItem<'a> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.step_index
            .cmp(&other.step_index)
            .then_with(|| self.variable_index.cmp(&other.variable_index))
            .then_with(|| {
                self.production
                    .dynamic_precedence
                    .cmp(&other.production.dynamic_precedence)
            })
            .then_with(|| {
                self.production
                    .steps
                    .len()
                    .cmp(&other.production.steps.len())
            })
            .then_with(|| self.precedence().cmp(&other.precedence()))
            .then_with(|| self.associativity().cmp(&other.associativity()))
            .then_with(|| {
                for (i, step) in self.production.steps.iter().enumerate() {
                    // See the previous comment (in the `Hash::hash` impl) regarding comparisons
                    // of parse items' already-completed steps.
                    let o = if i < self.step_index as usize {
                        step.alias
                            .cmp(&other.production.steps[i].alias)
                            .then_with(|| {
                                step.field_name.cmp(&other.production.steps[i].field_name)
                            })
                    } else {
                        step.cmp(&other.production.steps[i])
                    };
                    if o != Ordering::Equal {
                        return o;
                    }
                }
                return Ordering::Equal;
            })
    }
}

impl<'a> PartialOrd for ParseItem<'a> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a> Eq for ParseItem<'a> {}

impl<'a> Hash for ParseItemSet<'a> {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_usize(self.entries.len());
        for (item, lookaheads) in self.entries.iter() {
            item.hash(hasher);
            lookaheads.hash(hasher);
        }
    }
}

impl<'a> Hash for ParseItemSetCore<'a> {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_usize(self.entries.len());
        for item in &self.entries {
            item.hash(hasher);
        }
    }
}
<|endoftext|>