<commit_before>extern crate ssz_helpers;

use self::ssz_helpers::ssz_beacon_block::SszBeaconBlock;
use super::BLOCKS_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use std::sync::Arc;

type BeaconBlockHash = Vec<u8>;
type BeaconBlockSsz = Vec<u8>;

#[derive(Clone, Debug, PartialEq)]
pub enum BeaconBlockAtSlotError {
    UnknownBeaconBlock,
    InvalidBeaconBlock,
    DBError(String),
}

pub struct BeaconBlockStore<T>
where
    T: ClientDB,
{
    db: Arc<T>,
}

impl<T: ClientDB> BeaconBlockStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self { db }
    }

    pub fn put_serialized_block(&self, hash: &[u8], ssz: &[u8]) -> Result<(), DBError> {
        self.db.put(DB_COLUMN, hash, ssz)
    }

    pub fn get_serialized_block(&self, hash: &[u8]) -> Result<Option<Vec<u8>>, DBError> {
        self.db.get(DB_COLUMN, hash)
    }

    pub fn block_exists(&self, hash: &[u8]) -> Result<bool, DBError> {
        self.db.exists(DB_COLUMN, hash)
    }

    pub fn delete_block(&self, hash: &[u8]) -> Result<(), DBError> {
        self.db.delete(DB_COLUMN, hash)
    }

    /// Retrieve the block at a slot given a "head_hash" and a slot.
    ///
    /// A "head_hash" must be a block hash with a slot number greater than or equal to the desired
    /// slot.
    ///
    /// This function will read each block down the chain until it finds a block with the given
    /// slot number. If the slot is skipped, the function will return None.
    ///
    /// If a block is found, a tuple of (block_hash, serialized_block) is returned.
    pub fn block_at_slot(
        &self,
        head_hash: &[u8],
        slot: u64,
    ) -> Result<Option<(BeaconBlockHash, BeaconBlockSsz)>, BeaconBlockAtSlotError> {
        match self.get_serialized_block(head_hash)? {
            None => Err(BeaconBlockAtSlotError::UnknownBeaconBlock),
            Some(ssz) => {
                let block = SszBeaconBlock::from_slice(&ssz)
                    .map_err(|_| BeaconBlockAtSlotError::InvalidBeaconBlock)?;
                match block.slot() {
                    s if s == slot => Ok(Some((head_hash.to_vec(), ssz.to_vec()))),
                    s if s < slot => Ok(None),
                    _ => match block.parent_hash() {
                        Some(parent_hash) => self.block_at_slot(parent_hash, slot),
                        None => Err(BeaconBlockAtSlotError::UnknownBeaconBlock),
                    },
                }
            }
        }
    }
}

impl From<DBError> for BeaconBlockAtSlotError {
    fn from(e: DBError) -> Self {
        BeaconBlockAtSlotError::DBError(e.message)
    }
}

#[cfg(test)]
mod tests {
    extern crate ssz;
    extern crate types;

    use self::ssz::SszStream;
    use self::types::attestation_record::AttestationRecord;
    use self::types::beacon_block::BeaconBlock;
    use self::types::Hash256;

    use super::super::super::MemoryDB;
    use super::*;
    use std::sync::Arc;
    use std::thread;

    #[test]
    fn test_block_store_on_memory_db() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));

        let thread_count = 10;
        let write_count = 10;

        // We're expecting the product of these numbers to fit in one byte.
        assert!(thread_count * write_count <= 255);

        let mut handles = vec![];
        for t in 0..thread_count {
            let wc = write_count;
            let bs = bs.clone();
            let handle = thread::spawn(move || {
                for w in 0..wc {
                    let key = (t * w) as u8;
                    let val = 42;
                    bs.put_serialized_block(&vec![key], &vec![val]).unwrap();
                }
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.join().unwrap();
        }

        for t in 0..thread_count {
            for w in 0..write_count {
                let key = (t * w) as u8;
                assert!(bs.block_exists(&vec![key]).unwrap());
                let val = bs.get_serialized_block(&vec![key]).unwrap().unwrap();
                assert_eq!(vec![42], val);
            }
        }
    }

    #[test]
    fn test_block_at_slot() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));

        let blocks = (0..5).into_iter().map(|_| {
            let mut block = BeaconBlock::zero();
            let ar = AttestationRecord::zero();
            block.attestations.push(ar);
            block
        });

        let hashes = [
            Hash256::from("zero".as_bytes()),
            Hash256::from("one".as_bytes()),
            Hash256::from("two".as_bytes()),
            Hash256::from("three".as_bytes()),
            Hash256::from("four".as_bytes()),
        ];

        let parent_hashes = [
            Hash256::from("genesis".as_bytes()),
            Hash256::from("zero".as_bytes()),
            Hash256::from("one".as_bytes()),
            Hash256::from("two".as_bytes()),
            Hash256::from("three".as_bytes()),
        ];

        let slots = [0, 1, 3, 4, 5];

        for (i, mut block) in blocks.enumerate() {
            block.ancestor_hashes.push(parent_hashes[i]);
            block.slot = slots[i];
            let mut s = SszStream::new();
            s.append(&block);
            let ssz = s.drain();
            bs.put_serialized_block(&hashes[i].to_vec(), &ssz).unwrap();
        }

        let tuple = bs.block_at_slot(&hashes[4], 5).unwrap().unwrap();
        let block = SszBeaconBlock::from_slice(&tuple.1).unwrap();
        assert_eq!(block.slot(), 5);
        assert_eq!(tuple.0, hashes[4].to_vec());

        let tuple = bs.block_at_slot(&hashes[4], 4).unwrap().unwrap();
        let block = SszBeaconBlock::from_slice(&tuple.1).unwrap();
        assert_eq!(block.slot(), 4);
        assert_eq!(tuple.0, hashes[3].to_vec());

        let tuple = bs.block_at_slot(&hashes[4], 3).unwrap().unwrap();
        let block = SszBeaconBlock::from_slice(&tuple.1).unwrap();
        assert_eq!(block.slot(), 3);
        assert_eq!(tuple.0, hashes[2].to_vec());

        let tuple = bs.block_at_slot(&hashes[4], 0).unwrap().unwrap();
        let block = SszBeaconBlock::from_slice(&tuple.1).unwrap();
        assert_eq!(block.slot(), 0);
        assert_eq!(tuple.0, hashes[0].to_vec());

        let ssz = bs.block_at_slot(&hashes[4], 2).unwrap();
        assert_eq!(ssz, None);

        let ssz = bs.block_at_slot(&hashes[4], 6).unwrap();
        assert_eq!(ssz, None);

        let ssz = bs.block_at_slot(&Hash256::from("unknown".as_bytes()), 2);
        assert_eq!(ssz, Err(BeaconBlockAtSlotError::UnknownBeaconBlock));
    }
}
<commit_msg>beacon block tests<commit_after>extern crate ssz_helpers;

use self::ssz_helpers::ssz_beacon_block::SszBeaconBlock;
use super::BLOCKS_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use std::sync::Arc;

type BeaconBlockHash = Vec<u8>;
type BeaconBlockSsz = Vec<u8>;

#[derive(Clone, Debug, PartialEq)]
pub enum BeaconBlockAtSlotError {
    UnknownBeaconBlock,
    InvalidBeaconBlock,
    DBError(String),
}

pub struct BeaconBlockStore<T>
where
    T: ClientDB,
{
    db: Arc<T>,
}

impl<T: ClientDB> BeaconBlockStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self { db }
    }

    pub fn put_serialized_block(&self, hash: &[u8], ssz: &[u8]) -> Result<(), DBError> {
        self.db.put(DB_COLUMN, hash, ssz)
    }

    pub fn get_serialized_block(&self, hash: &[u8]) -> Result<Option<Vec<u8>>, DBError> {
        self.db.get(DB_COLUMN, hash)
    }

    pub fn block_exists(&self, hash: &[u8]) -> Result<bool, DBError> {
        self.db.exists(DB_COLUMN, hash)
    }

    pub fn delete_block(&self, hash: &[u8]) -> Result<(), DBError> {
        self.db.delete(DB_COLUMN, hash)
    }

    /// Retrieve the block at a slot given a "head_hash" and a slot.
    ///
    /// A "head_hash" must be a block hash with a slot number greater than or equal to the desired
    /// slot.
    ///
    /// This function will read each block down the chain until it finds a block with the given
    /// slot number. If the slot is skipped, the function will return None.
    ///
    /// If a block is found, a tuple of (block_hash, serialized_block) is returned.
    pub fn block_at_slot(
        &self,
        head_hash: &[u8],
        slot: u64,
    ) -> Result<Option<(BeaconBlockHash, BeaconBlockSsz)>, BeaconBlockAtSlotError> {
        match self.get_serialized_block(head_hash)? {
            None => Err(BeaconBlockAtSlotError::UnknownBeaconBlock),
            Some(ssz) => {
                let block = SszBeaconBlock::from_slice(&ssz)
                    .map_err(|_| BeaconBlockAtSlotError::InvalidBeaconBlock)?;
                match block.slot() {
                    s if s == slot => Ok(Some((head_hash.to_vec(), ssz.to_vec()))),
                    s if s < slot => Ok(None),
                    _ => match block.parent_hash() {
                        Some(parent_hash) => self.block_at_slot(parent_hash, slot),
                        None => Err(BeaconBlockAtSlotError::UnknownBeaconBlock),
                    },
                }
            }
        }
    }
}

impl From<DBError> for BeaconBlockAtSlotError {
    fn from(e: DBError) -> Self {
        BeaconBlockAtSlotError::DBError(e.message)
    }
}

#[cfg(test)]
mod tests {
    extern crate ssz;
    extern crate types;

    use self::ssz::SszStream;
    use self::types::attestation_record::AttestationRecord;
    use self::types::beacon_block::BeaconBlock;
    use self::types::Hash256;

    use super::super::super::MemoryDB;
    use super::*;
    use std::sync::Arc;
    use std::thread;

    #[test]
    fn test_put_serialized_block() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "some bytes".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes()).to_vec();

        store.put_serialized_block(hash, ssz);
        assert_eq!(db.get(DB_COLUMN, hash).unwrap().unwrap(), ssz);
    }

    #[test]
    fn test_get_serialized_block() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "some bytes".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes()).to_vec();

        db.put(DB_COLUMN, hash, ssz);
        assert_eq!(store.get_serialized_block(hash).unwrap().unwrap(), ssz);
    }

    #[test]
    fn test_block_exists() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "some bytes".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes()).to_vec();

        db.put(DB_COLUMN, hash, ssz);
        assert!(store.block_exists(hash).unwrap());
    }

    #[test]
    fn test_block_doesnt_exist() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "some bytes".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes()).to_vec();
        let other_hash = &Hash256::from("another hash".as_bytes()).to_vec();

        db.put(DB_COLUMN, hash, ssz);
        assert!(!store.block_exists(other_hash).unwrap());
    }

    #[test]
    fn test_delete_block() {
        let db = Arc::new(MemoryDB::open());
        let store = BeaconBlockStore::new(db.clone());

        let ssz = "some bytes".as_bytes();
        let hash = &Hash256::from("some hash".as_bytes()).to_vec();

        db.put(DB_COLUMN, hash, ssz);
        assert!(db.exists(DB_COLUMN, hash).unwrap());

        store.delete_block(hash);
        assert!(!db.exists(DB_COLUMN, hash).unwrap());
    }

    #[test]
    fn test_block_store_on_memory_db() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));

        let thread_count = 10;
        let write_count = 10;

        // We're expecting the product of these numbers to fit in one byte.
        assert!(thread_count * write_count <= 255);

        let mut handles = vec![];
        for t in 0..thread_count {
            let wc = write_count;
            let bs = bs.clone();
            let handle = thread::spawn(move || {
                for w in 0..wc {
                    let key = (t * w) as u8;
                    let val = 42;
                    bs.put_serialized_block(&vec![key], &vec![val]).unwrap();
                }
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.join().unwrap();
        }

        for t in 0..thread_count {
            for w in 0..write_count {
                let key = (t * w) as u8;
                assert!(bs.block_exists(&vec![key]).unwrap());
                let val = bs.get_serialized_block(&vec![key]).unwrap().unwrap();
                assert_eq!(vec![42], val);
            }
        }
    }

    #[test]
    fn test_block_at_slot() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BeaconBlockStore::new(db.clone()));

        let blocks = (0..5).into_iter().map(|_| {
            let mut block = BeaconBlock::zero();
            let ar = AttestationRecord::zero();
            block.attestations.push(ar);
            block
        });

        let hashes = [
            Hash256::from("zero".as_bytes()),
            Hash256::from("one".as_bytes()),
            Hash256::from("two".as_bytes()),
            Hash256::from("three".as_bytes()),
            Hash256::from("four".as_bytes()),
        ];

        let parent_hashes = [
            Hash256::from("genesis".as_bytes()),
            Hash256::from("zero".as_bytes()),
            Hash256::from("one".as_bytes()),
            Hash256::from("two".as_bytes()),
            Hash256::from("three".as_bytes()),
        ];

        let slots = [0, 1, 3, 4, 5];

        for (i, mut block) in blocks.enumerate() {
            block.ancestor_hashes.push(parent_hashes[i]);
            block.slot = slots[i];
            let mut s = SszStream::new();
            s.append(&block);
            let ssz = s.drain();
            bs.put_serialized_block(&hashes[i].to_vec(), &ssz).unwrap();
        }

        let tuple = bs.block_at_slot(&hashes[4], 5).unwrap().unwrap();
        let block = SszBeaconBlock::from_slice(&tuple.1).unwrap();
        assert_eq!(block.slot(), 5);
        assert_eq!(tuple.0, hashes[4].to_vec());

        let tuple = bs.block_at_slot(&hashes[4], 4).unwrap().unwrap();
        let block = SszBeaconBlock::from_slice(&tuple.1).unwrap();
        assert_eq!(block.slot(), 4);
        assert_eq!(tuple.0, hashes[3].to_vec());

        let tuple = bs.block_at_slot(&hashes[4], 3).unwrap().unwrap();
        let block = SszBeaconBlock::from_slice(&tuple.1).unwrap();
        assert_eq!(block.slot(), 3);
        assert_eq!(tuple.0, hashes[2].to_vec());

        let tuple = bs.block_at_slot(&hashes[4], 0).unwrap().unwrap();
        let block = SszBeaconBlock::from_slice(&tuple.1).unwrap();
        assert_eq!(block.slot(), 0);
        assert_eq!(tuple.0, hashes[0].to_vec());

        let ssz = bs.block_at_slot(&hashes[4], 2).unwrap();
        assert_eq!(ssz, None);

        let ssz = bs.block_at_slot(&hashes[4], 6).unwrap();
        assert_eq!(ssz, None);

        let ssz = bs.block_at_slot(&Hash256::from("unknown".as_bytes()), 2);
        assert_eq!(ssz, Err(BeaconBlockAtSlotError::UnknownBeaconBlock));
    }
}
<|endoftext|>


<commit_before>use std::io::{self,Error,ErrorKind};
use futures::Future;
use futures::future;
use amq_protocol::types::*;
use tokio_io::{AsyncRead,AsyncWrite};
use std::sync::{Arc,Mutex};
use std::default::Default;

use transport::*;
use consumer::Consumer;
use client::wait_for_answer;

/// `Channel` provides methods to act on a channel, such as managing queues
//#[derive(Clone)]
pub struct Channel<T> {
  pub transport: Arc<Mutex<AMQPTransport<T>>>,
  pub id:    u16,
}

impl<T> Clone for Channel<T> {
  fn clone(&self) -> Channel<T> {
    Channel {
      transport: self.transport.clone(),
      id:        self.id,
    }
  }
}

#[derive(Clone,Debug,PartialEq)]
pub struct QueueDeclareOptions {
  pub passive:     bool,
  pub durable:     bool,
  pub exclusive:   bool,
  pub auto_delete: bool,
  pub nowait:      bool,
}

impl Default for QueueDeclareOptions {
  fn default() -> QueueDeclareOptions {
    QueueDeclareOptions {
      passive:     false,
      durable:     false,
      exclusive:   false,
      auto_delete: false,
      nowait:      false,
    }
  }
}

#[derive(Clone,Debug,PartialEq)]
pub struct BasicPublishOptions {
  pub ticket:    u16,
  pub exchange:  String,
  pub mandatory: bool,
  pub immediate: bool,
}

impl Default for BasicPublishOptions {
  fn default() -> BasicPublishOptions {
    BasicPublishOptions {
      ticket:    0,
      exchange:  "".to_string(),
      mandatory: false,
      immediate: false,
    }
  }
}

#[derive(Clone,Debug,PartialEq)]
pub struct BasicConsumeOptions {
  pub ticket:    u16,
  pub no_local:  bool,
  pub no_ack:    bool,
  pub exclusive: bool,
  pub no_wait:   bool,
}

impl Default for BasicConsumeOptions {
  fn default() -> BasicConsumeOptions {
    BasicConsumeOptions {
      ticket:    0,
      no_local:  false,
      no_ack:    false,
      exclusive: false,
      no_wait:   false,
    }
  }
}

impl<T: AsyncRead+AsyncWrite+'static> Channel<T> {
  /// creates a queue
  ///
  /// returns a future that resolves once the queue is available
  ///
  /// WARNING: this method cannot pass custom queue_declare arguments yet
  pub fn queue_declare(&self, name: &str, options: &QueueDeclareOptions) -> Box<Future<Item = (), Error = io::Error>> {
    let cl_transport = self.transport.clone();

    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.queue_declare(
        self.id, 0, name.to_string(),
        options.passive, options.durable, options.exclusive, options.auto_delete, options.nowait, FieldTable::new()) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not declare queue: {:?}", e)))
        ),
        Ok(request_id) => {
          trace!("queue_declare request id: {}", request_id);
          transport.send_frames();

          transport.handle_frames();

          trace!("queue_declare returning closure");
          wait_for_answer(cl_transport, request_id)
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// publishes a message on a queue
  ///
  /// WARNING: does not handle chunking of the content for now
  pub fn basic_publish(&self, queue: &str, payload: &[u8], options: &BasicPublishOptions) -> Box<Future<Item = (), Error = io::Error>> {
    if let Ok(mut transport) = self.transport.lock() {
      //FIXME: does not handle the return messages with mandatory and immediate
      match transport.conn.basic_publish(self.id, options.ticket, options.exchange.clone(),
        queue.to_string(), options.mandatory, options.immediate) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not publish: {:?}", e)))
        ),
        Ok(_) => {
          transport.send_frames();
          transport.conn.send_content_frames(self.id, 60, payload);
          transport.send_frames();

          transport.handle_frames();

          Box::new(future::ok(()))
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// creates a consumer stream
  ///
  /// returns a future of a `Consumer` that resolves once the method succeeds
  ///
  /// `Consumer` implements `futures::Stream`, so it can be used with any of
  /// the usual combinators
  pub fn basic_consume(&self, queue: &str, consumer_tag: &str, options: &BasicConsumeOptions) -> Box<Future<Item = Consumer<T>, Error = io::Error>> {
    let cl_transport = self.transport.clone();

    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.basic_consume(self.id, options.ticket, queue.to_string(), consumer_tag.to_string(),
        options.no_local, options.no_ack, options.exclusive, options.no_wait, FieldTable::new()) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not start consumer")))
        ),
        Ok(request_id) => {
          transport.send_frames();

          transport.handle_frames();

          let consumer = Consumer {
            transport:    cl_transport.clone(),
            channel_id:   self.id,
            queue:        queue.to_string(),
            consumer_tag: consumer_tag.to_string(),
          };

          trace!("basic_consume returning closure");
          Box::new(wait_for_answer(cl_transport, request_id).map(move |_| {
            trace!("basic_consume received response, returning consumer");
            consumer
          }))
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// acks a message
  pub fn basic_ack(&self, delivery_tag: u64) -> Box<Future<Item = (), Error = io::Error>> {
    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.basic_ack(self.id, delivery_tag, false) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not publish: {:?}", e)))
        ),
        Ok(_) => {
          transport.send_frames();
          Box::new(future::ok(()))
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// rejects a message
  pub fn basic_reject(&self, delivery_tag: u64, requeue: bool) -> Box<Future<Item = (), Error = io::Error>> {
    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.basic_reject(self.id, delivery_tag, requeue) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not publish: {:?}", e)))
        ),
        Ok(_) => {
          transport.send_frames();
          Box::new(future::ok(()))
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// purges a queue
  pub fn queue_purge(&self, name: &str) -> Box<Future<Item = (), Error = io::Error>> {
    let cl_transport = self.transport.clone();

    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.queue_purge(self.id, 0, name.to_string(), false) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not purge queue: {:?}", e)))
        ),
        Ok(request_id) => {
          trace!("purge request id: {}", request_id);
          transport.send_frames();

          transport.handle_frames();

          trace!("purge returning closure");
          wait_for_answer(cl_transport, request_id)
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not purge queue {}", name))
      ))
    }
  }
}
<commit_msg>documentation warning<commit_after>use std::io::{self,Error,ErrorKind};
use futures::Future;
use futures::future;
use amq_protocol::types::*;
use tokio_io::{AsyncRead,AsyncWrite};
use std::sync::{Arc,Mutex};
use std::default::Default;

use transport::*;
use consumer::Consumer;
use client::wait_for_answer;

/// `Channel` provides methods to act on a channel, such as managing queues
//#[derive(Clone)]
pub struct Channel<T> {
  pub transport: Arc<Mutex<AMQPTransport<T>>>,
  pub id:    u16,
}

impl<T> Clone for Channel<T> {
  fn clone(&self) -> Channel<T> {
    Channel {
      transport: self.transport.clone(),
      id:        self.id,
    }
  }
}

#[derive(Clone,Debug,PartialEq)]
pub struct QueueDeclareOptions {
  pub passive:     bool,
  pub durable:     bool,
  pub exclusive:   bool,
  pub auto_delete: bool,
  pub nowait:      bool,
}

impl Default for QueueDeclareOptions {
  fn default() -> QueueDeclareOptions {
    QueueDeclareOptions {
      passive:     false,
      durable:     false,
      exclusive:   false,
      auto_delete: false,
      nowait:      false,
    }
  }
}

#[derive(Clone,Debug,PartialEq)]
pub struct BasicPublishOptions {
  pub ticket:    u16,
  pub exchange:  String,
  pub mandatory: bool,
  pub immediate: bool,
}

impl Default for BasicPublishOptions {
  fn default() -> BasicPublishOptions {
    BasicPublishOptions {
      ticket:    0,
      exchange:  "".to_string(),
      mandatory: false,
      immediate: false,
    }
  }
}

#[derive(Clone,Debug,PartialEq)]
pub struct BasicConsumeOptions {
  pub ticket:    u16,
  pub no_local:  bool,
  pub no_ack:    bool,
  pub exclusive: bool,
  pub no_wait:   bool,
}

impl Default for BasicConsumeOptions {
  fn default() -> BasicConsumeOptions {
    BasicConsumeOptions {
      ticket:    0,
      no_local:  false,
      no_ack:    false,
      exclusive: false,
      no_wait:   false,
    }
  }
}

impl<T: AsyncRead+AsyncWrite+'static> Channel<T> {
  /// creates a queue
  ///
  /// returns a future that resolves once the queue is available
  ///
  /// the `mandatory` and `ìmmediate` options can be set to true,
  /// but the return message will not be handled
  pub fn queue_declare(&self, name: &str, options: &QueueDeclareOptions) -> Box<Future<Item = (), Error = io::Error>> {
    let cl_transport = self.transport.clone();

    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.queue_declare(
        self.id, 0, name.to_string(),
        options.passive, options.durable, options.exclusive, options.auto_delete, options.nowait, FieldTable::new()) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not declare queue: {:?}", e)))
        ),
        Ok(request_id) => {
          trace!("queue_declare request id: {}", request_id);
          transport.send_frames();

          transport.handle_frames();

          trace!("queue_declare returning closure");
          wait_for_answer(cl_transport, request_id)
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// publishes a message on a queue
  ///
  /// WARNING: does not handle chunking of the content for now
  pub fn basic_publish(&self, queue: &str, payload: &[u8], options: &BasicPublishOptions) -> Box<Future<Item = (), Error = io::Error>> {
    if let Ok(mut transport) = self.transport.lock() {
      //FIXME: does not handle the return messages with mandatory and immediate
      match transport.conn.basic_publish(self.id, options.ticket, options.exchange.clone(),
        queue.to_string(), options.mandatory, options.immediate) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not publish: {:?}", e)))
        ),
        Ok(_) => {
          transport.send_frames();
          transport.conn.send_content_frames(self.id, 60, payload);
          transport.send_frames();

          transport.handle_frames();

          Box::new(future::ok(()))
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// creates a consumer stream
  ///
  /// returns a future of a `Consumer` that resolves once the method succeeds
  ///
  /// `Consumer` implements `futures::Stream`, so it can be used with any of
  /// the usual combinators
  pub fn basic_consume(&self, queue: &str, consumer_tag: &str, options: &BasicConsumeOptions) -> Box<Future<Item = Consumer<T>, Error = io::Error>> {
    let cl_transport = self.transport.clone();

    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.basic_consume(self.id, options.ticket, queue.to_string(), consumer_tag.to_string(),
        options.no_local, options.no_ack, options.exclusive, options.no_wait, FieldTable::new()) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not start consumer")))
        ),
        Ok(request_id) => {
          transport.send_frames();

          transport.handle_frames();

          let consumer = Consumer {
            transport:    cl_transport.clone(),
            channel_id:   self.id,
            queue:        queue.to_string(),
            consumer_tag: consumer_tag.to_string(),
          };

          trace!("basic_consume returning closure");
          Box::new(wait_for_answer(cl_transport, request_id).map(move |_| {
            trace!("basic_consume received response, returning consumer");
            consumer
          }))
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// acks a message
  pub fn basic_ack(&self, delivery_tag: u64) -> Box<Future<Item = (), Error = io::Error>> {
    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.basic_ack(self.id, delivery_tag, false) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not publish: {:?}", e)))
        ),
        Ok(_) => {
          transport.send_frames();
          Box::new(future::ok(()))
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// rejects a message
  pub fn basic_reject(&self, delivery_tag: u64, requeue: bool) -> Box<Future<Item = (), Error = io::Error>> {
    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.basic_reject(self.id, delivery_tag, requeue) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not publish: {:?}", e)))
        ),
        Ok(_) => {
          transport.send_frames();
          Box::new(future::ok(()))
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not create channel"))
      ))
    }
  }

  /// purges a queue
  pub fn queue_purge(&self, name: &str) -> Box<Future<Item = (), Error = io::Error>> {
    let cl_transport = self.transport.clone();

    if let Ok(mut transport) = self.transport.lock() {
      match transport.conn.queue_purge(self.id, 0, name.to_string(), false) {
        Err(e) => Box::new(
          future::err(Error::new(ErrorKind::ConnectionAborted, format!("could not purge queue: {:?}", e)))
        ),
        Ok(request_id) => {
          trace!("purge request id: {}", request_id);
          transport.send_frames();

          transport.handle_frames();

          trace!("purge returning closure");
          wait_for_answer(cl_transport, request_id)
        },
      }
    } else {
      //FIXME: if we're there, it means the mutex failed
      Box::new(future::err(
        Error::new(ErrorKind::ConnectionAborted, format!("could not purge queue {}", name))
      ))
    }
  }
}
<|endoftext|>


<commit_before>use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::query::outlives_bounds::InferCtxtExt as _;
use crate::traits::{self, TraitEngine, TraitEngineExt};

use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::traits::ObligationCause;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
use rustc_middle::traits::query::Fallible;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::WithConstness;
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_span::{Span, DUMMY_SP};

use std::fmt::Debug;

pub use rustc_infer::infer::*;

pub trait InferCtxtExt<'tcx> {
    fn type_is_copy_modulo_regions(
        &self,
        param_env: ty::ParamEnv<'tcx>,
        ty: Ty<'tcx>,
        span: Span,
    ) -> bool;

    fn partially_normalize_associated_types_in<T>(
        &self,
        cause: ObligationCause<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
        value: T,
    ) -> InferOk<'tcx, T>
    where
        T: TypeFoldable<'tcx>;

    /// Check whether a `ty` implements given trait(trait_def_id).
    /// The inputs are:
    ///
    /// - the def-id of the trait
    /// - the self type
    /// - the *other* type parameters of the trait, excluding the self-type
    /// - the parameter environment
    fn type_implements_trait(
        &self,
        trait_def_id: DefId,
        ty: Ty<'tcx>,
        params: SubstsRef<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
    ) -> traits::EvaluationResult;
}
impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
    fn type_is_copy_modulo_regions(
        &self,
        param_env: ty::ParamEnv<'tcx>,
        ty: Ty<'tcx>,
        span: Span,
    ) -> bool {
        let ty = self.resolve_vars_if_possible(ty);

        if !(param_env, ty).needs_infer() {
            return ty.is_copy_modulo_regions(self.tcx.at(span), param_env);
        }

        let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None);

        // This can get called from typeck (by euv), and `moves_by_default`
        // rightly refuses to work with inference variables, but
        // moves_by_default has a cache, which we want to use in other
        // cases.
        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
    }

    /// Normalizes associated types in `value`, potentially returning
    /// new obligations that must further be processed.
    fn partially_normalize_associated_types_in<T>(
        &self,
        cause: ObligationCause<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
        value: T,
    ) -> InferOk<'tcx, T>
    where
        T: TypeFoldable<'tcx>,
    {
        debug!("partially_normalize_associated_types_in(value={:?})", value);
        let mut selcx = traits::SelectionContext::new(self);
        let traits::Normalized { value, obligations } =
            traits::normalize(&mut selcx, param_env, cause, value);
        debug!(
            "partially_normalize_associated_types_in: result={:?} predicates={:?}",
            value, obligations
        );
        InferOk { value, obligations }
    }

    fn type_implements_trait(
        &self,
        trait_def_id: DefId,
        ty: Ty<'tcx>,
        params: SubstsRef<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
    ) -> traits::EvaluationResult {
        debug!(
            "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
            trait_def_id, ty, params, param_env
        );

        let trait_ref =
            ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) };

        let obligation = traits::Obligation {
            cause: traits::ObligationCause::dummy(),
            param_env,
            recursion_depth: 0,
            predicate: trait_ref.without_const().to_predicate(self.tcx),
        };
        self.evaluate_obligation_no_overflow(&obligation)
    }
}

pub trait InferCtxtBuilderExt<'tcx> {
    fn enter_canonical_trait_query<K, R>(
        &mut self,
        canonical_key: &Canonical<'tcx, K>,
        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
    where
        K: TypeFoldable<'tcx>,
        R: Debug + TypeFoldable<'tcx>,
        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>;
}

impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
    /// The "main method" for a canonicalized trait query. Given the
    /// canonical key `canonical_key`, this method will create a new
    /// inference context, instantiate the key, and run your operation
    /// `op`. The operation should yield up a result (of type `R`) as
    /// well as a set of trait obligations that must be fully
    /// satisfied. These obligations will be processed and the
    /// canonical result created.
    ///
    /// Returns `NoSolution` in the event of any error.
    ///
    /// (It might be mildly nicer to implement this on `TyCtxt`, and
    /// not `InferCtxtBuilder`, but that is a bit tricky right now.
    /// In part because we would need a `for<'tcx>` sort of
    /// bound for the closure and in part because it is convenient to
    /// have `'tcx` be free on this function so that we can talk about
    /// `K: TypeFoldable<'tcx>`.)
    fn enter_canonical_trait_query<K, R>(
        &mut self,
        canonical_key: &Canonical<'tcx, K>,
        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
    where
        K: TypeFoldable<'tcx>,
        R: Debug + TypeFoldable<'tcx>,
        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
    {
        self.enter_with_canonical(
            DUMMY_SP,
            canonical_key,
            |ref infcx, key, canonical_inference_vars| {
                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
                let value = operation(infcx, &mut *fulfill_cx, key)?;
                infcx.make_canonicalized_query_response(
                    canonical_inference_vars,
                    value,
                    &mut *fulfill_cx,
                )
            },
        )
    }
}

pub trait OutlivesEnvironmentExt<'tcx> {
    fn add_implied_bounds(
        &mut self,
        infcx: &InferCtxt<'a, 'tcx>,
        fn_sig_tys: &[Ty<'tcx>],
        body_id: hir::HirId,
        span: Span,
    );
}

impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
    /// This method adds "implied bounds" into the outlives environment.
    /// Implied bounds are outlives relationships that we can deduce
    /// on the basis that certain types must be well-formed -- these are
    /// either the types that appear in the function signature or else
    /// the input types to an impl. For example, if you have a function
    /// like
    ///
    /// ```
    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
    /// ```
    ///
    /// we can assume in the caller's body that `'b: 'a` and that `T:
    /// 'b` (and hence, transitively, that `T: 'a`). This method would
    /// add those assumptions into the outlives-environment.
    ///
    /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
    fn add_implied_bounds(
        &mut self,
        infcx: &InferCtxt<'a, 'tcx>,
        fn_sig_tys: &[Ty<'tcx>],
        body_id: hir::HirId,
        span: Span,
    ) {
        debug!("add_implied_bounds()");

        for &ty in fn_sig_tys {
            let ty = infcx.resolve_vars_if_possible(ty);
            debug!("add_implied_bounds: ty = {}", ty);
            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
            self.add_outlives_bounds(Some(infcx), implied_bounds)
        }
    }
}
<commit_msg>Rollup merge of #88320 - sexxi-goose:issue-88103, r=nikomatsakis<commit_after>use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::query::outlives_bounds::InferCtxtExt as _;
use crate::traits::{self, TraitEngine, TraitEngineExt};

use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::traits::ObligationCause;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
use rustc_middle::traits::query::Fallible;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::WithConstness;
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_span::{Span, DUMMY_SP};

use std::fmt::Debug;

pub use rustc_infer::infer::*;

pub trait InferCtxtExt<'tcx> {
    fn type_is_copy_modulo_regions(
        &self,
        param_env: ty::ParamEnv<'tcx>,
        ty: Ty<'tcx>,
        span: Span,
    ) -> bool;

    fn partially_normalize_associated_types_in<T>(
        &self,
        cause: ObligationCause<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
        value: T,
    ) -> InferOk<'tcx, T>
    where
        T: TypeFoldable<'tcx>;

    /// Check whether a `ty` implements given trait(trait_def_id).
    /// The inputs are:
    ///
    /// - the def-id of the trait
    /// - the self type
    /// - the *other* type parameters of the trait, excluding the self-type
    /// - the parameter environment
    ///
    /// Invokes `evaluate_obligation`, so in the event that evaluating
    /// `Ty: Trait` causes overflow, EvaluatedToRecur (or EvaluatedToUnknown)
    /// will be returned.
    fn type_implements_trait(
        &self,
        trait_def_id: DefId,
        ty: Ty<'tcx>,
        params: SubstsRef<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
    ) -> traits::EvaluationResult;
}
impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
    fn type_is_copy_modulo_regions(
        &self,
        param_env: ty::ParamEnv<'tcx>,
        ty: Ty<'tcx>,
        span: Span,
    ) -> bool {
        let ty = self.resolve_vars_if_possible(ty);

        if !(param_env, ty).needs_infer() {
            return ty.is_copy_modulo_regions(self.tcx.at(span), param_env);
        }

        let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None);

        // This can get called from typeck (by euv), and `moves_by_default`
        // rightly refuses to work with inference variables, but
        // moves_by_default has a cache, which we want to use in other
        // cases.
        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
    }

    /// Normalizes associated types in `value`, potentially returning
    /// new obligations that must further be processed.
    fn partially_normalize_associated_types_in<T>(
        &self,
        cause: ObligationCause<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
        value: T,
    ) -> InferOk<'tcx, T>
    where
        T: TypeFoldable<'tcx>,
    {
        debug!("partially_normalize_associated_types_in(value={:?})", value);
        let mut selcx = traits::SelectionContext::new(self);
        let traits::Normalized { value, obligations } =
            traits::normalize(&mut selcx, param_env, cause, value);
        debug!(
            "partially_normalize_associated_types_in: result={:?} predicates={:?}",
            value, obligations
        );
        InferOk { value, obligations }
    }

    fn type_implements_trait(
        &self,
        trait_def_id: DefId,
        ty: Ty<'tcx>,
        params: SubstsRef<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
    ) -> traits::EvaluationResult {
        debug!(
            "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
            trait_def_id, ty, params, param_env
        );

        let trait_ref =
            ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) };

        let obligation = traits::Obligation {
            cause: traits::ObligationCause::dummy(),
            param_env,
            recursion_depth: 0,
            predicate: trait_ref.without_const().to_predicate(self.tcx),
        };
        self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr)
    }
}

pub trait InferCtxtBuilderExt<'tcx> {
    fn enter_canonical_trait_query<K, R>(
        &mut self,
        canonical_key: &Canonical<'tcx, K>,
        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
    where
        K: TypeFoldable<'tcx>,
        R: Debug + TypeFoldable<'tcx>,
        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>;
}

impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
    /// The "main method" for a canonicalized trait query. Given the
    /// canonical key `canonical_key`, this method will create a new
    /// inference context, instantiate the key, and run your operation
    /// `op`. The operation should yield up a result (of type `R`) as
    /// well as a set of trait obligations that must be fully
    /// satisfied. These obligations will be processed and the
    /// canonical result created.
    ///
    /// Returns `NoSolution` in the event of any error.
    ///
    /// (It might be mildly nicer to implement this on `TyCtxt`, and
    /// not `InferCtxtBuilder`, but that is a bit tricky right now.
    /// In part because we would need a `for<'tcx>` sort of
    /// bound for the closure and in part because it is convenient to
    /// have `'tcx` be free on this function so that we can talk about
    /// `K: TypeFoldable<'tcx>`.)
    fn enter_canonical_trait_query<K, R>(
        &mut self,
        canonical_key: &Canonical<'tcx, K>,
        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
    where
        K: TypeFoldable<'tcx>,
        R: Debug + TypeFoldable<'tcx>,
        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
    {
        self.enter_with_canonical(
            DUMMY_SP,
            canonical_key,
            |ref infcx, key, canonical_inference_vars| {
                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
                let value = operation(infcx, &mut *fulfill_cx, key)?;
                infcx.make_canonicalized_query_response(
                    canonical_inference_vars,
                    value,
                    &mut *fulfill_cx,
                )
            },
        )
    }
}

pub trait OutlivesEnvironmentExt<'tcx> {
    fn add_implied_bounds(
        &mut self,
        infcx: &InferCtxt<'a, 'tcx>,
        fn_sig_tys: &[Ty<'tcx>],
        body_id: hir::HirId,
        span: Span,
    );
}

impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
    /// This method adds "implied bounds" into the outlives environment.
    /// Implied bounds are outlives relationships that we can deduce
    /// on the basis that certain types must be well-formed -- these are
    /// either the types that appear in the function signature or else
    /// the input types to an impl. For example, if you have a function
    /// like
    ///
    /// ```
    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
    /// ```
    ///
    /// we can assume in the caller's body that `'b: 'a` and that `T:
    /// 'b` (and hence, transitively, that `T: 'a`). This method would
    /// add those assumptions into the outlives-environment.
    ///
    /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
    fn add_implied_bounds(
        &mut self,
        infcx: &InferCtxt<'a, 'tcx>,
        fn_sig_tys: &[Ty<'tcx>],
        body_id: hir::HirId,
        span: Span,
    ) {
        debug!("add_implied_bounds()");

        for &ty in fn_sig_tys {
            let ty = infcx.resolve_vars_if_possible(ty);
            debug!("add_implied_bounds: ty = {}", ty);
            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
            self.add_outlives_bounds(Some(infcx), implied_bounds)
        }
    }
}
<|endoftext|>


<commit_before>//! Module for built-in filter functions
//!
//! Contains all the built-in filter functions for use in templates.
//! Currently, there is no way to define filters outside this module.
use std::fmt;

fn escapable(b: &u8) -> bool {
    *b == b'<' || *b == b'>' || *b == b'&'
}

/// Escapes `&`, `<` and `>` in strings
pub fn escape(s: &fmt::Display) -> String {
    let s = format!("{}", s);
    let mut found = Vec::new();
    for (i, b) in s.as_bytes().iter().enumerate() {
        if escapable(b) {
            found.push(i);
        }
    }
    if found.is_empty() {
        return s;
    }

    let bytes = s.as_bytes();
    let max_len = bytes.len() + found.len() * 3;
    let mut res = Vec::<u8>::with_capacity(max_len);
    let mut start = 0;
    for idx in &found {
        if start < *idx {
            res.extend(&bytes[start..*idx]);
        }
        start = *idx + 1;
        match bytes[*idx] {
            b'<' => { res.extend(b"<"); },
            b'>' => { res.extend(b">"); },
            b'&' => { res.extend(b"&"); },
            _ => panic!("incorrect indexing"),
        }
    }
    if start < bytes.len() - 1 {
        res.extend(&bytes[start..]);
    }

    String::from_utf8(res).unwrap()
}

/// Alias for the `escape()` filter
pub fn e(s: &fmt::Display) -> String {
    escape(s)
}

/// Formats arguments according to the specified format
///
/// The first argument to this filter must be a string literal (as in normal
/// Rust). All arguments are passed through to the `format!()`
/// [macro](https://doc.rust-lang.org/stable/std/macro.format.html) by
/// the Askama code generator.
pub fn format() { }

/// Converts to lowercase.
pub fn lower(s: &fmt::Display) -> String {
    let s = format!("{}", s);
    s.to_lowercase()
}

/// Alias for the `lower()` filter.
pub fn lowercase(s: &fmt::Display) -> String {
    lower(s)
}

/// Converts to uppercase.
pub fn upper(s: &fmt::Display) -> String {
    let s = format!("{}", s);
    s.to_uppercase()
}

/// Alias for the `upper()` filter.
pub fn uppercase(s: &fmt::Display) -> String {
    upper(s)
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_escape() {
        assert_eq!(escape(&""), "");
        assert_eq!(escape(&"<&>"), "<&>");
        assert_eq!(escape(&"bla&"), "bla&");
        assert_eq!(escape(&"<foo"), "<foo");

        assert_eq!(lower(&"Foo"), "foo");
        assert_eq!(lower(&"FOO"), "foo");
        assert_eq!(lower(&"FooBar"), "foobar");
        assert_eq!(lower(&"foo"), "foo");

        assert_eq!(upper(&"Foo"), "FOO");
        assert_eq!(upper(&"FOO"), "FOO");
        assert_eq!(upper(&"FooBar"), "FOOBAR");
        assert_eq!(upper(&"foo"), "FOO");
    }
}
<commit_msg>added trim filter (#18)<commit_after>//! Module for built-in filter functions
//!
//! Contains all the built-in filter functions for use in templates.
//! Currently, there is no way to define filters outside this module.
use std::fmt;

fn escapable(b: &u8) -> bool {
    *b == b'<' || *b == b'>' || *b == b'&'
}

/// Escapes `&`, `<` and `>` in strings
pub fn escape(s: &fmt::Display) -> String {
    let s = format!("{}", s);
    let mut found = Vec::new();
    for (i, b) in s.as_bytes().iter().enumerate() {
        if escapable(b) {
            found.push(i);
        }
    }
    if found.is_empty() {
        return s;
    }

    let bytes = s.as_bytes();
    let max_len = bytes.len() + found.len() * 3;
    let mut res = Vec::<u8>::with_capacity(max_len);
    let mut start = 0;
    for idx in &found {
        if start < *idx {
            res.extend(&bytes[start..*idx]);
        }
        start = *idx + 1;
        match bytes[*idx] {
            b'<' => { res.extend(b"<"); },
            b'>' => { res.extend(b">"); },
            b'&' => { res.extend(b"&"); },
            _ => panic!("incorrect indexing"),
        }
    }
    if start < bytes.len() - 1 {
        res.extend(&bytes[start..]);
    }

    String::from_utf8(res).unwrap()
}

/// Alias for the `escape()` filter
pub fn e(s: &fmt::Display) -> String {
    escape(s)
}

/// Formats arguments according to the specified format
///
/// The first argument to this filter must be a string literal (as in normal
/// Rust). All arguments are passed through to the `format!()`
/// [macro](https://doc.rust-lang.org/stable/std/macro.format.html) by
/// the Askama code generator.
pub fn format() { }

/// Converts to lowercase.
pub fn lower(s: &fmt::Display) -> String {
    let s = format!("{}", s);
    s.to_lowercase()
}

/// Alias for the `lower()` filter.
pub fn lowercase(s: &fmt::Display) -> String {
    lower(s)
}

/// Converts to uppercase.
pub fn upper(s: &fmt::Display) -> String {
    let s = format!("{}", s);
    s.to_uppercase()
}

/// Alias for the `upper()` filter.
pub fn uppercase(s: &fmt::Display) -> String {
    upper(s)
}

/// Strip leading and trailing whitespace.
pub fn trim(s: &fmt::Display) -> String {
    let s = format!("{}", s);
    s.trim().to_owned()
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_escape() {
        assert_eq!(escape(&""), "");
        assert_eq!(escape(&"<&>"), "<&>");
        assert_eq!(escape(&"bla&"), "bla&");
        assert_eq!(escape(&"<foo"), "<foo");

        assert_eq!(lower(&"Foo"), "foo");
        assert_eq!(lower(&"FOO"), "foo");
        assert_eq!(lower(&"FooBar"), "foobar");
        assert_eq!(lower(&"foo"), "foo");

        assert_eq!(upper(&"Foo"), "FOO");
        assert_eq!(upper(&"FOO"), "FOO");
        assert_eq!(upper(&"FooBar"), "FOOBAR");
        assert_eq!(upper(&"foo"), "FOO");
    }

    #[test]
    fn test_trim() {
        assert_eq!(trim(&" Hello\tworld\t"), "Hello\tworld");
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate futures;
extern crate tokio_core;

use std::time::{Instant, Duration};

use tokio_core::reactor::{Core, Timeout};

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

#[test]
fn smoke() {
    drop(env_logger::init());
    let mut l = t!(Core::new());
    let dur = Duration::from_millis(10);
    let timeout = t!(Timeout::new(dur, &l.handle()));
    let start = Instant::now();
    t!(l.run(timeout));
    assert!(start.elapsed() >= dur);
}

#[test]
fn two() {
    drop(env_logger::init());

    let mut l = t!(Core::new());
    let dur = Duration::from_millis(10);
    let timeout = t!(Timeout::new(dur, &l.handle()));
    t!(l.run(timeout));
    let timeout = t!(Timeout::new(dur, &l.handle()));
    t!(l.run(timeout));
}
<commit_msg>Allow a bit of sloppiness in the timeout test<commit_after>extern crate env_logger;
extern crate futures;
extern crate tokio_core;

use std::time::{Instant, Duration};

use tokio_core::reactor::{Core, Timeout};

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

#[test]
fn smoke() {
    drop(env_logger::init());
    let mut l = t!(Core::new());
    let dur = Duration::from_millis(10);
    let timeout = t!(Timeout::new(dur, &l.handle()));
    let start = Instant::now();
    t!(l.run(timeout));
    assert!(start.elapsed() >= (dur / 2));
}

#[test]
fn two() {
    drop(env_logger::init());

    let mut l = t!(Core::new());
    let dur = Duration::from_millis(10);
    let timeout = t!(Timeout::new(dur, &l.handle()));
    t!(l.run(timeout));
    let timeout = t!(Timeout::new(dur, &l.handle()));
    t!(l.run(timeout));
}
<|endoftext|>


<commit_before>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

#![allow(deprecated)]

use clap::Parser;

#[test]
fn bool_type_is_flag() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long, action)]
        alice: bool,
    }

    assert_eq!(
        Opt { alice: false },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "--alice"]).unwrap()
    );
    assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
    assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
fn count() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long, action = clap::ArgAction::Count)]
        alice: u8,
        #[clap(short, long, action = clap::ArgAction::Count)]
        bob: u8,
    }

    assert_eq!(
        Opt { alice: 0, bob: 0 },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 1, bob: 0 },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 2, bob: 0 },
        Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 2, bob: 2 },
        Opt::try_parse_from(&["test", "-a", "--alice", "-bb"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 3, bob: 1 },
        Opt::try_parse_from(&["test", "-aaa", "--bob"]).unwrap()
    );
    assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
    assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
fn non_bool_type_flag() {
    fn parse_from_flag(b: bool) -> std::sync::atomic::AtomicBool {
        std::sync::atomic::AtomicBool::new(b)
    }

    #[derive(Parser, Debug)]
    struct Opt {
        #[clap(short, long, parse(from_flag = parse_from_flag))]
        alice: std::sync::atomic::AtomicBool,
        #[clap(short, long, parse(from_flag))]
        bob: std::sync::atomic::AtomicBool,
    }

    let falsey = Opt::try_parse_from(&["test"]).unwrap();
    assert!(!falsey.alice.load(std::sync::atomic::Ordering::Relaxed));
    assert!(!falsey.bob.load(std::sync::atomic::Ordering::Relaxed));

    let alice = Opt::try_parse_from(&["test", "-a"]).unwrap();
    assert!(alice.alice.load(std::sync::atomic::Ordering::Relaxed));
    assert!(!alice.bob.load(std::sync::atomic::Ordering::Relaxed));

    let bob = Opt::try_parse_from(&["test", "-b"]).unwrap();
    assert!(!bob.alice.load(std::sync::atomic::Ordering::Relaxed));
    assert!(bob.bob.load(std::sync::atomic::Ordering::Relaxed));

    let both = Opt::try_parse_from(&["test", "-b", "-a"]).unwrap();
    assert!(both.alice.load(std::sync::atomic::Ordering::Relaxed));
    assert!(both.bob.load(std::sync::atomic::Ordering::Relaxed));
}

#[test]
fn mixed_type_flags() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long, action)]
        alice: bool,
        #[clap(short, long, action = clap::ArgAction::Count)]
        bob: u8,
    }

    assert_eq!(
        Opt {
            alice: false,
            bob: 0
        },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 0
        },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 0
        },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: false,
            bob: 1
        },
        Opt::try_parse_from(&["test", "-b"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 1
        },
        Opt::try_parse_from(&["test", "--alice", "--bob"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 4
        },
        Opt::try_parse_from(&["test", "-bb", "-a", "-bb"]).unwrap()
    );
}

#[test]
fn ignore_qualified_bool_type() {
    mod inner {
        #[allow(non_camel_case_types)]
        #[derive(PartialEq, Debug)]
        pub struct bool(pub String);

        impl std::str::FromStr for self::bool {
            type Err = String;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                Ok(self::bool(s.into()))
            }
        }
    }

    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        arg: inner::bool,
    }

    assert_eq!(
        Opt {
            arg: inner::bool("success".into())
        },
        Opt::try_parse_from(&["test", "success"]).unwrap()
    );
}

#[test]
fn override_implicit_action() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(long, action = clap::ArgAction::Set)]
        arg: bool,
    }

    assert_eq!(
        Opt { arg: false },
        Opt::try_parse_from(&["test", "--arg", "false"]).unwrap()
    );

    assert_eq!(
        Opt { arg: true },
        Opt::try_parse_from(&["test", "--arg", "true"]).unwrap()
    );
}

#[test]
fn override_implicit_from_flag_positional() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(action = clap::ArgAction::Set)]
        arg: bool,
    }

    assert_eq!(
        Opt { arg: false },
        Opt::try_parse_from(&["test", "false"]).unwrap()
    );

    assert_eq!(
        Opt { arg: true },
        Opt::try_parse_from(&["test", "true"]).unwrap()
    );
}
<commit_msg>test(derive): Update another case to new approach<commit_after>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

#![allow(deprecated)]

use clap::Parser;

#[test]
fn bool_type_is_flag() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long, action)]
        alice: bool,
    }

    assert_eq!(
        Opt { alice: false },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "--alice"]).unwrap()
    );
    assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
    assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
fn count() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long, action = clap::ArgAction::Count)]
        alice: u8,
        #[clap(short, long, action = clap::ArgAction::Count)]
        bob: u8,
    }

    assert_eq!(
        Opt { alice: 0, bob: 0 },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 1, bob: 0 },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 2, bob: 0 },
        Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 2, bob: 2 },
        Opt::try_parse_from(&["test", "-a", "--alice", "-bb"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 3, bob: 1 },
        Opt::try_parse_from(&["test", "-aaa", "--bob"]).unwrap()
    );
    assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
    assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
fn non_bool_type_flag() {
    fn parse_from_flag(b: bool) -> std::sync::atomic::AtomicBool {
        std::sync::atomic::AtomicBool::new(b)
    }

    #[derive(Parser, Debug)]
    struct Opt {
        #[clap(short, long, parse(from_flag = parse_from_flag))]
        alice: std::sync::atomic::AtomicBool,
        #[clap(short, long, parse(from_flag))]
        bob: std::sync::atomic::AtomicBool,
    }

    let falsey = Opt::try_parse_from(&["test"]).unwrap();
    assert!(!falsey.alice.load(std::sync::atomic::Ordering::Relaxed));
    assert!(!falsey.bob.load(std::sync::atomic::Ordering::Relaxed));

    let alice = Opt::try_parse_from(&["test", "-a"]).unwrap();
    assert!(alice.alice.load(std::sync::atomic::Ordering::Relaxed));
    assert!(!alice.bob.load(std::sync::atomic::Ordering::Relaxed));

    let bob = Opt::try_parse_from(&["test", "-b"]).unwrap();
    assert!(!bob.alice.load(std::sync::atomic::Ordering::Relaxed));
    assert!(bob.bob.load(std::sync::atomic::Ordering::Relaxed));

    let both = Opt::try_parse_from(&["test", "-b", "-a"]).unwrap();
    assert!(both.alice.load(std::sync::atomic::Ordering::Relaxed));
    assert!(both.bob.load(std::sync::atomic::Ordering::Relaxed));
}

#[test]
fn mixed_type_flags() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long, action)]
        alice: bool,
        #[clap(short, long, action = clap::ArgAction::Count)]
        bob: u8,
    }

    assert_eq!(
        Opt {
            alice: false,
            bob: 0
        },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 0
        },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 0
        },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: false,
            bob: 1
        },
        Opt::try_parse_from(&["test", "-b"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 1
        },
        Opt::try_parse_from(&["test", "--alice", "--bob"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 4
        },
        Opt::try_parse_from(&["test", "-bb", "-a", "-bb"]).unwrap()
    );
}

#[test]
fn ignore_qualified_bool_type() {
    mod inner {
        #[allow(non_camel_case_types)]
        #[derive(PartialEq, Debug, Clone)]
        pub struct bool(pub String);

        impl std::str::FromStr for self::bool {
            type Err = String;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                Ok(self::bool(s.into()))
            }
        }
    }

    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(action)]
        arg: inner::bool,
    }

    assert_eq!(
        Opt {
            arg: inner::bool("success".into())
        },
        Opt::try_parse_from(&["test", "success"]).unwrap()
    );
}

#[test]
fn override_implicit_action() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(long, action = clap::ArgAction::Set)]
        arg: bool,
    }

    assert_eq!(
        Opt { arg: false },
        Opt::try_parse_from(&["test", "--arg", "false"]).unwrap()
    );

    assert_eq!(
        Opt { arg: true },
        Opt::try_parse_from(&["test", "--arg", "true"]).unwrap()
    );
}

#[test]
fn override_implicit_from_flag_positional() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(action = clap::ArgAction::Set)]
        arg: bool,
    }

    assert_eq!(
        Opt { arg: false },
        Opt::try_parse_from(&["test", "false"]).unwrap()
    );

    assert_eq!(
        Opt { arg: true },
        Opt::try_parse_from(&["test", "true"]).unwrap()
    );
}
<|endoftext|>


<commit_before>// Copyright 2017 Jan-Erik Rediger <badboy@archlinux.us>
//
// Adopted from tests in `tests/assembler.rs`
//
// Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
// the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate rbpf;
mod common;

use rbpf::assembler::assemble;
use rbpf::disassembler::to_insn_vec;

// Using a macro to keep actual line numbers in failure output
macro_rules! disasm {
    ($src:expr) => {
        {
            let src = $src;
            let asm = assemble(src).expect("Can't assemble from string");
            let insn = to_insn_vec(&asm);
            let reasm = insn.into_iter().map(|ins| ins.desc).collect::<Vec<_>>().join("\n");

            assert_eq!(src, reasm);
        }
    }
}

#[test]
fn test_empty() {
    disasm!("");
}

// Example for InstructionType::NoOperand.
#[test]
fn test_exit() {
    disasm!("exit");
}

// Example for InstructionType::AluBinary.
#[test]
fn test_add64() {
    disasm!("add64 r1, r3");
    disasm!("add64 r1, 0x5");
}

// Example for InstructionType::AluUnary.
#[test]
fn test_neg64() {
    disasm!("neg64 r1");
}

// Example for InstructionType::LoadReg.
#[test]
fn test_ldxw() {
    disasm!("ldxw r1, [r2+0x5]");
}

// Example for InstructionType::StoreImm.
#[test]
fn test_stw() {
    disasm!("stw [r2+0x5], 0x7");
}

// Example for InstructionType::StoreReg.
#[test]
fn test_stxw() {
    disasm!("stxw [r2+0x5], r8");
}

// Example for InstructionType::JumpUnconditional.
#[test]
fn test_ja() {
    disasm!("ja +0x8");
}

// Example for InstructionType::JumpConditional.
#[test]
fn test_jeq() {
    disasm!("jeq r1, 0x4, +0x8");
    disasm!("jeq r1, r3, +0x8");
}

// Example for InstructionType::Call.
#[test]
fn test_call() {
    disasm!("call 0x3");
}

// Example for InstructionType::Endian.
#[test]
fn test_be32() {
    disasm!("be32 r1");
}

// Example for InstructionType::LoadImm.
#[test]
fn test_lddw() {
    disasm!("lddw r1, 0x1234abcd5678eeff");
    disasm!("lddw r1, 0xff11ee22dd33cc44");
}

// Example for InstructionType::LoadAbs.
#[test]
fn test_ldabsw() {
    disasm!("ldabsw 0x1");
}

// Example for InstructionType::LoadInd.
#[test]
fn test_ldindw() {
    disasm!("ldindw r1, 0x2");
}

// Example for InstructionType::LoadReg.
#[test]
fn test_ldxdw() {
    disasm!("ldxdw r1, [r2+0x3]");
}

// Example for InstructionType::StoreImm.
#[test]
fn test_sth() {
    disasm!("sth [r1+0x2], 0x3");
}

// Example for InstructionType::StoreReg.
#[test]
fn test_stxh() {
    disasm!("stxh [r1+0x2], r3");
}

// Test all supported AluBinary mnemonics.
#[test]
fn test_alu_binary() {
    disasm!("add64 r1, r2
sub64 r1, r2
mul64 r1, r2
div64 r1, r2
or64 r1, r2
and64 r1, r2
lsh64 r1, r2
rsh64 r1, r2
mod64 r1, r2
xor64 r1, r2
mov64 r1, r2
arsh64 r1, r2");

    disasm!("add64 r1, 0x2
sub64 r1, 0x2
mul64 r1, 0x2
div64 r1, 0x2
or64 r1, 0x2
and64 r1, 0x2
lsh64 r1, 0x2
rsh64 r1, 0x2
mod64 r1, 0x2
xor64 r1, 0x2
mov64 r1, 0x2
arsh64 r1, 0x2");

    disasm!("add32 r1, r2
sub32 r1, r2
mul32 r1, r2
div32 r1, r2
or32 r1, r2
and32 r1, r2
lsh32 r1, r2
rsh32 r1, r2
mod32 r1, r2
xor32 r1, r2
mov32 r1, r2
arsh32 r1, r2");

    disasm!("add32 r1, 0x2
sub32 r1, 0x2
mul32 r1, 0x2
div32 r1, 0x2
or32 r1, 0x2
and32 r1, 0x2
lsh32 r1, 0x2
rsh32 r1, 0x2
mod32 r1, 0x2
xor32 r1, 0x2
mov32 r1, 0x2
arsh32 r1, 0x2");
}

// Test all supported AluUnary mnemonics.
#[test]
fn test_alu_unary() {
    disasm!("neg64 r1
neg32 r1");
}

// Test all supported LoadAbs mnemonics.
#[test]
fn test_load_abs() {
    disasm!("ldabsw 0x1
ldabsh 0x1
ldabsb 0x1
ldabsdw 0x1");
}

// Test all supported LoadInd mnemonics.
#[test]
fn test_load_ind() {
    disasm!("ldindw r1, 0x2
ldindh r1, 0x2
ldindb r1, 0x2
ldinddw r1, 0x2");
}

// Test all supported LoadReg mnemonics.
#[test]
fn test_load_reg() {
    disasm!(r"ldxw r1, [r2+0x3]
ldxh r1, [r2+0x3]
ldxb r1, [r2+0x3]
ldxdw r1, [r2+0x3]");
}

// Test all supported StoreImm mnemonics.
#[test]
fn test_store_imm() {
    disasm!("stw [r1+0x2], 0x3
sth [r1+0x2], 0x3
stb [r1+0x2], 0x3
stdw [r1+0x2], 0x3");
}

// Test all supported StoreReg mnemonics.
#[test]
fn test_store_reg() {
    disasm!("stxw [r1+0x2], r3
stxh [r1+0x2], r3
stxb [r1+0x2], r3
stxdw [r1+0x2], r3");
}

// Test all supported JumpConditional mnemonics.
#[test]
fn test_jump_conditional() {
    disasm!("jeq r1, r2, +0x3
jgt r1, r2, +0x3
jge r1, r2, +0x3
jlt r1, r2, +0x3
jle r1, r2, +0x3
jset r1, r2, +0x3
jne r1, r2, +0x3
jsgt r1, r2, +0x3
jsge r1, r2, +0x3
jslt r1, r2, +0x3
jsle r1, r2, +0x3");

    disasm!("jeq r1, 0x2, +0x3
jgt r1, 0x2, +0x3
jge r1, 0x2, +0x3
jlt r1, 0x2, +0x3
jle r1, 0x2, +0x3
jset r1, 0x2, +0x3
jne r1, 0x2, +0x3
jsgt r1, 0x2, +0x3
jsge r1, 0x2, +0x3
jslt r1, 0x2, +0x3
jsle r1, 0x2, +0x3");
}

// Test all supported Endian mnemonics.
#[test]
fn test_endian() {
    disasm!("be16 r1
be32 r1
be64 r1
le16 r1
le32 r1
le64 r1");
}

#[test]
fn test_large_immediate() {
    disasm!("add64 r1, 0x7fffffff");
    disasm!("add64 r1, 0x7fffffff");
}
<commit_msg>tests/disassembler: Use negative offsets in disassembler tests<commit_after>// Copyright 2017 Jan-Erik Rediger <badboy@archlinux.us>
//
// Adopted from tests in `tests/assembler.rs`
//
// Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
// the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate rbpf;
mod common;

use rbpf::assembler::assemble;
use rbpf::disassembler::to_insn_vec;

// Using a macro to keep actual line numbers in failure output
macro_rules! disasm {
    ($src:expr) => {
        {
            let src = $src;
            let asm = assemble(src).expect("Can't assemble from string");
            let insn = to_insn_vec(&asm);
            let reasm = insn.into_iter().map(|ins| ins.desc).collect::<Vec<_>>().join("\n");

            assert_eq!(src, reasm);
        }
    }
}

#[test]
fn test_empty() {
    disasm!("");
}

// Example for InstructionType::NoOperand.
#[test]
fn test_exit() {
    disasm!("exit");
}

// Example for InstructionType::AluBinary.
#[test]
fn test_add64() {
    disasm!("add64 r1, r3");
    disasm!("add64 r1, 0x5");
}

// Example for InstructionType::AluUnary.
#[test]
fn test_neg64() {
    disasm!("neg64 r1");
}

// Example for InstructionType::LoadReg.
#[test]
fn test_ldxw() {
    disasm!("ldxw r1, [r2+0x5]");
}

// Example for InstructionType::StoreImm.
#[test]
fn test_stw() {
    disasm!("stw [r2+0x5], 0x7");
}

// Example for InstructionType::StoreReg.
#[test]
fn test_stxw() {
    disasm!("stxw [r2+0x5], r8");
}

// Example for InstructionType::JumpUnconditional.
#[test]
fn test_ja() {
    disasm!("ja +0x8");
}

// Example for InstructionType::JumpConditional.
#[test]
fn test_jeq() {
    disasm!("jeq r1, 0x4, +0x8");
    disasm!("jeq r1, r3, +0x8");
}

// Example for InstructionType::Call.
#[test]
fn test_call() {
    disasm!("call 0x3");
}

// Example for InstructionType::Endian.
#[test]
fn test_be32() {
    disasm!("be32 r1");
}

// Example for InstructionType::LoadImm.
#[test]
fn test_lddw() {
    disasm!("lddw r1, 0x1234abcd5678eeff");
    disasm!("lddw r1, 0xff11ee22dd33cc44");
}

// Example for InstructionType::LoadAbs.
#[test]
fn test_ldabsw() {
    disasm!("ldabsw 0x1");
}

// Example for InstructionType::LoadInd.
#[test]
fn test_ldindw() {
    disasm!("ldindw r1, 0x2");
}

// Example for InstructionType::LoadReg.
#[test]
fn test_ldxdw() {
    disasm!("ldxdw r1, [r2+0x3]");
}

// Example for InstructionType::StoreImm.
#[test]
fn test_sth() {
    disasm!("sth [r1+0x2], 0x3");
}

// Example for InstructionType::StoreReg.
#[test]
fn test_stxh() {
    disasm!("stxh [r1+0x2], r3");
}

// Test all supported AluBinary mnemonics.
#[test]
fn test_alu_binary() {
    disasm!("add64 r1, r2
sub64 r1, r2
mul64 r1, r2
div64 r1, r2
or64 r1, r2
and64 r1, r2
lsh64 r1, r2
rsh64 r1, r2
mod64 r1, r2
xor64 r1, r2
mov64 r1, r2
arsh64 r1, r2");

    disasm!("add64 r1, 0x2
sub64 r1, 0x2
mul64 r1, 0x2
div64 r1, 0x2
or64 r1, 0x2
and64 r1, 0x2
lsh64 r1, 0x2
rsh64 r1, 0x2
mod64 r1, 0x2
xor64 r1, 0x2
mov64 r1, 0x2
arsh64 r1, 0x2");

    disasm!("add32 r1, r2
sub32 r1, r2
mul32 r1, r2
div32 r1, r2
or32 r1, r2
and32 r1, r2
lsh32 r1, r2
rsh32 r1, r2
mod32 r1, r2
xor32 r1, r2
mov32 r1, r2
arsh32 r1, r2");

    disasm!("add32 r1, 0x2
sub32 r1, 0x2
mul32 r1, 0x2
div32 r1, 0x2
or32 r1, 0x2
and32 r1, 0x2
lsh32 r1, 0x2
rsh32 r1, 0x2
mod32 r1, 0x2
xor32 r1, 0x2
mov32 r1, 0x2
arsh32 r1, 0x2");
}

// Test all supported AluUnary mnemonics.
#[test]
fn test_alu_unary() {
    disasm!("neg64 r1
neg32 r1");
}

// Test all supported LoadAbs mnemonics.
#[test]
fn test_load_abs() {
    disasm!("ldabsw 0x1
ldabsh 0x1
ldabsb 0x1
ldabsdw 0x1");
}

// Test all supported LoadInd mnemonics.
#[test]
fn test_load_ind() {
    disasm!("ldindw r1, 0x2
ldindh r1, 0x2
ldindb r1, 0x2
ldinddw r1, 0x2");
}

// Test all supported LoadReg mnemonics.
#[test]
fn test_load_reg() {
    disasm!(r"ldxw r1, [r2+0x3]
ldxh r1, [r2+0x3]
ldxb r1, [r2+0x3]
ldxdw r1, [r2+0x3]");
}

// Test all supported StoreImm mnemonics.
#[test]
fn test_store_imm() {
    disasm!("stw [r1+0x2], 0x3
sth [r1+0x2], 0x3
stb [r1+0x2], 0x3
stdw [r1+0x2], 0x3");
}

// Test all supported StoreReg mnemonics.
#[test]
fn test_store_reg() {
    disasm!("stxw [r1+0x2], r3
stxh [r1+0x2], r3
stxb [r1+0x2], r3
stxdw [r1+0x2], r3");
}

// Test all supported JumpConditional mnemonics.
#[test]
fn test_jump_conditional() {
    disasm!("jeq r1, r2, +0x3
jgt r1, r2, +0x3
jge r1, r2, +0x3
jlt r1, r2, +0x3
jle r1, r2, +0x3
jset r1, r2, +0x3
jne r1, r2, +0x3
jsgt r1, r2, +0x3
jsge r1, r2, -0x3
jslt r1, r2, +0x3
jsle r1, r2, -0x3");

    disasm!("jeq r1, 0x2, +0x3
jgt r1, 0x2, +0x3
jge r1, 0x2, +0x3
jlt r1, 0x2, +0x3
jle r1, 0x2, +0x3
jset r1, 0x2, +0x3
jne r1, 0x2, +0x3
jsgt r1, 0x2, +0x3
jsge r1, 0x2, -0x3
jslt r1, 0x2, +0x3
jsle r1, 0x2, -0x3");
}

// Test all supported Endian mnemonics.
#[test]
fn test_endian() {
    disasm!("be16 r1
be32 r1
be64 r1
le16 r1
le32 r1
le64 r1");
}

#[test]
fn test_large_immediate() {
    disasm!("add64 r1, 0x7fffffff");
    disasm!("add64 r1, 0x7fffffff");
}
<|endoftext|>


<commit_before>//! Utilities for tracking time.
//!
//! This module provides a number of types for executing code after a set period
//! of time.
//!
//! * `Sleep` is a future that does no work and completes at a specific `Instant`
//!   in time.
//!
//! * `Interval` is a stream yielding a value at a fixed period. It is
//!   initialized with a `Duration` and repeatedly yields each time the duration
//!   elapses.
//!
//! * `Timeout`: Wraps a future or stream, setting an upper bound to the amount
//!   of time it is allowed to execute. If the future or stream does not
//!   complete in time, then it is canceled and an error is returned.
//!
//! These types are sufficient for handling a large number of scenarios
//! involving time.
//!
//! These types must be used from within the context of the `Runtime`.
//!
//! # Examples
//!
//! Wait 100ms and print "100 ms have elapsed"
//!
//! ```
//! use std::time::Duration;
//! use tokio::time::sleep;
//!
//! #[tokio::main]
//! async fn main() {
//!     sleep(Duration::from_millis(100)).await;
//!     println!("100 ms have elapsed");
//! }
//! ```
//!
//! Require that an operation takes no more than 300ms.
//!
//! ```
//! use tokio::time::{timeout, Duration};
//!
//! async fn long_future() {
//!     // do work here
//! }
//!
//! # async fn dox() {
//! let res = timeout(Duration::from_secs(1), long_future()).await;
//!
//! if res.is_err() {
//!     println!("operation timed out");
//! }
//! # }
//! ```
//!
//! A simple example using [`interval`] to execute a task every two seconds.
//!
//! The difference between [`interval`] and [`sleep`] is that an [`interval`]
//! measures the time since the last tick, which means that `.tick().await`
//! may wait for a shorter time than the duration specified for the interval
//! if some time has passed between calls to `.tick().await`.
//!
//! If the tick in the example below was replaced with [`sleep`], the task
//! would only be executed once every three seconds, and not every two
//! seconds.
//!
//! ```
//! use tokio::time;
//!
//! async fn task_that_takes_a_second() {
//!     println!("hello");
//!     time::sleep(time::Duration::from_secs(1)).await
//! }
//!
//! #[tokio::main]
//! async fn main() {
//!     let mut interval = time::interval(time::Duration::from_secs(2));
//!     for _i in 0..5 {
//!         interval.tick().await;
//!         task_that_takes_a_second().await;
//!     }
//! }
//! ```
//!
//! [`sleep`]: crate::time::sleep()
//! [`interval`]: crate::time::interval()

mod clock;
pub(crate) use self::clock::Clock;
#[cfg(feature = "test-util")]
pub use clock::{advance, pause, resume};

pub(crate) mod driver;

#[doc(inline)]
pub use driver::sleep::{sleep, sleep_until, Sleep};

pub mod error;

mod instant;
pub use self::instant::Instant;

mod interval;
pub use interval::{interval, interval_at, Interval};

mod timeout;
#[doc(inline)]
pub use timeout::{timeout, timeout_at, Timeout};

#[cfg(test)]
#[cfg(not(loom))]
mod tests;

// Re-export for convenience
#[doc(no_inline)]
pub use std::time::Duration;
<commit_msg>time: change 300ms to 1s in documentation (#3685)<commit_after>//! Utilities for tracking time.
//!
//! This module provides a number of types for executing code after a set period
//! of time.
//!
//! * `Sleep` is a future that does no work and completes at a specific `Instant`
//!   in time.
//!
//! * `Interval` is a stream yielding a value at a fixed period. It is
//!   initialized with a `Duration` and repeatedly yields each time the duration
//!   elapses.
//!
//! * `Timeout`: Wraps a future or stream, setting an upper bound to the amount
//!   of time it is allowed to execute. If the future or stream does not
//!   complete in time, then it is canceled and an error is returned.
//!
//! These types are sufficient for handling a large number of scenarios
//! involving time.
//!
//! These types must be used from within the context of the `Runtime`.
//!
//! # Examples
//!
//! Wait 100ms and print "100 ms have elapsed"
//!
//! ```
//! use std::time::Duration;
//! use tokio::time::sleep;
//!
//! #[tokio::main]
//! async fn main() {
//!     sleep(Duration::from_millis(100)).await;
//!     println!("100 ms have elapsed");
//! }
//! ```
//!
//! Require that an operation takes no more than 1s.
//!
//! ```
//! use tokio::time::{timeout, Duration};
//!
//! async fn long_future() {
//!     // do work here
//! }
//!
//! # async fn dox() {
//! let res = timeout(Duration::from_secs(1), long_future()).await;
//!
//! if res.is_err() {
//!     println!("operation timed out");
//! }
//! # }
//! ```
//!
//! A simple example using [`interval`] to execute a task every two seconds.
//!
//! The difference between [`interval`] and [`sleep`] is that an [`interval`]
//! measures the time since the last tick, which means that `.tick().await`
//! may wait for a shorter time than the duration specified for the interval
//! if some time has passed between calls to `.tick().await`.
//!
//! If the tick in the example below was replaced with [`sleep`], the task
//! would only be executed once every three seconds, and not every two
//! seconds.
//!
//! ```
//! use tokio::time;
//!
//! async fn task_that_takes_a_second() {
//!     println!("hello");
//!     time::sleep(time::Duration::from_secs(1)).await
//! }
//!
//! #[tokio::main]
//! async fn main() {
//!     let mut interval = time::interval(time::Duration::from_secs(2));
//!     for _i in 0..5 {
//!         interval.tick().await;
//!         task_that_takes_a_second().await;
//!     }
//! }
//! ```
//!
//! [`sleep`]: crate::time::sleep()
//! [`interval`]: crate::time::interval()

mod clock;
pub(crate) use self::clock::Clock;
#[cfg(feature = "test-util")]
pub use clock::{advance, pause, resume};

pub(crate) mod driver;

#[doc(inline)]
pub use driver::sleep::{sleep, sleep_until, Sleep};

pub mod error;

mod instant;
pub use self::instant::Instant;

mod interval;
pub use interval::{interval, interval_at, Interval};

mod timeout;
#[doc(inline)]
pub use timeout::{timeout, timeout_at, Timeout};

#[cfg(test)]
#[cfg(not(loom))]
mod tests;

// Re-export for convenience
#[doc(no_inline)]
pub use std::time::Duration;
<|endoftext|>


<commit_before>extern crate hyper;
extern crate serde;
extern crate serde_json as json;
extern crate syncdb_changes_stream;

use syncdb_changes_stream::changes_stream::ChangesStream;

use hyper::Client;
use hyper::header::Connection;

fn main() {
    // Create a client.
    let client = Client::new();

    // Creating an outgoing request.
    let res = client.get("http://localhost:5984/test/_changes?feed=continuous&include_docs=true")
        // set a header
        .header(Connection::close())
        // let 'er go!
        .send().unwrap();

    let stream: ChangesStream<_,json::Value> = ChangesStream::new(res);

    for change in stream.changes() {
        println!("{:?}", change);
    }
}

<commit_msg>Remove last trace of syncdb<commit_after>extern crate hyper;
extern crate serde;
extern crate serde_json as json;
extern crate lazers_changes_stream;

use lazers_changes_stream::changes_stream::ChangesStream;

use hyper::Client;
use hyper::header::Connection;

fn main() {
    // Create a client.
    let client = Client::new();

    // Creating an outgoing request.
    let res = client.get("http://localhost:5984/test/_changes?feed=continuous&include_docs=true")
        // set a header
        .header(Connection::close())
        // let 'er go!
        .send().unwrap();

    let stream: ChangesStream<_,json::Value> = ChangesStream::new(res);

    for change in stream.changes() {
        println!("{:?}", change);
    }
}

<|endoftext|>


<commit_before>//! Position data structure for terrain blocks.

use cgmath::{Point3, Vector3};
use std::ops::Add;

pub const BLOCK_WIDTH: i32 = 8;

#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
/// Position of blocks on an "infinite" regular grid.
/// The position is implicitly in units of BLOCK_WIDTH.
pub struct BlockPosition(Point3<i32>);

impl BlockPosition {
  #[inline(always)]
  #[allow(missing_docs)]
  pub fn new(x: i32, y: i32, z: i32) -> BlockPosition {
    BlockPosition(Point3::new(x, y, z))
  }

  #[inline(always)]
  #[allow(missing_docs)]
  pub fn as_pnt<'a>(&'a self) -> &'a Point3<i32> {
    let BlockPosition(ref pnt) = *self;
    pnt
  }

  #[inline(always)]
  #[allow(missing_docs)]
  pub fn as_mut_pnt3<'a>(&'a mut self) -> &'a mut Point3<i32> {
    let BlockPosition(ref mut pnt) = *self;
    pnt
  }

  #[allow(missing_docs)]
  pub fn from_world_position(world_position: &Point3<f32>) -> BlockPosition {
    macro_rules! convert_coordinate(
      ($x: expr) => ({
        let x = $x.floor() as i32;
        let x =
          if x < 0 {
            x - (BLOCK_WIDTH - 1)
          } else {
            x
          };
        x / BLOCK_WIDTH
      })
    );
    BlockPosition(
      Point3::new(
        convert_coordinate!(world_position.x),
        convert_coordinate!(world_position.y),
        convert_coordinate!(world_position.z),
      )
    )
  }

  #[allow(missing_docs)]
  pub fn to_world_position(&self) -> Point3<f32> {
    Point3::new(
      (self.as_pnt().x * BLOCK_WIDTH) as f32,
      (self.as_pnt().y * BLOCK_WIDTH) as f32,
      (self.as_pnt().z * BLOCK_WIDTH) as f32,
    )
  }
}

impl Add<Vector3<i32>> for BlockPosition {
  type Output = BlockPosition;

  fn add(mut self, rhs: Vector3<i32>) -> Self {
    self.as_mut_pnt3().x += rhs.x;
    self.as_mut_pnt3().y += rhs.y;
    self.as_mut_pnt3().z += rhs.z;
    self
  }
}
<commit_msg>Remove redundant constant<commit_after>//! Position data structure for terrain blocks.

use cgmath::{Point3, Vector3};
use std::ops::Add;

use terrain_block;

#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
/// Position of blocks on an "infinite" regular grid.
/// The position is implicitly in units of terrain_block::WIDTH.
pub struct BlockPosition(Point3<i32>);

impl BlockPosition {
  #[inline(always)]
  #[allow(missing_docs)]
  pub fn new(x: i32, y: i32, z: i32) -> BlockPosition {
    BlockPosition(Point3::new(x, y, z))
  }

  #[inline(always)]
  #[allow(missing_docs)]
  pub fn as_pnt<'a>(&'a self) -> &'a Point3<i32> {
    let BlockPosition(ref pnt) = *self;
    pnt
  }

  #[inline(always)]
  #[allow(missing_docs)]
  pub fn as_mut_pnt3<'a>(&'a mut self) -> &'a mut Point3<i32> {
    let BlockPosition(ref mut pnt) = *self;
    pnt
  }

  #[allow(missing_docs)]
  pub fn from_world_position(world_position: &Point3<f32>) -> BlockPosition {
    macro_rules! convert_coordinate(
      ($x: expr) => ({
        let x = $x.floor() as i32;
        let x =
          if x < 0 {
            x - (terrain_block::WIDTH - 1)
          } else {
            x
          };
        x / terrain_block::WIDTH
      })
    );
    BlockPosition(
      Point3::new(
        convert_coordinate!(world_position.x),
        convert_coordinate!(world_position.y),
        convert_coordinate!(world_position.z),
      )
    )
  }

  #[allow(missing_docs)]
  pub fn to_world_position(&self) -> Point3<f32> {
    Point3::new(
      (self.as_pnt().x * terrain_block::WIDTH) as f32,
      (self.as_pnt().y * terrain_block::WIDTH) as f32,
      (self.as_pnt().z * terrain_block::WIDTH) as f32,
    )
  }
}

impl Add<Vector3<i32>> for BlockPosition {
  type Output = BlockPosition;

  fn add(mut self, rhs: Vector3<i32>) -> Self {
    self.as_mut_pnt3().x += rhs.x;
    self.as_mut_pnt3().y += rhs.y;
    self.as_mut_pnt3().z += rhs.z;
    self
  }
}
<|endoftext|>