<commit_before>use std::error::Error;
use std::fmt;
use std::fmt::{ Display, Formatter };
use std::io;
use std::io::{ BufRead, BufReader, ErrorKind, Read };
use std::result::Result;

/// Wrapper for a Reader, providing convenience methods to read the stream bit-by-bit.
///
/// # Examples
///
/// extern crate compression;
///
/// use compression::bitreader::BitReader;
/// use std::fs::File;
///
/// let f = try!(File::open("filename"));
/// let mut br = BitReader::new(f);
/// let byte: u8 = br.read_u8().unwrap();
#[derive(Debug)]
pub struct BitReader<R: Read> {
	inner: BufReader<R>,
	bit_pos: u8,
	current_byte: Option<u8>,
}

impl<R: Read> BitReader<R> {
	pub fn new(inner: R) -> BitReader<R> {
		BitReader{
			inner: BufReader::new(inner),
			bit_pos: 0,
			current_byte: None,
		}
	}

	fn read_exact(&mut self, mut buf: &mut [u8]) -> io::Result<()> {
		while !buf.is_empty() {
			match self.inner.read(buf) {
				Ok(0) => break,
				Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
				Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
				Err(e) => return Err(e),
			}
		}
		if !buf.is_empty() {
			Err(io::Error::new(ErrorKind::Other, "failed to fill whole buffer"))
		} else {
			Ok(())
		}
	}

	pub fn read_u8(&mut self) -> Result<u8, BitReaderError> {
		let mut buf = &mut [0u8];

		match (self.current_byte, self.read_exact(buf)) {
			(Some(byte), Ok(())) => {
				self.current_byte = Some(buf[0]);
				Ok((byte >> self.bit_pos) | (buf[0] << (8 - self.bit_pos)))
			},
			(None, Ok(())) => Ok(buf[0]),
			(_, Err(_)) => Err(BitReaderError::Unspecified),
		}
	}

	pub fn read_u16(&mut self) -> Result<u16, BitReaderError> {
		let mut buf = &mut [0u8; 2];

		match (self.current_byte, self.read_exact(buf)) {
			(Some(byte), Ok(())) => {
				self.current_byte = Some(buf[1]);
				Ok(((byte as u16) >> self.bit_pos) | ((buf[0] as u16) << (8 - self.bit_pos)) | ((buf[1] as u16) << (16 - self.bit_pos)))
			},
			(None, Ok(())) => Ok(((buf[1] as u16) << 8) | (buf[0] as u16)),
			(_, Err(_)) => Err(BitReaderError::Unspecified),
		}
	}

	pub fn read_bit(&mut self) -> Result<bool, BitReaderError> {
		match (self.current_byte, self.bit_pos) {
			(Some(byte), bit_pos) => {
				self.bit_pos = (self.bit_pos + 1) % 8;
				if self.bit_pos == 0 {
					self.current_byte = None;
				}
				Ok(byte >> bit_pos & 1 == 1)
			},
			(None, _) => {
				let mut buf = &mut [0u8; 1];
				match self.read_exact(buf) {
					Ok(()) => {
						self.current_byte = Some(buf[0]);
						self.bit_pos = 1;
						Ok(buf[0] & 1 == 1)
					},
					Err(_) => Err(BitReaderError::Unspecified),
				}
			}
		}

	}
}

#[derive(Debug, Clone, PartialEq)]
pub enum BitReaderError {
	Unspecified
}

impl Display for BitReaderError {
	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
		fmt.write_str(self.description())
	}
}

impl Error for BitReaderError {
	fn description(&self) -> &str {
		match self {
			_ => "Generic error",
		}
	}
}

mod tests {
	use super::*;

	#[test]
	fn should_read_one_u8() {
		use std::io::{ BufRead, BufReader, Cursor };

		let expected = 0x1f;
		let mut br = BitReader::new(Cursor::new(vec![expected, 0x8b]));

		match br.read_u8() {
			Ok(byte) => assert_eq!(expected, byte),
			Err(_) => panic!("Should have read one byte"),
		}
	}

	#[test]
	fn should_read_two_u8() {
		use std::io::{ Cursor };

		let (expected0, expected1) = (0x1f, 0x8b);
		let mut br = BitReader::new(Cursor::new(vec![expected0, expected1]));

		match (br.read_u8(), br.read_u8()) {
			(Ok(my_u8_0), Ok(my_u8_1)) => assert_eq!((expected0, expected1), (my_u8_0, my_u8_1)),
			_ => panic!("Should have read two bytes"),
		}
	}

	#[test]
	fn should_read_one_u16() {
		use std::io::{ Cursor };

		let expected = 0x8b1f;
		let mut br = BitReader::new(Cursor::new(vec![(expected & 0x00FF) as u8, (expected >> 8) as u8]));

		match br.read_u16() {
			Ok(my_u16) => assert_eq!(expected, my_u16),
			_ => panic!("Should have read one u16"),
		}
	}

	#[test]
	fn should_read_one_set_bit() {
		use std::io::{ Cursor };

		let mut br = BitReader::new(Cursor::new(vec![3]));

		match br.read_bit() {
			Ok(my_bit) => assert!(my_bit),
			_ => panic!("Should have read one set bit"),
		}
	}

	#[test]
	fn should_read_two_bits() {
		use std::io::{ Cursor };

		let mut br = BitReader::new(Cursor::new(vec![2]));

		match (br.read_bit(), br.read_bit()) {
			(Ok(my_bit_0), Ok(my_bit_1)) => {
				assert!(!my_bit_0);
				assert!(my_bit_1);
			},
			_ => panic!("Should have read one unset bit and one set bit"),
		}
	}

	#[test]
	fn should_read_u8_after_bit() {
		use std::io::{ Cursor };

		let mut br = BitReader::new(Cursor::new(vec![0b10001101, 0b00010101]));

		match (br.read_bit(), br.read_u8()) {
			(Ok(my_bit), Ok(my_u8)) => {
				assert!(my_bit);
				assert_eq!(0b11000110, my_u8);
			},
			_ => panic!("Should have read one set bit and one u8"),
		}
	}

	#[test]
	fn should_read_u16_after_bit() {
		use std::io::{ Cursor };

		let mut br = BitReader::new(Cursor::new(vec![0b10001101, 0b00010101, 0b00010101]));

		match (br.read_bit(), br.read_u16()) {
			(Ok(my_bit), Ok(my_u16)) => {
				assert!(my_bit);
				assert_eq!(0b1000101011000110, my_u16);
			},
			_ => panic!("Should have read one set bit and one u16"),
		}
	}}
<commit_msg>MOD: addressed some warnings, made sure bit test case addresses across-boundary case<commit_after>use std::error::Error;
use std::fmt;
use std::fmt::{ Display, Formatter };
use std::io;
use std::io::{ BufReader, ErrorKind, Read };
use std::result::Result;

/// Wrapper for a Reader, providing convenience methods to read the stream bit-by-bit.
///
/// # Examples
///
/// extern crate compression;
///
/// use compression::bitreader::BitReader;
/// use std::fs::File;
///
/// let f = try!(File::open("filename"));
/// let mut br = BitReader::new(f);
/// let byte: u8 = br.read_u8().unwrap();
#[derive(Debug)]
pub struct BitReader<R: Read> {
	inner: BufReader<R>,
	bit_pos: u8,
	current_byte: Option<u8>,
}

impl<R: Read> BitReader<R> {
	pub fn new(inner: R) -> BitReader<R> {
		BitReader{
			inner: BufReader::new(inner),
			bit_pos: 0,
			current_byte: None,
		}
	}

	fn read_exact(&mut self, mut buf: &mut [u8]) -> io::Result<()> {
		while !buf.is_empty() {
			match self.inner.read(buf) {
				Ok(0) => break,
				Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
				Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
				Err(e) => return Err(e),
			}
		}
		if !buf.is_empty() {
			Err(io::Error::new(ErrorKind::Other, "failed to fill whole buffer"))
		} else {
			Ok(())
		}
	}

	pub fn read_u8(&mut self) -> Result<u8, BitReaderError> {
		let mut buf = &mut [0u8];

		match (self.current_byte, self.read_exact(buf)) {
			(Some(byte), Ok(())) => {
				self.current_byte = Some(buf[0]);
				Ok((byte >> self.bit_pos) | (buf[0] << (8 - self.bit_pos)))
			},
			(None, Ok(())) => Ok(buf[0]),
			(_, Err(_)) => Err(BitReaderError::Unspecified),
		}
	}

	pub fn read_u16(&mut self) -> Result<u16, BitReaderError> {
		let mut buf = &mut [0u8; 2];

		match (self.current_byte, self.read_exact(buf)) {
			(Some(byte), Ok(())) => {
				self.current_byte = Some(buf[1]);
				Ok(((byte as u16) >> self.bit_pos) | ((buf[0] as u16) << (8 - self.bit_pos)) | ((buf[1] as u16) << (16 - self.bit_pos)))
			},
			(None, Ok(())) => Ok(((buf[1] as u16) << 8) | (buf[0] as u16)),
			(_, Err(_)) => Err(BitReaderError::Unspecified),
		}
	}

	pub fn read_bit(&mut self) -> Result<bool, BitReaderError> {
		match (self.current_byte, self.bit_pos) {
			(Some(byte), bit_pos) => {
				self.bit_pos = (self.bit_pos + 1) % 8;
				if self.bit_pos == 0 {
					self.current_byte = None;
				}
				Ok(byte >> bit_pos & 1 == 1)
			},
			(None, _) => {
				let mut buf = &mut [0u8; 1];
				match self.read_exact(buf) {
					Ok(()) => {
						self.current_byte = Some(buf[0]);
						self.bit_pos = 1;
						Ok(buf[0] & 1 == 1)
					},
					Err(_) => Err(BitReaderError::Unspecified),
				}
			}
		}

	}
}

#[derive(Debug, Clone, PartialEq)]
pub enum BitReaderError {
	Unspecified
}

impl Display for BitReaderError {
	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
		fmt.write_str(self.description())
	}
}

impl Error for BitReaderError {
	fn description(&self) -> &str {
		match self {
			_ => "Generic error",
		}
	}
}

mod tests {
	#[test]
	fn should_read_one_u8() {
		use super::*;
		use std::io::{ Cursor };

		let expected = 0x1f;
		let mut br = BitReader::new(Cursor::new(vec![expected, 0x8b]));

		match br.read_u8() {
			Ok(byte) => assert_eq!(expected, byte),
			Err(_) => panic!("Should have read one byte"),
		}
	}

	#[test]
	fn should_read_two_u8() {
		use super::*;
		use std::io::{ Cursor };

		let (expected0, expected1) = (0x1f, 0x8b);
		let mut br = BitReader::new(Cursor::new(vec![expected0, expected1]));

		match (br.read_u8(), br.read_u8()) {
			(Ok(my_u8_0), Ok(my_u8_1)) => assert_eq!((expected0, expected1), (my_u8_0, my_u8_1)),
			_ => panic!("Should have read two bytes"),
		}
	}

	#[test]
	fn should_read_one_u16() {
		use super::*;
		use std::io::{ Cursor };

		let expected = 0x8b1f;
		let mut br = BitReader::new(Cursor::new(vec![(expected & 0x00FF) as u8, (expected >> 8) as u8]));

		match br.read_u16() {
			Ok(my_u16) => assert_eq!(expected, my_u16),
			_ => panic!("Should have read one u16"),
		}
	}

	#[test]
	fn should_read_one_set_bit() {
		use super::*;
		use std::io::{ Cursor };

		let mut br = BitReader::new(Cursor::new(vec![3]));

		match br.read_bit() {
			Ok(my_bit) => assert!(my_bit),
			_ => panic!("Should have read one set bit"),
		}
	}

	#[test]
	fn should_read_some_bits() {
		use super::*;
		use std::io::{ Cursor };

		let mut br = BitReader::new(Cursor::new(vec![134, 1]));

		match (br.read_bit(), br.read_bit(), br.read_bit(), br.read_bit(), br.read_bit(),
		       br.read_bit(), br.read_bit(), br.read_bit(), br.read_bit(), br.read_bit()) {
			(Ok(my_bit_0), Ok(my_bit_1), Ok(my_bit_2), Ok(my_bit_3), Ok(my_bit_4),
			 Ok(my_bit_5), Ok(my_bit_6), Ok(my_bit_7), Ok(my_bit_8), Ok(my_bit_9)) => {
				assert!(!my_bit_0);
				assert!(my_bit_1);
				assert!(my_bit_2);
				assert!(!my_bit_3);
				assert!(!my_bit_4);
				assert!(!my_bit_5);
				assert!(!my_bit_6);
				assert!(my_bit_7);
				assert!(my_bit_8);
				assert!(!my_bit_9);
			},
			_ => panic!("Should have read 10 bits"),
		}
	}

	#[test]
	fn should_read_u8_after_bit() {
		use super::*;
		use std::io::{ Cursor };

		let mut br = BitReader::new(Cursor::new(vec![0b10001101, 0b00010101]));

		match (br.read_bit(), br.read_u8()) {
			(Ok(my_bit), Ok(my_u8)) => {
				assert!(my_bit);
				assert_eq!(0b11000110, my_u8);
			},
			_ => panic!("Should have read one set bit and one u8"),
		}
	}

	#[test]
	fn should_read_u16_after_bit() {
		use super::*;
		use std::io::{ Cursor };

		let mut br = BitReader::new(Cursor::new(vec![0b10001101, 0b00010101, 0b00010101]));

		match (br.read_bit(), br.read_u16()) {
			(Ok(my_bit), Ok(my_u16)) => {
				assert!(my_bit);
				assert_eq!(0b1000101011000110, my_u16);
			},
			_ => panic!("Should have read one set bit and one u16"),
		}
	}}
<|endoftext|>


<commit_before>//! A Single-Producer, Multiple-Consumer queue.

use std::sync::mpsc::{channel, Receiver, RecvError, Sender, SendError};
use std::sync::{Arc, RwLock, RwLockReadGuard};
use std::fmt;
use std::any::Any;
use std::error::Error;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
/// Error from broadcast module.
pub enum BroadcastError<T> {
    /// Send error
    SendError(T),
    /// Receive error
    RecvError,
}

impl<T: fmt::Display> fmt::Display for BroadcastError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            BroadcastError::SendError(ref t) =>
                write!(fmt, "could not send data on channel: {}", t),
            BroadcastError::RecvError =>
                write!(fmt, "could not receive data on channel"),
        }
    }
}

impl<T: Send + fmt::Display + fmt::Debug + Any> Error for BroadcastError<T> {
    fn description(&self) -> &str {
        match *self {
            BroadcastError::SendError(_) => "could not send data on channel",
            BroadcastError::RecvError => "could not receive data on channel",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<T> From<SendError<T>> for BroadcastError<T> {
    fn from(err: SendError<T>) -> BroadcastError<T> {
        let SendError(data) = err;
        BroadcastError::SendError(data)
    }
}

impl<T> From<RecvError> for BroadcastError<T> {
    fn from(_err: RecvError) -> BroadcastError<T> {
        BroadcastError::RecvError
    }
}

/// Struct that sends message on a broadcast pattern.
pub struct Broadcast<T> {
    inner: Arc<Inner<T>>,
}

impl<T> Broadcast<T> {
    /// Create a new Broadcast struct.
    pub fn new() -> Broadcast<T> {
        let inner = Arc::new(Inner { senders: RwLock::new(Vec::new()) });
        Broadcast { inner: inner }
    }

    /// Create a Consumer that listens to messages from the Broadcaster.
    pub fn consume(&self) -> Consumer<T> {
        let (b, c) = channel();
        self.inner.add_sender(b);
        Consumer { inner: self.inner.clone(), receiver: c }
    }
}

impl<T: Clone> Broadcast<T> {
    /// Send a message on the broadcast.
    pub fn send(&self, data: T) -> Result<(), BroadcastError<T>> {
        let guard = self.inner.read_senders();
        for s in guard.iter() {
            try!(s.send(data.clone()));
        }

        Ok(())
    }
}

// We implement Send/Sync here since we guarantee that the Sender<T>s in the
// vec only have `send()` called by the Broadcast struct. We need sync in order
// to share the vector with the Consumer to add senders too.
//
// TODO: Is there a way to not need to implement these traits?
//
// The same trait bounds on T are used here as in RwLock.
unsafe impl<T: Sync + Send + Sized> Sync for Inner<T> {}
unsafe impl<T: Sync + Send + Sized> Send for Inner<T> {}
struct Inner<T> {
    senders: RwLock<Vec<Sender<T>>>,
}

impl<T> Inner<T> {
    // This should only be called by Broadcast. Something may or may not go
    // horriblely wrong if send() is called from multiple threads.
    //
    // TODO: Disallow Consumer from calling this.
    fn read_senders<'a>(&'a self) -> RwLockReadGuard<'a, Vec<Sender<T>>> {
        self.senders.read().unwrap()
    }

    fn add_sender(&self, sender: Sender<T>) {
        let mut vec = self.senders.write().unwrap();
        vec.push(sender);
    }
}

/// Struct that receives messages from Broadcast.
pub struct Consumer<T> {
    inner: Arc<Inner<T>>,
    receiver: Receiver<T>,
}

impl<T> Consumer<T> {
    /// Receive a message from the Broadcast.
    ///
    /// This function will block.
    pub fn recv(&self) -> Result<T, BroadcastError<T>> {
        let data = try!(self.receiver.recv());
        Ok(data)
    }
}

impl<T> Clone for Consumer<T> {
    fn clone(&self) -> Self {
        let (s, r) = channel();
        self.inner.add_sender(s);
        Consumer {
            inner: self.inner.clone(),
            receiver: r,
        }
    }
}

/// Create a (Broadcast<T>, Consumer<T>) pair.
pub fn broadcast_channel<T: Clone>() -> (Broadcast<T>, Consumer<T>) {
    let broadcast = Broadcast::new();
    let consumer = broadcast.consume();
    (broadcast, consumer)
}

#[cfg(test)]
mod test {
    use broadcast::broadcast_channel;
    use super::Inner;

    use std::sync::{Arc, RwLock};
    use std::sync::mpsc::{channel};
    use std::thread::spawn;

    #[test]
    fn inner_iterator() {
        let (s1, r1) = channel();
        let (s2, r2) = channel();
        let inner = Arc::new(Inner { senders: RwLock::new(vec!(s1, s2)) });
        let guard = inner.read_senders();
        for s in guard.iter() {
            assert!(s.send(10u8).is_ok());
        }

        assert_eq!(r1.recv().unwrap(), 10u8);
        assert_eq!(r2.recv().unwrap(), 10u8);
    }

    #[test]
    fn sends_to_multiple_consumers() {
        let (p, c) = broadcast_channel();
        let c2 = c.clone();

        let res = p.send(9u8);
        assert!(res.is_ok());

        let res = c.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8);

        let res = c2.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8)
    }

    #[test]
    fn test_send_threads() {
        let (p, c1) = broadcast_channel();
        let c2 = c1.clone();

        let (s1, r1) = channel();
        let (s2, r2) = channel();

        let _thread = spawn(move || {
            assert_eq!(c1.recv().unwrap(), 9u8);
            s1.send(10u8).unwrap();
        });

        let _thread = spawn(move || {
            assert_eq!(c2.recv().unwrap(), 9u8);
            s2.send(10u8).unwrap();
        });

        assert!(p.send(9u8).is_ok());
        assert!(r1.recv().is_ok());
        assert!(r2.recv().is_ok());
    }
}
<commit_msg>Use Mutex instead of RwLock<commit_after>//! A Single-Producer, Multiple-Consumer queue.

use std::sync::mpsc::{channel, Receiver, RecvError, Sender, SendError};
use std::sync::{Arc, Mutex, MutexGuard};
use std::marker::PhantomData;
use std::fmt;
use std::any::Any;
use std::error::Error;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
/// Error from broadcast module.
pub enum BroadcastError<T> {
    /// Send error
    SendError(T),
    /// Receive error
    RecvError,
}

impl<T: fmt::Display> fmt::Display for BroadcastError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            BroadcastError::SendError(ref t) =>
                write!(fmt, "could not send data on channel: {}", t),
            BroadcastError::RecvError =>
                write!(fmt, "could not receive data on channel"),
        }
    }
}

impl<T: Send + fmt::Display + fmt::Debug + Any> Error for BroadcastError<T> {
    fn description(&self) -> &str {
        match *self {
            BroadcastError::SendError(_) => "could not send data on channel",
            BroadcastError::RecvError => "could not receive data on channel",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<T> From<SendError<T>> for BroadcastError<T> {
    fn from(err: SendError<T>) -> BroadcastError<T> {
        let SendError(data) = err;
        BroadcastError::SendError(data)
    }
}

impl<T> From<RecvError> for BroadcastError<T> {
    fn from(_err: RecvError) -> BroadcastError<T> {
        BroadcastError::RecvError
    }
}

/// Struct that sends message on a broadcast pattern.
pub struct Broadcast<T> {
    inner: Arc<Inner<T>>,
}

impl<T> Broadcast<T> {
    /// Create a new Broadcast struct.
    pub fn new() -> Broadcast<T> {
        let inner = Arc::new(Inner { senders: Mutex::new(Vec::new()) });
        Broadcast { inner: inner, not_sync: PhantomData }
    }

    /// Create a Consumer that listens to messages from the Broadcaster.
    pub fn consume(&self) -> Consumer<T> {
        let (b, c) = channel();
        self.inner.add_sender(b);
        Consumer { inner: self.inner.clone(), receiver: c }
    }
}

impl<T: Clone> Broadcast<T> {
    /// Send a message on the broadcast.
    pub fn send(&self, data: T) -> Result<(), BroadcastError<T>> {
        let guard = self.inner.read_senders();
        for s in guard.iter() {
            try!(s.send(data.clone()));
        }

        Ok(())
    }
}

struct Inner<T> {
    senders: Mutex<Vec<Sender<T>>>,
}

impl<T> Inner<T> {
    fn read_senders<'a>(&'a self) -> MutexGuard<'a, Vec<Sender<T>>> {
        self.senders.lock().unwrap()
    }

    fn add_sender(&self, sender: Sender<T>) {
        let mut vec = self.senders.lock().unwrap();
        vec.push(sender);
    }
}

/// Struct that receives messages from Broadcast.
pub struct Consumer<T> {
    inner: Arc<Inner<T>>,
    receiver: Receiver<T>,
}

impl<T> Consumer<T> {
    /// Receive a message from the Broadcast.
    ///
    /// This function will block.
    pub fn recv(&self) -> Result<T, BroadcastError<T>> {
        let data = try!(self.receiver.recv());
        Ok(data)
    }
}

impl<T> Clone for Consumer<T> {
    fn clone(&self) -> Self {
        let (s, r) = channel();
        self.inner.add_sender(s);
        Consumer {
            inner: self.inner.clone(),
            receiver: r,
        }
    }
}

/// Create a (Broadcast<T>, Consumer<T>) pair.
pub fn broadcast_channel<T: Clone>() -> (Broadcast<T>, Consumer<T>) {
    let broadcast = Broadcast::new();
    let consumer = broadcast.consume();
    (broadcast, consumer)
}

#[cfg(test)]
mod test {
    use broadcast::broadcast_channel;
    use super::Inner;

    use std::sync::{Arc, Mutex};
    use std::sync::mpsc::{channel};
    use std::thread::spawn;

    #[test]
    fn inner_iterator() {
        let (s1, r1) = channel();
        let (s2, r2) = channel();
        let inner = Arc::new(Inner { senders: Mutex::new(vec!(s1, s2)) });
        let guard = inner.read_senders();
        for s in guard.iter() {
            assert!(s.send(10u8).is_ok());
        }

        assert_eq!(r1.recv().unwrap(), 10u8);
        assert_eq!(r2.recv().unwrap(), 10u8);
    }

    #[test]
    fn sends_to_multiple_consumers() {
        let (p, c) = broadcast_channel();
        let c2 = c.clone();

        let res = p.send(9u8);
        assert!(res.is_ok());

        let res = c.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8);

        let res = c2.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8)
    }

    #[test]
    fn test_send_threads() {
        let (p, c1) = broadcast_channel();
        let c2 = c1.clone();

        let (s1, r1) = channel();
        let (s2, r2) = channel();

        let _thread = spawn(move || {
            assert_eq!(c1.recv().unwrap(), 9u8);
            s1.send(10u8).unwrap();
        });

        let _thread = spawn(move || {
            assert_eq!(c2.recv().unwrap(), 9u8);
            s2.send(10u8).unwrap();
        });

        assert!(p.send(9u8).is_ok());
        assert!(r1.recv().is_ok());
        assert!(r2.recv().is_ok());
    }
}
<|endoftext|>


<commit_before>
use std::thread;
use std::sync::mpsc;
use std::sync::{Arc, RwLock};
use std::io::Write;
use byteorder::{WriteBytesExt, NativeEndian};
use world;
use render;

const NUM_WORKERS: usize = 4;

pub struct ChunkBuilder {
    threads: Vec<(mpsc::Sender<BuildReq>, thread::JoinHandle<()>)>,
    free_builders: Vec<usize>,
    built_recv: mpsc::Receiver<(usize, BuildReply)>,
}

impl ChunkBuilder {
    pub fn new(textures: Arc<RwLock<render::TextureManager>>) -> ChunkBuilder {
        let mut threads = vec![];
        let mut free = vec![];
        let (built_send, built_recv) = mpsc::channel();
        for i in 0 .. NUM_WORKERS {
            let built_send = built_send.clone();
            let (work_send, work_recv) = mpsc::channel();
            let textures = textures.clone();
            let id = i;
            threads.push((work_send, thread::spawn(move || build_func(id, textures, work_recv, built_send))));
            free.push(i);
        }
        ChunkBuilder {
            threads: threads,
            free_builders: free,
            built_recv: built_recv,
        }
    }

    pub fn tick(&mut self, world: &mut world::World, renderer: &mut render::Renderer) {
        while let Ok((id, val)) = self.built_recv.try_recv() {
            world.reset_building_flag(val.position);

            renderer.update_chunk_solid(val.position, &val.solid_buffer, val.solid_count);

            self.free_builders.push(id);
        }
        if self.free_builders.is_empty() {
            return;
        }
        while let Some((x, y, z)) = world.next_dirty_chunk_section() {
            let t_id = self.free_builders.pop().unwrap();
            let (cx, cy, cz) = (x << 4, y << 4, z << 4);
            let mut snapshot = world.capture_snapshot(cx - 2, cy - 2, cz - 2, 20, 20, 20);
            snapshot.make_relative(-2, -2, -2);
            self.threads[t_id].0.send(BuildReq {
                snapshot: snapshot,
                position: (x, y, z),
            }).unwrap();
            if self.free_builders.is_empty() {
                return;
            }
        }
    }
}

struct BuildReq {
    snapshot: world::Snapshot,
    position: (i32, i32, i32),
}

struct BuildReply {
    position: (i32, i32, i32),
    solid_buffer: Vec<u8>,
    solid_count: usize,
}

fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, work_recv: mpsc::Receiver<BuildReq>, built_send: mpsc::Sender<(usize, BuildReply)>) {
    use rand::{self, Rng};
    loop {
        let BuildReq {
            snapshot,
            position,
        } = work_recv.recv().unwrap();

        let mut solid_buffer = vec![];
        let mut solid_count = 0;

        let mut rng = rand::thread_rng();

        for y in 0 .. 16 {
            for x in 0 .. 16 {
                for z in 0 .. 16 {
                    let block = snapshot.get_block(x, y, z);
                    if !block.renderable() {
                        continue;
                    }

                    for verts in &PRECOMPUTED_VERTS {
                        let stone = render::Renderer::get_texture(&textures, rng.choose(&[
                            "minecraft:blocks/lava_flow",
                            "minecraft:blocks/stone",
                            "minecraft:blocks/melon_side",
                            "minecraft:blocks/sand",
                        ]).unwrap());
                        solid_count += 6;
                        for vert in verts {
                            let mut vert = vert.clone();
                            // TODO
                            vert.r = 255;
                            vert.g = 255;
                            vert.b = 255;

                            vert.x += x as f32;
                            vert.y += y as f32;
                            vert.z += z as f32;

                            vert.toffsetx *= stone.get_width() as i16 * 16;
                            vert.toffsety *= stone.get_height() as i16 * 16;

                            // TODO
                            vert.block_light = 15 * 4000;
                            vert.sky_light = 15 * 4000;

                            // TODO
                            vert.tatlas = stone.atlas as i16;
                            vert.tx = stone.get_x() as u16;
                            vert.ty = stone.get_y() as u16;
                            vert.tw = stone.get_width() as u16;
                            vert.th = stone.get_height() as u16;

                            vert.write(&mut solid_buffer);
                        }
                    }
                }
            }
        }

        built_send.send((id, BuildReply {
            position: position,
            solid_buffer: solid_buffer,
            solid_count: solid_count,
        })).unwrap();
    }
}

const PRECOMPUTED_VERTS: [[BlockVertex; 4]; 6] = [
    [ // Up
        BlockVertex::base(0.0, 1.0, 0.0, 0, 0),
        BlockVertex::base(1.0, 1.0, 0.0, 1, 0),
        BlockVertex::base(0.0, 1.0, 1.0, 0, 1),
        BlockVertex::base(1.0, 1.0, 1.0, 1, 1),
    ],
    [ // Down
        BlockVertex::base(0.0, 0.0, 0.0, 0, 1),
        BlockVertex::base(0.0, 0.0, 1.0, 0, 0),
        BlockVertex::base(1.0, 0.0, 0.0, 1, 1),
        BlockVertex::base(1.0, 0.0, 1.0, 1, 0),
    ],
    [ // North
        BlockVertex::base(0.0, 0.0, 0.0, 1, 1),
        BlockVertex::base(1.0, 0.0, 0.0, 0, 1),
        BlockVertex::base(0.0, 1.0, 0.0, 1, 0),
        BlockVertex::base(1.0, 1.0, 0.0, 0, 0),
    ],
    [ // South
        BlockVertex::base(0.0, 0.0, 1.0, 0, 1),
        BlockVertex::base(0.0, 1.0, 1.0, 0, 0),
        BlockVertex::base(1.0, 0.0, 1.0, 1, 1),
        BlockVertex::base(1.0, 1.0, 1.0, 1, 0),
    ],
    [ // West
        BlockVertex::base(0.0, 0.0, 0.0, 0, 1),
        BlockVertex::base(0.0, 1.0, 0.0, 0, 0),
        BlockVertex::base(0.0, 0.0, 1.0, 1, 1),
        BlockVertex::base(0.0, 1.0, 1.0, 1, 0),
    ],
    [ // East
        BlockVertex::base(1.0, 0.0, 0.0, 1, 1),
        BlockVertex::base(1.0, 0.0, 1.0, 0, 1),
        BlockVertex::base(1.0, 1.0, 0.0, 1, 0),
        BlockVertex::base(1.0, 1.0, 1.0, 0, 0),
    ],
];

#[derive(Clone)]
pub struct BlockVertex {
    x: f32, y: f32, z: f32,
    tx: u16, ty: u16, tw: u16, th: u16,
    toffsetx: i16, toffsety: i16, tatlas: i16,
    r: u8, g: u8, b: u8,
    block_light: u16, sky_light: u16,
}

impl BlockVertex {
    const fn base(x: f32, y: f32, z: f32, tx: i16, ty: i16) -> BlockVertex {
        BlockVertex {
            x: x, y: y, z: z,
            tx: 0, ty: 0, tw: 0, th: 0,
            toffsetx: tx, toffsety: ty, tatlas: 0,
            r: 0, g: 0, b: 0,
            block_light: 0, sky_light: 0,
        }
    }
    fn write<W: Write>(&self, w: &mut W) {
        let _ = w.write_f32::<NativeEndian>(self.x);
        let _ = w.write_f32::<NativeEndian>(self.y);
        let _ = w.write_f32::<NativeEndian>(self.z);
        let _ = w.write_u16::<NativeEndian>(self.tx);
        let _ = w.write_u16::<NativeEndian>(self.ty);
        let _ = w.write_u16::<NativeEndian>(self.tw);
        let _ = w.write_u16::<NativeEndian>(self.th);
        let _ = w.write_i16::<NativeEndian>(self.toffsetx);
        let _ = w.write_i16::<NativeEndian>(self.toffsety);
        let _ = w.write_i16::<NativeEndian>(self.tatlas);
        let _ = w.write_i16::<NativeEndian>(0);
        let _ = w.write_u8(self.r);
        let _ = w.write_u8(self.g);
        let _ = w.write_u8(self.b);
        let _ = w.write_u8(255);
        let _ = w.write_u16::<NativeEndian>(self.block_light);
        let _ = w.write_u16::<NativeEndian>(self.sky_light);
        let _ = w.write_u16::<NativeEndian>(0);
        let _ = w.write_u16::<NativeEndian>(0);
    }
}
<commit_msg>Fix panics on shutdown (Fixes #15)<commit_after>
use std::thread;
use std::sync::mpsc;
use std::sync::{Arc, RwLock};
use std::io::Write;
use byteorder::{WriteBytesExt, NativeEndian};
use world;
use render;

const NUM_WORKERS: usize = 4;

pub struct ChunkBuilder {
    threads: Vec<(mpsc::Sender<BuildReq>, thread::JoinHandle<()>)>,
    free_builders: Vec<usize>,
    built_recv: mpsc::Receiver<(usize, BuildReply)>,
}

impl ChunkBuilder {
    pub fn new(textures: Arc<RwLock<render::TextureManager>>) -> ChunkBuilder {
        let mut threads = vec![];
        let mut free = vec![];
        let (built_send, built_recv) = mpsc::channel();
        for i in 0 .. NUM_WORKERS {
            let built_send = built_send.clone();
            let (work_send, work_recv) = mpsc::channel();
            let textures = textures.clone();
            let id = i;
            threads.push((work_send, thread::spawn(move || build_func(id, textures, work_recv, built_send))));
            free.push(i);
        }
        ChunkBuilder {
            threads: threads,
            free_builders: free,
            built_recv: built_recv,
        }
    }

    pub fn tick(&mut self, world: &mut world::World, renderer: &mut render::Renderer) {
        while let Ok((id, val)) = self.built_recv.try_recv() {
            world.reset_building_flag(val.position);

            renderer.update_chunk_solid(val.position, &val.solid_buffer, val.solid_count);

            self.free_builders.push(id);
        }
        if self.free_builders.is_empty() {
            return;
        }
        while let Some((x, y, z)) = world.next_dirty_chunk_section() {
            let t_id = self.free_builders.pop().unwrap();
            let (cx, cy, cz) = (x << 4, y << 4, z << 4);
            let mut snapshot = world.capture_snapshot(cx - 2, cy - 2, cz - 2, 20, 20, 20);
            snapshot.make_relative(-2, -2, -2);
            self.threads[t_id].0.send(BuildReq {
                snapshot: snapshot,
                position: (x, y, z),
            }).unwrap();
            if self.free_builders.is_empty() {
                return;
            }
        }
    }
}

struct BuildReq {
    snapshot: world::Snapshot,
    position: (i32, i32, i32),
}

struct BuildReply {
    position: (i32, i32, i32),
    solid_buffer: Vec<u8>,
    solid_count: usize,
}

fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, work_recv: mpsc::Receiver<BuildReq>, built_send: mpsc::Sender<(usize, BuildReply)>) {
    use rand::{self, Rng};
    loop {
        let BuildReq {
            snapshot,
            position,
        } = match work_recv.recv() {
            Ok(val) => val,
            Err(_) => return,
        };

        let mut solid_buffer = vec![];
        let mut solid_count = 0;

        let mut rng = rand::thread_rng();

        for y in 0 .. 16 {
            for x in 0 .. 16 {
                for z in 0 .. 16 {
                    let block = snapshot.get_block(x, y, z);
                    if !block.renderable() {
                        continue;
                    }

                    for verts in &PRECOMPUTED_VERTS {
                        let stone = render::Renderer::get_texture(&textures, rng.choose(&[
                            "minecraft:blocks/lava_flow",
                            "minecraft:blocks/stone",
                            "minecraft:blocks/melon_side",
                            "minecraft:blocks/sand",
                        ]).unwrap());
                        solid_count += 6;
                        for vert in verts {
                            let mut vert = vert.clone();
                            // TODO
                            vert.r = 255;
                            vert.g = 255;
                            vert.b = 255;

                            vert.x += x as f32;
                            vert.y += y as f32;
                            vert.z += z as f32;

                            vert.toffsetx *= stone.get_width() as i16 * 16;
                            vert.toffsety *= stone.get_height() as i16 * 16;

                            // TODO
                            vert.block_light = 15 * 4000;
                            vert.sky_light = 15 * 4000;

                            // TODO
                            vert.tatlas = stone.atlas as i16;
                            vert.tx = stone.get_x() as u16;
                            vert.ty = stone.get_y() as u16;
                            vert.tw = stone.get_width() as u16;
                            vert.th = stone.get_height() as u16;

                            vert.write(&mut solid_buffer);
                        }
                    }
                }
            }
        }

        built_send.send((id, BuildReply {
            position: position,
            solid_buffer: solid_buffer,
            solid_count: solid_count,
        })).unwrap();
    }
}

const PRECOMPUTED_VERTS: [[BlockVertex; 4]; 6] = [
    [ // Up
        BlockVertex::base(0.0, 1.0, 0.0, 0, 0),
        BlockVertex::base(1.0, 1.0, 0.0, 1, 0),
        BlockVertex::base(0.0, 1.0, 1.0, 0, 1),
        BlockVertex::base(1.0, 1.0, 1.0, 1, 1),
    ],
    [ // Down
        BlockVertex::base(0.0, 0.0, 0.0, 0, 1),
        BlockVertex::base(0.0, 0.0, 1.0, 0, 0),
        BlockVertex::base(1.0, 0.0, 0.0, 1, 1),
        BlockVertex::base(1.0, 0.0, 1.0, 1, 0),
    ],
    [ // North
        BlockVertex::base(0.0, 0.0, 0.0, 1, 1),
        BlockVertex::base(1.0, 0.0, 0.0, 0, 1),
        BlockVertex::base(0.0, 1.0, 0.0, 1, 0),
        BlockVertex::base(1.0, 1.0, 0.0, 0, 0),
    ],
    [ // South
        BlockVertex::base(0.0, 0.0, 1.0, 0, 1),
        BlockVertex::base(0.0, 1.0, 1.0, 0, 0),
        BlockVertex::base(1.0, 0.0, 1.0, 1, 1),
        BlockVertex::base(1.0, 1.0, 1.0, 1, 0),
    ],
    [ // West
        BlockVertex::base(0.0, 0.0, 0.0, 0, 1),
        BlockVertex::base(0.0, 1.0, 0.0, 0, 0),
        BlockVertex::base(0.0, 0.0, 1.0, 1, 1),
        BlockVertex::base(0.0, 1.0, 1.0, 1, 0),
    ],
    [ // East
        BlockVertex::base(1.0, 0.0, 0.0, 1, 1),
        BlockVertex::base(1.0, 0.0, 1.0, 0, 1),
        BlockVertex::base(1.0, 1.0, 0.0, 1, 0),
        BlockVertex::base(1.0, 1.0, 1.0, 0, 0),
    ],
];

#[derive(Clone)]
pub struct BlockVertex {
    x: f32, y: f32, z: f32,
    tx: u16, ty: u16, tw: u16, th: u16,
    toffsetx: i16, toffsety: i16, tatlas: i16,
    r: u8, g: u8, b: u8,
    block_light: u16, sky_light: u16,
}

impl BlockVertex {
    const fn base(x: f32, y: f32, z: f32, tx: i16, ty: i16) -> BlockVertex {
        BlockVertex {
            x: x, y: y, z: z,
            tx: 0, ty: 0, tw: 0, th: 0,
            toffsetx: tx, toffsety: ty, tatlas: 0,
            r: 0, g: 0, b: 0,
            block_light: 0, sky_light: 0,
        }
    }
    fn write<W: Write>(&self, w: &mut W) {
        let _ = w.write_f32::<NativeEndian>(self.x);
        let _ = w.write_f32::<NativeEndian>(self.y);
        let _ = w.write_f32::<NativeEndian>(self.z);
        let _ = w.write_u16::<NativeEndian>(self.tx);
        let _ = w.write_u16::<NativeEndian>(self.ty);
        let _ = w.write_u16::<NativeEndian>(self.tw);
        let _ = w.write_u16::<NativeEndian>(self.th);
        let _ = w.write_i16::<NativeEndian>(self.toffsetx);
        let _ = w.write_i16::<NativeEndian>(self.toffsety);
        let _ = w.write_i16::<NativeEndian>(self.tatlas);
        let _ = w.write_i16::<NativeEndian>(0);
        let _ = w.write_u8(self.r);
        let _ = w.write_u8(self.g);
        let _ = w.write_u8(self.b);
        let _ = w.write_u8(255);
        let _ = w.write_u16::<NativeEndian>(self.block_light);
        let _ = w.write_u16::<NativeEndian>(self.sky_light);
        let _ = w.write_u16::<NativeEndian>(0);
        let _ = w.write_u16::<NativeEndian>(0);
    }
}
<|endoftext|>


<commit_before>use analysis::namespaces;
use analysis::rust_type::rust_type;
use codegen::general;
use config::gobjects::GObject;
use env::Env;
use file_saver;
use library::*;
use std::io::prelude::*;
use std::io::Result;
use std::path::Path;
use traits::*;

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    let configs: Vec<&GObject> = env.config
        .objects
        .values()
        .filter(|c| {
            c.status.need_generate() && c.type_id.map_or(false, |tid| tid.ns_id == namespaces::MAIN)
        })
        .collect();
    let mut has_any = false;
    for config in &configs {
        if let Type::Alias(_) = *env.library.type_(config.type_id.unwrap()) {
            has_any = true;
            break;
        }
    }

    if !has_any {
        return;
    }

    let path = root_path.join("alias.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        try!(general::start_comments(w, &env.config));
        try!(writeln!(w, ""));

        mod_rs.push("\nmod alias;".into());
        for config in &configs {
            if let Type::Alias(ref alias) = *env.library.type_(config.type_id.unwrap()) {
                mod_rs.push(format!("pub use self::alias::{};", alias.name));
                try!(generate_alias(env, w, alias, config));
            }
        }

        Ok(())
    });
}

fn generate_alias(env: &Env, w: &mut Write, alias: &Alias, _: &GObject) -> Result<()> {
    let typ = rust_type(env, alias.typ).into_string();
    try!(writeln!(w, "pub type {} = {};", alias.name, typ));

    Ok(())
}
<commit_msg>Import everything from auto in case a type is an alias of an auto type<commit_after>use analysis::namespaces;
use analysis::rust_type::rust_type;
use codegen::general;
use config::gobjects::GObject;
use env::Env;
use file_saver;
use library::*;
use std::io::prelude::*;
use std::io::Result;
use std::path::Path;
use traits::*;

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    let configs: Vec<&GObject> = env.config
        .objects
        .values()
        .filter(|c| {
            c.status.need_generate() && c.type_id.map_or(false, |tid| tid.ns_id == namespaces::MAIN)
        })
        .collect();
    let mut has_any = false;
    for config in &configs {
        if let Type::Alias(_) = *env.library.type_(config.type_id.unwrap()) {
            has_any = true;
            break;
        }
    }

    if !has_any {
        return;
    }

    let path = root_path.join("alias.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        try!(general::start_comments(w, &env.config));
        try!(writeln!(w, ""));
        try!(writeln!(w, "#[allow(unused_imports)]"));
        try!(writeln!(w, "use auto::*;"));
        try!(writeln!(w, ""));

        mod_rs.push("\nmod alias;".into());
        for config in &configs {
            if let Type::Alias(ref alias) = *env.library.type_(config.type_id.unwrap()) {
                mod_rs.push(format!("pub use self::alias::{};", alias.name));
                try!(generate_alias(env, w, alias, config));
            }
        }

        Ok(())
    });
}

fn generate_alias(env: &Env, w: &mut Write, alias: &Alias, _: &GObject) -> Result<()> {
    let typ = rust_type(env, alias.typ).into_string();
    try!(writeln!(w, "pub type {} = {};", alias.name, typ));

    Ok(())
}
<|endoftext|>


<commit_before>extern crate libc;
use self::libc::*;

use low_level as ll;
use error::Error;
use device::Device;
use context::Context;
use event::{Event, EventStatus, EventLike};
use kernel::Kernel;
use mem::Mem;

use std::ptr;
use std::mem::{size_of, transmute};

pub struct CommandQueue {
    pub id: ll::CommandQueue,
}

pub struct ReadLock<'a, T: Sized + 'a> {
    #[allow(dead_code)]
    sl: &'a [T],
    evt: Event,
}

pub struct WriteLock<'a, T: Sized + 'a> {
    #[allow(dead_code)]
    sl: &'a mut [T],
    evt: Event,
}

impl<'a, T: Sized> Drop for ReadLock<'a, T> {
    fn drop(self: &mut Self) -> () {
        self.evt.wait().ok().expect(
            "error waiting to finish write for ReadLock");
    }
}

impl<'a, T: Sized> EventLike for ReadLock<'a, T> {
    fn status(self: &Self) -> Result<EventStatus, Error> {
        self.evt.status()
    }

    fn wait(self: &Self) -> Result<(), Error> {
        self.evt.wait()
    }
}

impl<'a, T: Sized> Drop for WriteLock<'a, T> {
    fn drop(self: &mut Self) -> () {
        self.evt.wait().ok().expect(
            "error waiting to finish write for ReadLock");
    }
}

impl<'a, T: Sized> EventLike for WriteLock<'a, T> {
    fn status(self: &Self) -> Result<EventStatus, Error> {
        self.evt.status()
    }

    fn wait(self: &Self) -> Result<(), Error> {
        self.evt.wait()
    }
}

impl CommandQueue {
    pub fn new(context: Context,
               device: Device) -> Result<CommandQueue, Error> {
        let props: c_ulong = if try!(device.out_of_order_supported()) {
            1
        } else {
            0
        };
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateCommandQueue(context.id,
                                              device.id,
                                              props,
                                              &mut err);
            try!(Error::check(err));
            id
        };
        Ok(CommandQueue{ id: id })
    }

    fn get_info(self: &Self, param: u32) -> Result<*mut c_void, Error> {
        let mut tr: *mut c_void = ptr::null_mut();
        unsafe {
            try!(Error::check(ll::clGetCommandQueueInfo(self.id,
                                                   param,
                                                   size_of::<*mut c_void>() as size_t,
                                                   transmute(&mut tr),
                                                   ptr::null_mut())));
        }
        Ok(tr)
    }

    pub fn context(self: &Self) -> Result<Context, Error> {
        let val = try!(self.get_info(0x1090));
        let id = unsafe { transmute(val) };
        unsafe {
            try!(Error::check(ll::clRetainContext(id)));
        }
        Ok(Context{id: id})
    }

    pub fn device(self: &Self) -> Result<Device, Error> {
        let val = try!(self.get_info(0x1091));
        let id = unsafe { transmute(val) };
        Ok(Device{id: id})
    }

    fn alloc_ll_buffer(self: &Self,
                    flags: c_ulong,
                    size_bytes: usize) -> Result<ll::Mem, Error> {
        let context = try!(self.context());
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateBuffer(context.id,
                                        flags,
                                        size_bytes as size_t,
                                        ptr::null_mut(),
                                        &mut err);
            try!(Error::check(err));
            id
        };
        Ok(id)
    }

    fn alloc_ll_buffer_with_data(self: &Self,
                                 flags: c_ulong,
                                 size_bytes: usize,
                                 data: *const c_void) -> Result<ll::Mem, Error> {
        let context = try!(self.context());
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateBuffer(context.id,
                                        flags | (1 << 5),
                                        size_bytes as size_t,
                                        data,
                                        &mut err);
            try!(Error::check(err));
            id
        };
        Ok(id)
    }

    fn write_buffer_raw<T: Sized>(self: &Self,
                       buf: &mut Mem,
                       offset: usize,
                       size: usize,
                       data: &[T]) -> Result<Event, Error> {
        let mut event_id: ll::Event = ptr::null_mut();
        let host_ptr = &data[0] as *const T;
        let wait_list: Vec<ll::Event> = buf.write_events();
        let wait_size = wait_list.len() as u32;

        let wait_list_ptr: *const ll::Event = match wait_size {
            0 => ptr::null(),
            _ => &wait_list[0],
        };

        unsafe {
            try!(Error::check(ll::clEnqueueWriteBuffer(self.id,
                                                       buf.id,
                                                       0, // don't block
                                                       offset as size_t,
                                                       size as size_t,
                                                       transmute(host_ptr),
                                                       wait_size,
                                                       wait_list_ptr,
                                                       &mut event_id)));
        }

        let event = Event{id: event_id};
        buf.register_write(event.clone());
        Ok(event)
    }

    fn read_buffer_raw<T: Sized>(self: &Self,
                                 buf: &Mem,
                                 offset: usize,
                                 size: usize,
                                 data: &mut [T]) -> Result<Event, Error> {
        let mut event_id: ll::Event = ptr::null_mut();
        let host_ptr = &mut data[0] as *mut T;
        let wait_list: Vec<ll::Event> = buf.read_events();
        let wait_size = wait_list.len() as u32;

        let wait_list_ptr: *const ll::Event = match wait_size {
            0 => ptr::null(),
            _ => &wait_list[0],
        };

        unsafe {
            try!(Error::check(ll::clEnqueueReadBuffer(self.id,
                                                      buf.id,
                                                      0, // don't block,
                                                      offset as size_t,
                                                      size as size_t,
                                                      transmute(host_ptr),
                                                      wait_size,
                                                      wait_list_ptr,
                                                      &mut event_id)));
        }

        let event = Event{id: event_id};
        buf.register_read(event.clone());
        Ok(event)
    }

    pub fn create_buffer(self: &Self,
                               size_bytes: usize) -> Result<Mem, Error> {
        let id = try!(self.alloc_ll_buffer(0, size_bytes));
        let tr = Mem::new(id);
        Ok(tr)
    }

    pub fn create_buffer_from_slice<T: Sized>(self: &Self,
                                    slice: &[T]) -> Result<Mem, Error> {
        let num_bytes = slice.len() * size_of::<T>();
        let id = try!(self.alloc_ll_buffer_with_data(0, num_bytes, unsafe { transmute(&slice[0]) } ));
        let tr = Mem::new(id);
        Ok(tr)
    }

    pub fn write_buffer<'a, 'b, T: Sized + 'a>(self: &Self,
                                  mem: &'b mut Mem,
                                  slice: &'a [T]) -> Result<ReadLock<'a, T>, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.write_buffer_raw(mem,
                                             0,
                                             size_bytes,
                                             slice));
        Ok(ReadLock{ evt: evt, sl: slice })
    }

    pub fn read_buffer<'a, T: Sized>(self: &Self,
                                 mem: &Mem,
                                 slice: &'a mut [T]) -> Result<WriteLock<'a, T>, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.read_buffer_raw(mem,
                                            0,
                                            size_bytes,
                                            slice));
        Ok(WriteLock{ evt: evt, sl: slice })
    }

    fn next_mul(self: &Self, global: usize, local: usize) -> usize {
        if global % local == 0 {
            global
        } else {
            ((global/local)+1)*local
        }
    }

    pub fn run( self: &Self,
                kernel: &mut Kernel,
                local_size: (usize, usize, usize),
                global_size: (usize, usize, usize)) -> Result<Event, Error> {
        let events = kernel.run_events();
        let global_size_fixed = (self.next_mul(global_size.0, local_size.0),
                                self.next_mul(global_size.1, local_size.1),
                                self.next_mul(global_size.2, local_size.2));

        let local_vec = vec!(local_size.0 as size_t,
                             local_size.1 as size_t,
                             local_size.2 as size_t);
        let global_vec = vec!(global_size_fixed.0 as size_t,
                              global_size_fixed.1 as size_t,
                              global_size_fixed.2 as size_t);

        let mut event_id: ll::Event = ptr::null_mut();
        unsafe {
            let events_val = if events.len() > 0 {
                transmute(&events[0])
            } else {
                ptr::null_mut()
            };
            try!(Error::check(ll::clEnqueueNDRangeKernel(self.id,
                                                         kernel.id,
                                                         3,
                                                         ptr::null(),
                                                         &global_vec[0],
                                                         &local_vec[0],
                                                         events.len() as u32,
                                                         events_val,
                                                         &mut event_id)));
        }
        let event = Event{id: event_id};

        try!(kernel.register_run(event.clone()));
        Ok(event)
    }
}

impl Drop for CommandQueue {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseCommandQueue(self.id))
                .ok().expect("Error releasing command queue");
        }
    }
}

impl Clone for CommandQueue {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainCommandQueue(self.id))
                .ok().expect("Error retaining command queue");
        }
        CommandQueue{ id: self.id }
    }
}

<commit_msg>simplfies create_buffer_from_slice<commit_after>extern crate libc;
use self::libc::*;

use low_level as ll;
use error::Error;
use device::Device;
use context::Context;
use event::{Event, EventStatus, EventLike};
use kernel::Kernel;
use mem::Mem;

use std::ptr;
use std::mem::{size_of, transmute};

pub struct CommandQueue {
    pub id: ll::CommandQueue,
}

pub struct ReadLock<'a, T: Sized + 'a> {
    #[allow(dead_code)]
    sl: &'a [T],
    evt: Event,
}

pub struct WriteLock<'a, T: Sized + 'a> {
    #[allow(dead_code)]
    sl: &'a mut [T],
    evt: Event,
}

impl<'a, T: Sized> Drop for ReadLock<'a, T> {
    fn drop(self: &mut Self) -> () {
        self.evt.wait().ok().expect(
            "error waiting to finish write for ReadLock");
    }
}

impl<'a, T: Sized> EventLike for ReadLock<'a, T> {
    fn status(self: &Self) -> Result<EventStatus, Error> {
        self.evt.status()
    }

    fn wait(self: &Self) -> Result<(), Error> {
        self.evt.wait()
    }
}

impl<'a, T: Sized> Drop for WriteLock<'a, T> {
    fn drop(self: &mut Self) -> () {
        self.evt.wait().ok().expect(
            "error waiting to finish write for ReadLock");
    }
}

impl<'a, T: Sized> EventLike for WriteLock<'a, T> {
    fn status(self: &Self) -> Result<EventStatus, Error> {
        self.evt.status()
    }

    fn wait(self: &Self) -> Result<(), Error> {
        self.evt.wait()
    }
}

impl CommandQueue {
    pub fn new(context: Context,
               device: Device) -> Result<CommandQueue, Error> {
        let props: c_ulong = if try!(device.out_of_order_supported()) {
            1
        } else {
            0
        };
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateCommandQueue(context.id,
                                              device.id,
                                              props,
                                              &mut err);
            try!(Error::check(err));
            id
        };
        Ok(CommandQueue{ id: id })
    }

    fn get_info(self: &Self, param: u32) -> Result<*mut c_void, Error> {
        let mut tr: *mut c_void = ptr::null_mut();
        unsafe {
            try!(Error::check(ll::clGetCommandQueueInfo(self.id,
                                                   param,
                                                   size_of::<*mut c_void>() as size_t,
                                                   transmute(&mut tr),
                                                   ptr::null_mut())));
        }
        Ok(tr)
    }

    pub fn context(self: &Self) -> Result<Context, Error> {
        let val = try!(self.get_info(0x1090));
        let id = unsafe { transmute(val) };
        unsafe {
            try!(Error::check(ll::clRetainContext(id)));
        }
        Ok(Context{id: id})
    }

    pub fn device(self: &Self) -> Result<Device, Error> {
        let val = try!(self.get_info(0x1091));
        let id = unsafe { transmute(val) };
        Ok(Device{id: id})
    }

    fn alloc_ll_buffer(self: &Self,
                    flags: c_ulong,
                    size_bytes: usize) -> Result<ll::Mem, Error> {
        let context = try!(self.context());
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateBuffer(context.id,
                                        flags,
                                        size_bytes as size_t,
                                        ptr::null_mut(),
                                        &mut err);
            try!(Error::check(err));
            id
        };
        Ok(id)
    }

    fn write_buffer_raw<T: Sized>(self: &Self,
                       buf: &mut Mem,
                       offset: usize,
                       size: usize,
                       data: &[T]) -> Result<Event, Error> {
        let mut event_id: ll::Event = ptr::null_mut();
        let host_ptr = &data[0] as *const T;
        let wait_list: Vec<ll::Event> = buf.write_events();
        let wait_size = wait_list.len() as u32;

        let wait_list_ptr: *const ll::Event = match wait_size {
            0 => ptr::null(),
            _ => &wait_list[0],
        };

        unsafe {
            try!(Error::check(ll::clEnqueueWriteBuffer(self.id,
                                                       buf.id,
                                                       0, // don't block
                                                       offset as size_t,
                                                       size as size_t,
                                                       transmute(host_ptr),
                                                       wait_size,
                                                       wait_list_ptr,
                                                       &mut event_id)));
        }

        let event = Event{id: event_id};
        buf.register_write(event.clone());
        Ok(event)
    }

    fn read_buffer_raw<T: Sized>(self: &Self,
                                 buf: &Mem,
                                 offset: usize,
                                 size: usize,
                                 data: &mut [T]) -> Result<Event, Error> {
        let mut event_id: ll::Event = ptr::null_mut();
        let host_ptr = &mut data[0] as *mut T;
        let wait_list: Vec<ll::Event> = buf.read_events();
        let wait_size = wait_list.len() as u32;

        let wait_list_ptr: *const ll::Event = match wait_size {
            0 => ptr::null(),
            _ => &wait_list[0],
        };

        unsafe {
            try!(Error::check(ll::clEnqueueReadBuffer(self.id,
                                                      buf.id,
                                                      0, // don't block,
                                                      offset as size_t,
                                                      size as size_t,
                                                      transmute(host_ptr),
                                                      wait_size,
                                                      wait_list_ptr,
                                                      &mut event_id)));
        }

        let event = Event{id: event_id};
        buf.register_read(event.clone());
        Ok(event)
    }

    pub fn create_buffer(self: &Self,
                               size_bytes: usize) -> Result<Mem, Error> {
        let id = try!(self.alloc_ll_buffer(0, size_bytes));
        let tr = Mem::new(id);
        Ok(tr)
    }

    pub fn create_buffer_from_slice<T: Sized>(self: &Self,
                                    slice: &[T]) -> Result<Mem, Error> {
        let num_bytes = slice.len() * size_of::<T>();
        let mut buf = try!(self.create_buffer(num_bytes));
        try!(self.write_buffer(&mut buf, slice));
        Ok(buf)
    }

    pub fn write_buffer<'a, 'b, T: Sized + 'a>(self: &Self,
                                  mem: &'b mut Mem,
                                  slice: &'a [T]) -> Result<ReadLock<'a, T>, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.write_buffer_raw(mem,
                                             0,
                                             size_bytes,
                                             slice));
        Ok(ReadLock{ evt: evt, sl: slice })
    }

    pub fn read_buffer<'a, T: Sized>(self: &Self,
                                 mem: &Mem,
                                 slice: &'a mut [T]) -> Result<WriteLock<'a, T>, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.read_buffer_raw(mem,
                                            0,
                                            size_bytes,
                                            slice));
        Ok(WriteLock{ evt: evt, sl: slice })
    }

    fn next_mul(self: &Self, global: usize, local: usize) -> usize {
        if global % local == 0 {
            global
        } else {
            ((global/local)+1)*local
        }
    }

    pub fn run( self: &Self,
                kernel: &mut Kernel,
                local_size: (usize, usize, usize),
                global_size: (usize, usize, usize)) -> Result<Event, Error> {
        let events = kernel.run_events();
        let global_size_fixed = (self.next_mul(global_size.0, local_size.0),
                                self.next_mul(global_size.1, local_size.1),
                                self.next_mul(global_size.2, local_size.2));

        let local_vec = vec!(local_size.0 as size_t,
                             local_size.1 as size_t,
                             local_size.2 as size_t);
        let global_vec = vec!(global_size_fixed.0 as size_t,
                              global_size_fixed.1 as size_t,
                              global_size_fixed.2 as size_t);

        let mut event_id: ll::Event = ptr::null_mut();
        unsafe {
            let events_val = if events.len() > 0 {
                transmute(&events[0])
            } else {
                ptr::null_mut()
            };
            try!(Error::check(ll::clEnqueueNDRangeKernel(self.id,
                                                         kernel.id,
                                                         3,
                                                         ptr::null(),
                                                         &global_vec[0],
                                                         &local_vec[0],
                                                         events.len() as u32,
                                                         events_val,
                                                         &mut event_id)));
        }
        let event = Event{id: event_id};

        try!(kernel.register_run(event.clone()));
        Ok(event)
    }
}

impl Drop for CommandQueue {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseCommandQueue(self.id))
                .ok().expect("Error releasing command queue");
        }
    }
}

impl Clone for CommandQueue {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainCommandQueue(self.id))
                .ok().expect("Error retaining command queue");
        }
        CommandQueue{ id: self.id }
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

use super::*;

use objc_foundation::{NSString, INSString};
use block::Block;

#[repr(u32)]
#[allow(non_camel_case_types)]
pub enum MTLCommandBufferStatus {
    NotEnqueued = 0,
    Enqueued = 1,
    Committed = 2,
    Scheduled = 3,
    Completed = 4,
    Error = 5,
}

#[repr(u32)]
#[allow(non_camel_case_types)]
pub enum MTLCommandBufferError {
    None = 0,
    Internal = 1,
    Timeout = 2,
    PageFault = 3,
    Blacklisted = 4,
    NotPermitted = 7,
    OutOfMemory = 8,
    InvalidResource = 9,
    Memoryless = 10,
    DeviceRemoved = 11,
}

type _MTLCommandBufferHandler = Block<(MTLCommandBuffer), ()>;

pub enum MTLCommandBuffer {}

foreign_obj_type! {
    type CType = MTLCommandBuffer;
    pub struct CommandBuffer;
    pub struct CommandBufferRef;
}

impl CommandBufferRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label: &NSString = msg_send![self, label];
            label.as_str()
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = NSString::from_str(label);
            msg_send![self, setLabel:nslabel];
        }
    }

    pub fn enqueue(&self) {
        unsafe {
            msg_send![self, enqueue]
        }
    }

    pub fn commit(&self) {
        unsafe {
            msg_send![self, commit]
        }
    }

    pub fn status(&self) -> MTLCommandBufferStatus {
        unsafe {
            msg_send![self, status]
        }
    }

    pub fn present_drawable(&self, drawable: &DrawableRef) {
        unsafe {
            msg_send![self, presentDrawable:drawable]
        }
    }

    pub fn wait_until_completed(&self) {
        unsafe {
            msg_send![self, waitUntilCompleted]
        }
    }

    pub fn wait_until_scheduled(&self) {
        unsafe {
            msg_send![self, waitUntilScheduled]
        }
    }

    pub fn new_blit_command_encoder(&self) -> &BlitCommandEncoderRef {
        unsafe {
            msg_send![self, blitCommandEncoder]
        }
    }

    pub fn new_compute_command_encoder(&self) -> &ComputeCommandEncoderRef {
        unsafe {
            msg_send![self, computeCommandEncoder]
        }
    }

    pub fn new_render_command_encoder(&self, descriptor: &RenderPassDescriptorRef) -> &RenderCommandEncoderRef {
        unsafe {
            msg_send![self, renderCommandEncoderWithDescriptor:descriptor]
        }
    }

    pub fn new_parallel_render_command_encoder(&self, descriptor: &RenderPassDescriptorRef) -> &ParallelRenderCommandEncoderRef {
        unsafe {
            msg_send![self, parallelRenderCommandEncoderWithDescriptor:descriptor]
        }
    }
}
<commit_msg>[MTLCommandBuffer] add MTLDispatchType related operation<commit_after>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

use super::*;

use objc_foundation::{NSString, INSString};
use block::Block;

#[repr(u32)]
#[allow(non_camel_case_types)]
pub enum MTLCommandBufferStatus {
    NotEnqueued = 0,
    Enqueued = 1,
    Committed = 2,
    Scheduled = 3,
    Completed = 4,
    Error = 5,
}

#[repr(u32)]
#[allow(non_camel_case_types)]
pub enum MTLCommandBufferError {
    None = 0,
    Internal = 1,
    Timeout = 2,
    PageFault = 3,
    Blacklisted = 4,
    NotPermitted = 7,
    OutOfMemory = 8,
    InvalidResource = 9,
    Memoryless = 10,
    DeviceRemoved = 11,
}

#[repr(u32)]
#[allow(non_camel_case_types)]
pub enum MTLDispatchType {
    Serial = 0,
    Concurrent = 1,
}

type _MTLCommandBufferHandler = Block<(MTLCommandBuffer), ()>;

pub enum MTLCommandBuffer {}

foreign_obj_type! {
    type CType = MTLCommandBuffer;
    pub struct CommandBuffer;
    pub struct CommandBufferRef;
}

impl CommandBufferRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label: &NSString = msg_send![self, label];
            label.as_str()
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = NSString::from_str(label);
            msg_send![self, setLabel:nslabel];
        }
    }

    pub fn enqueue(&self) {
        unsafe {
            msg_send![self, enqueue]
        }
    }

    pub fn commit(&self) {
        unsafe {
            msg_send![self, commit]
        }
    }

    pub fn status(&self) -> MTLCommandBufferStatus {
        unsafe {
            msg_send![self, status]
        }
    }

    pub fn present_drawable(&self, drawable: &DrawableRef) {
        unsafe {
            msg_send![self, presentDrawable:drawable]
        }
    }

    pub fn wait_until_completed(&self) {
        unsafe {
            msg_send![self, waitUntilCompleted]
        }
    }

    pub fn wait_until_scheduled(&self) {
        unsafe {
            msg_send![self, waitUntilScheduled]
        }
    }

    pub fn new_blit_command_encoder(&self) -> &BlitCommandEncoderRef {
        unsafe {
            msg_send![self, blitCommandEncoder]
        }
    }

    pub fn new_compute_command_encoder(&self) -> &ComputeCommandEncoderRef {
        unsafe {
            msg_send![self, computeCommandEncoder]
        }
    }

    pub fn new_render_command_encoder(&self, descriptor: &RenderPassDescriptorRef) -> &RenderCommandEncoderRef {
        unsafe {
            msg_send![self, renderCommandEncoderWithDescriptor:descriptor]
        }
    }

    pub fn new_parallel_render_command_encoder(&self, descriptor: &RenderPassDescriptorRef) -> &ParallelRenderCommandEncoderRef {
        unsafe {
            msg_send![self, parallelRenderCommandEncoderWithDescriptor:descriptor]
        }
    }

    pub fn compute_command_encoder_with_dispatch_type(&self, ty: MTLDispatchType) -> &ComputeCommandEncoderRef {
        unsafe {
            msg_send![self, computeCommandEncoderWithDispatchType: ty]
        }
    }
}
<|endoftext|>


<commit_before>//! Implements a command for showing infos from Sentry.
use std::io;
use std::collections::HashMap;

use clap::{App, Arg, ArgMatches};
use serde_json;

use prelude::*;
use api::Api;
use config::{Auth, Config};

#[derive(Serialize, Default)]
pub struct AuthStatus {
    #[serde(rename="type")]
    auth_type: Option<String>,
    successful: bool,
}

#[derive(Serialize, Default)]
pub struct ConfigStatus {
    config: HashMap<String, Option<String>>,
    auth: AuthStatus,
    have_dsn: bool,
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("print out information about the sentry server")
        .arg(Arg::with_name("quiet")
             .short("q")
             .long("quiet")
             .help("Do not output anything, just report a status \
                    code for correct config"))
        .arg(Arg::with_name("config_status_json")
             .long("config-status-json")
             .help("Returns the status of the config that sentry-cli loads \
                    as JSON dump. This can be used by external tools to aid \
                    the user towards configuration."))
}

fn describe_auth(auth: Option<&Auth>) -> &str {
    match auth {
        None => "Unauthorized",
        Some(&Auth::Token(_)) => "Auth Token",
        Some(&Auth::Key(_)) => "API Key",
    }
}

fn get_config_status_json(config: &Config) -> Result<()> {
    let mut rv = ConfigStatus::default();

    let (org, project) = config.get_org_and_project_defaults();
    rv.config.insert("org".into(), org);
    rv.config.insert("project".into(), project);
    rv.config.insert("url".into(), Some(config.url.clone()));

    rv.auth.auth_type = config.auth.as_ref().map(|val| match val {
        &Auth::Token(_) => "token".into(),
        &Auth::Key(_) => "api_key".into(),
    });
    rv.auth.successful = config.auth.is_some() && Api::new(config).get_auth_info().is_ok();
    rv.have_dsn = config.get_dsn().is_ok();

    serde_json::to_writer_pretty(&mut io::stdout(), &rv)?;
    println!("");
    Ok(())
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> Result<()> {
    if matches.is_present("config_status_json") {
        return get_config_status_json(config);
    }

    let (org, project) = config.get_org_and_project_defaults();
    let info_rv = Api::new(config).get_auth_info();
    let errors = project.is_none() || org.is_none() || config.auth.is_none() || info_rv.is_err();

    if !matches.is_present("quiet") {
        println!("Sentry Server: {}", config.url);
        println!("Default Organization: {}", project.unwrap_or("-".into()));
        println!("Default Project: {}", org.unwrap_or("-".into()));

        if config.auth.is_some() {
            println!("");
            println!("Authentication Info:");
            println!("  Method: {}", describe_auth(config.auth.as_ref()));
            match info_rv {
                Ok(info) => {
                    if let Some(ref user) = info.user {
                        println!("  User: {}", user.email);
                    }
                    if let Some(ref auth) = info.auth {
                        println!("  Scopes:");
                        for scope in &auth.scopes {
                            println!("    - {}", scope);
                        }
                    }
                }
                Err(err) => {
                    println!("  (failure on authentication: {})", err);
                }
            }
        }
    }

    if errors {
        Err(ErrorKind::QuietExit(1).into())
    } else {
        Ok(())
    }
}
<commit_msg>fix: Correct swapped project and org in info command output (#124)<commit_after>//! Implements a command for showing infos from Sentry.
use std::io;
use std::collections::HashMap;

use clap::{App, Arg, ArgMatches};
use serde_json;

use prelude::*;
use api::Api;
use config::{Auth, Config};

#[derive(Serialize, Default)]
pub struct AuthStatus {
    #[serde(rename="type")]
    auth_type: Option<String>,
    successful: bool,
}

#[derive(Serialize, Default)]
pub struct ConfigStatus {
    config: HashMap<String, Option<String>>,
    auth: AuthStatus,
    have_dsn: bool,
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("print out information about the sentry server")
        .arg(Arg::with_name("quiet")
             .short("q")
             .long("quiet")
             .help("Do not output anything, just report a status \
                    code for correct config"))
        .arg(Arg::with_name("config_status_json")
             .long("config-status-json")
             .help("Returns the status of the config that sentry-cli loads \
                    as JSON dump. This can be used by external tools to aid \
                    the user towards configuration."))
}

fn describe_auth(auth: Option<&Auth>) -> &str {
    match auth {
        None => "Unauthorized",
        Some(&Auth::Token(_)) => "Auth Token",
        Some(&Auth::Key(_)) => "API Key",
    }
}

fn get_config_status_json(config: &Config) -> Result<()> {
    let mut rv = ConfigStatus::default();

    let (org, project) = config.get_org_and_project_defaults();
    rv.config.insert("org".into(), org);
    rv.config.insert("project".into(), project);
    rv.config.insert("url".into(), Some(config.url.clone()));

    rv.auth.auth_type = config.auth.as_ref().map(|val| match val {
        &Auth::Token(_) => "token".into(),
        &Auth::Key(_) => "api_key".into(),
    });
    rv.auth.successful = config.auth.is_some() && Api::new(config).get_auth_info().is_ok();
    rv.have_dsn = config.get_dsn().is_ok();

    serde_json::to_writer_pretty(&mut io::stdout(), &rv)?;
    println!("");
    Ok(())
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> Result<()> {
    if matches.is_present("config_status_json") {
        return get_config_status_json(config);
    }

    let (org, project) = config.get_org_and_project_defaults();
    let info_rv = Api::new(config).get_auth_info();
    let errors = project.is_none() || org.is_none() || config.auth.is_none() || info_rv.is_err();

    if !matches.is_present("quiet") {
        println!("Sentry Server: {}", config.url);
        println!("Default Organization: {}", org.unwrap_or("-".into()));
        println!("Default Project: {}", project.unwrap_or("-".into()));

        if config.auth.is_some() {
            println!("");
            println!("Authentication Info:");
            println!("  Method: {}", describe_auth(config.auth.as_ref()));
            match info_rv {
                Ok(info) => {
                    if let Some(ref user) = info.user {
                        println!("  User: {}", user.email);
                    }
                    if let Some(ref auth) = info.auth {
                        println!("  Scopes:");
                        for scope in &auth.scopes {
                            println!("    - {}", scope);
                        }
                    }
                }
                Err(err) => {
                    println!("  (failure on authentication: {})", err);
                }
            }
        }
    }

    if errors {
        Err(ErrorKind::QuietExit(1).into())
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::cmp;

use bytes::Bytes;

use error;

use solicit::end_stream::EndStream;
use solicit::header::Headers;
use solicit::session::StreamState;
use solicit::WindowSize;

use super::types::Types;

use super::stream_queue::StreamQueue;
use super::window_size;
use common::stream_handler::StreamHandlerInternal;
use data_or_headers::DataOrHeaders;
use data_or_headers_with_flag::DataOrHeadersWithFlag;
use ErrorCode;

pub enum HttpStreamCommand {
    Headers(Headers, EndStream),
    Data(Bytes, EndStream),
    Rst(ErrorCode),
}

impl HttpStreamCommand {
    pub fn from(part: DataOrHeadersWithFlag) -> HttpStreamCommand {
        let end_stream = match part.last {
            true => EndStream::Yes,
            false => EndStream::No,
        };
        match part.content {
            DataOrHeaders::Data(data) => HttpStreamCommand::Data(data, end_stream),
            DataOrHeaders::Headers(headers) => HttpStreamCommand::Headers(headers, end_stream),
        }
    }
}

#[must_use]
pub struct DroppedData {
    pub size: usize,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct HttpStreamStateSnapshot {
    pub state: StreamState,
    pub out_window_size: i32,
    pub in_window_size: i32,
    pub pump_out_window_size: isize,
    pub queued_out_data_size: usize,
    pub out_data_size: usize,
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum InMessageStage {
    Initial,
    AfterInitialHeaders,
    AfterTrailingHeaders,
}

/// All HTTP/2 stream state.
/// Note the state must be kept in sync with other fields,
/// thus sometimes this object must be manipulated with `HttpStreamRef`.
pub(crate) struct HttpStreamCommon<T: Types> {
    pub specific: T::HttpStreamSpecific,
    pub state: StreamState,
    pub out_window_size: WindowSize,
    pub in_window_size: WindowSize,
    pub outgoing: StreamQueue,
    pub peer_tx: Option<T::StreamHandlerHolder>,
    // task waiting for window increase
    pub pump_out_window: window_size::StreamOutWindowSender,
    // Incoming remaining content-length
    pub in_rem_content_length: Option<u64>,
    pub in_message_stage: InMessageStage,
}

impl<T: Types> HttpStreamCommon<T> {
    pub fn new(
        in_window_size: u32,
        out_window_size: u32,
        pump_out_window: window_size::StreamOutWindowSender,
        in_rem_content_length: Option<u64>,
        in_message_stage: InMessageStage,
        specific: T::HttpStreamSpecific,
    ) -> HttpStreamCommon<T> {
        HttpStreamCommon {
            specific,
            state: StreamState::Open,
            in_window_size: WindowSize::new(in_window_size as i32),
            out_window_size: WindowSize::new(out_window_size as i32),
            outgoing: StreamQueue::new(),
            peer_tx: None,
            pump_out_window,
            in_rem_content_length,
            in_message_stage,
        }
    }

    pub fn snapshot(&self) -> HttpStreamStateSnapshot {
        HttpStreamStateSnapshot {
            state: self.state,
            out_window_size: self.out_window_size.0,
            in_window_size: self.in_window_size.0,
            pump_out_window_size: self.pump_out_window.get(),
            queued_out_data_size: self.outgoing.data_size(),
            out_data_size: self.outgoing.data_size(),
        }
    }

    pub fn close_local(&mut self) {
        trace!("close local");
        self.state = match self.state {
            StreamState::Closed | StreamState::HalfClosedRemote => StreamState::Closed,
            _ => StreamState::HalfClosedLocal,
        };
    }

    pub fn close_remote(&mut self) {
        trace!("close remote");
        self.state = match self.state {
            StreamState::Closed | StreamState::HalfClosedLocal => StreamState::Closed,
            _ => StreamState::HalfClosedRemote,
        };
    }

    pub fn conn_died(self, error: error::Error) {
        if let Some(mut handler) = self.peer_tx {
            drop(handler.error(error));
        }
    }

    /// Must be kept in sync with `pop_outg`.
    pub fn is_writable(&self) -> bool {
        match self.outgoing.front() {
            Some(front) => match front {
                DataOrHeaders::Headers(..) => true,
                DataOrHeaders::Data(data) => data.len() == 0 || self.out_window_size.size() != 0,
            },
            None => {
                if let Some(_error_code) = self.outgoing.end() {
                    if !self.state.is_closed_local() {
                        return true;
                    }
                };

                false
            }
        }
    }

    #[cfg(debug_assertions)]
    pub fn pop_outg(&mut self, conn_out_window_size: &mut WindowSize) -> Option<HttpStreamCommand> {
        let writable = self.is_writable();
        let window_size_before = conn_out_window_size.0;

        let command = self.pop_outg_impl(conn_out_window_size);
        if command.is_some() {
            assert!(writable);
        } else {
            assert!(!writable || window_size_before == 0);
        }
        command
    }

    #[cfg(not(debug_assertions))]
    pub fn pop_outg(&mut self, conn_out_window_size: &mut WindowSize) -> Option<HttpStreamCommand> {
        self.pop_outg_impl(conn_out_window_size)
    }

    fn pop_outg_impl(
        &mut self,
        conn_out_window_size: &mut WindowSize,
    ) -> Option<HttpStreamCommand> {
        if self.outgoing.is_empty() {
            return if let Some(error_code) = self.outgoing.end() {
                if self.state.is_closed_local() {
                    None
                } else {
                    self.close_local();
                    Some(match error_code {
                        ErrorCode::NoError => HttpStreamCommand::Data(Bytes::new(), EndStream::Yes),
                        error_code => HttpStreamCommand::Rst(error_code),
                    })
                }
            } else {
                None
            };
        }

        let pop_headers = if let &DataOrHeaders::Headers(..) = self.outgoing.front().unwrap() {
            true
        } else {
            false
        };
        if pop_headers {
            let r = self.outgoing.pop_front().unwrap();
            let last = self.outgoing.end() == Some(ErrorCode::NoError);
            if last {
                self.close_local();
            }
            return Some(HttpStreamCommand::from(DataOrHeadersWithFlag {
                content: r,
                last: last,
            }));
        }

        if self.out_window_size.size() <= 0 || conn_out_window_size.size() <= 0 {
            return None;
        }

        let mut data = if let Some(DataOrHeaders::Data(data)) = self.outgoing.pop_front() {
            data
        } else {
            unreachable!()
        };

        // Min of connection and stream window size
        let max_window = cmp::min(self.out_window_size.size(), conn_out_window_size.size());

        if data.len() as usize > max_window as usize {
            trace!("truncating data of len {} to {}", data.len(), max_window);
            let size = max_window as usize;
            let rem = data.split_off(size);
            self.outgoing.push_front(DataOrHeaders::Data(rem));
        };

        self.out_window_size
            .try_decrease_to_positive(data.len() as i32)
            .unwrap();
        conn_out_window_size
            .try_decrease_to_positive(data.len() as i32)
            .unwrap();

        let last = self.outgoing.end() == Some(ErrorCode::NoError);
        if last {
            self.close_local();
        }

        Some(HttpStreamCommand::from(DataOrHeadersWithFlag {
            content: DataOrHeaders::Data(data),
            last: last,
        }))
    }

    pub fn data_recvd(&mut self, data: Bytes, last: bool) {
        if let Some(ref mut response_handler) = self.peer_tx {
            // TODO: reset stream if rx is dead
            drop(response_handler.data_frame(data, last));
        }
    }

    pub fn rst_recvd(&mut self, error_code: ErrorCode) -> DroppedData {
        if let Some(ref mut response_handler) = self.peer_tx.take() {
            drop(response_handler.rst(error_code));
        }
        DroppedData {
            size: self.outgoing.data_size(),
        }
    }

    pub fn goaway_recvd(&mut self, _raw_error_code: u32) {
        if let Some(mut response_handler) = self.peer_tx.take() {
            // it is OK to ignore error: handler may be already dead
            drop(response_handler.error(error::Error::Other("peer sent GOAWAY")));
        }
    }
}

pub(crate) trait HttpStreamDataSpecific {}

pub(crate) trait HttpStreamData {
    type Types: Types;
}
<commit_msg>Make sure error callback is called not more than once<commit_after>use std::cmp;

use bytes::Bytes;

use error;

use solicit::end_stream::EndStream;
use solicit::header::Headers;
use solicit::session::StreamState;
use solicit::WindowSize;

use super::types::Types;

use super::stream_queue::StreamQueue;
use super::window_size;
use common::stream_handler::StreamHandlerInternal;
use data_or_headers::DataOrHeaders;
use data_or_headers_with_flag::DataOrHeadersWithFlag;
use ErrorCode;

pub enum HttpStreamCommand {
    Headers(Headers, EndStream),
    Data(Bytes, EndStream),
    Rst(ErrorCode),
}

impl HttpStreamCommand {
    pub fn from(part: DataOrHeadersWithFlag) -> HttpStreamCommand {
        let end_stream = match part.last {
            true => EndStream::Yes,
            false => EndStream::No,
        };
        match part.content {
            DataOrHeaders::Data(data) => HttpStreamCommand::Data(data, end_stream),
            DataOrHeaders::Headers(headers) => HttpStreamCommand::Headers(headers, end_stream),
        }
    }
}

#[must_use]
pub struct DroppedData {
    pub size: usize,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct HttpStreamStateSnapshot {
    pub state: StreamState,
    pub out_window_size: i32,
    pub in_window_size: i32,
    pub pump_out_window_size: isize,
    pub queued_out_data_size: usize,
    pub out_data_size: usize,
}

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum InMessageStage {
    Initial,
    AfterInitialHeaders,
    AfterTrailingHeaders,
}

/// All HTTP/2 stream state.
/// Note the state must be kept in sync with other fields,
/// thus sometimes this object must be manipulated with `HttpStreamRef`.
pub(crate) struct HttpStreamCommon<T: Types> {
    pub specific: T::HttpStreamSpecific,
    pub state: StreamState,
    pub out_window_size: WindowSize,
    pub in_window_size: WindowSize,
    pub outgoing: StreamQueue,
    pub peer_tx: Option<T::StreamHandlerHolder>,
    // task waiting for window increase
    pub pump_out_window: window_size::StreamOutWindowSender,
    // Incoming remaining content-length
    pub in_rem_content_length: Option<u64>,
    pub in_message_stage: InMessageStage,
}

impl<T: Types> HttpStreamCommon<T> {
    pub fn new(
        in_window_size: u32,
        out_window_size: u32,
        pump_out_window: window_size::StreamOutWindowSender,
        in_rem_content_length: Option<u64>,
        in_message_stage: InMessageStage,
        specific: T::HttpStreamSpecific,
    ) -> HttpStreamCommon<T> {
        HttpStreamCommon {
            specific,
            state: StreamState::Open,
            in_window_size: WindowSize::new(in_window_size as i32),
            out_window_size: WindowSize::new(out_window_size as i32),
            outgoing: StreamQueue::new(),
            peer_tx: None,
            pump_out_window,
            in_rem_content_length,
            in_message_stage,
        }
    }

    pub fn snapshot(&self) -> HttpStreamStateSnapshot {
        HttpStreamStateSnapshot {
            state: self.state,
            out_window_size: self.out_window_size.0,
            in_window_size: self.in_window_size.0,
            pump_out_window_size: self.pump_out_window.get(),
            queued_out_data_size: self.outgoing.data_size(),
            out_data_size: self.outgoing.data_size(),
        }
    }

    pub fn close_local(&mut self) {
        trace!("close local");
        self.state = match self.state {
            StreamState::Closed | StreamState::HalfClosedRemote => StreamState::Closed,
            _ => StreamState::HalfClosedLocal,
        };
    }

    pub fn close_remote(&mut self) {
        trace!("close remote");
        self.state = match self.state {
            StreamState::Closed | StreamState::HalfClosedLocal => StreamState::Closed,
            _ => StreamState::HalfClosedRemote,
        };
    }

    pub fn conn_died(mut self, error: error::Error) {
        if let Some(mut handler) = self.peer_tx.take() {
            drop(handler.error(error));
        }
    }

    /// Must be kept in sync with `pop_outg`.
    pub fn is_writable(&self) -> bool {
        match self.outgoing.front() {
            Some(front) => match front {
                DataOrHeaders::Headers(..) => true,
                DataOrHeaders::Data(data) => data.len() == 0 || self.out_window_size.size() != 0,
            },
            None => {
                if let Some(_error_code) = self.outgoing.end() {
                    if !self.state.is_closed_local() {
                        return true;
                    }
                };

                false
            }
        }
    }

    #[cfg(debug_assertions)]
    pub fn pop_outg(&mut self, conn_out_window_size: &mut WindowSize) -> Option<HttpStreamCommand> {
        let writable = self.is_writable();
        let window_size_before = conn_out_window_size.0;

        let command = self.pop_outg_impl(conn_out_window_size);
        if command.is_some() {
            assert!(writable);
        } else {
            assert!(!writable || window_size_before == 0);
        }
        command
    }

    #[cfg(not(debug_assertions))]
    pub fn pop_outg(&mut self, conn_out_window_size: &mut WindowSize) -> Option<HttpStreamCommand> {
        self.pop_outg_impl(conn_out_window_size)
    }

    fn pop_outg_impl(
        &mut self,
        conn_out_window_size: &mut WindowSize,
    ) -> Option<HttpStreamCommand> {
        if self.outgoing.is_empty() {
            return if let Some(error_code) = self.outgoing.end() {
                if self.state.is_closed_local() {
                    None
                } else {
                    self.close_local();
                    Some(match error_code {
                        ErrorCode::NoError => HttpStreamCommand::Data(Bytes::new(), EndStream::Yes),
                        error_code => HttpStreamCommand::Rst(error_code),
                    })
                }
            } else {
                None
            };
        }

        let pop_headers = if let &DataOrHeaders::Headers(..) = self.outgoing.front().unwrap() {
            true
        } else {
            false
        };
        if pop_headers {
            let r = self.outgoing.pop_front().unwrap();
            let last = self.outgoing.end() == Some(ErrorCode::NoError);
            if last {
                self.close_local();
            }
            return Some(HttpStreamCommand::from(DataOrHeadersWithFlag {
                content: r,
                last: last,
            }));
        }

        if self.out_window_size.size() <= 0 || conn_out_window_size.size() <= 0 {
            return None;
        }

        let mut data = if let Some(DataOrHeaders::Data(data)) = self.outgoing.pop_front() {
            data
        } else {
            unreachable!()
        };

        // Min of connection and stream window size
        let max_window = cmp::min(self.out_window_size.size(), conn_out_window_size.size());

        if data.len() as usize > max_window as usize {
            trace!("truncating data of len {} to {}", data.len(), max_window);
            let size = max_window as usize;
            let rem = data.split_off(size);
            self.outgoing.push_front(DataOrHeaders::Data(rem));
        };

        self.out_window_size
            .try_decrease_to_positive(data.len() as i32)
            .unwrap();
        conn_out_window_size
            .try_decrease_to_positive(data.len() as i32)
            .unwrap();

        let last = self.outgoing.end() == Some(ErrorCode::NoError);
        if last {
            self.close_local();
        }

        Some(HttpStreamCommand::from(DataOrHeadersWithFlag {
            content: DataOrHeaders::Data(data),
            last: last,
        }))
    }

    pub fn data_recvd(&mut self, data: Bytes, last: bool) {
        if let Some(ref mut response_handler) = self.peer_tx {
            // TODO: reset stream if rx is dead
            drop(response_handler.data_frame(data, last));
        }
    }

    pub fn rst_recvd(&mut self, error_code: ErrorCode) -> DroppedData {
        if let Some(ref mut response_handler) = self.peer_tx.take() {
            drop(response_handler.rst(error_code));
        }
        DroppedData {
            size: self.outgoing.data_size(),
        }
    }

    pub fn goaway_recvd(&mut self, _raw_error_code: u32) {
        if let Some(mut response_handler) = self.peer_tx.take() {
            // it is OK to ignore error: handler may be already dead
            drop(response_handler.error(error::Error::Other("peer sent GOAWAY")));
        }
    }
}

pub(crate) trait HttpStreamDataSpecific {}

pub(crate) trait HttpStreamData {
    type Types: Types;
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Hub
//!
//! A hub provides a way to connect components into a tree. Hubs don't store changes, but can be used with things like
//! `ComponentEndPoint` to make component results user accessible.
//!

use super::super::tree::*;
use super::component::*;
use super::bus_publisher::*;
use super::immediate_publisher::*;

///
///
///
pub struct Hub {
    ///
    /// Passes changes between components
    ///
    bus: TreeChangeBus,

    ///
    /// Components attached to this hub
    ///
    components: Vec<ComponentRef>
}

impl Hub {
    ///
    /// Creates a new hub
    ///
    pub fn new() -> Hub {
        Hub { bus: TreeChangeBus::new(), components: vec![] }
    }

    ///
    /// Returns a consumer that will read from a particular address relative to this hub
    ///
    pub fn read_from<T: ToTreeAddress>(&mut self, address: &T) -> ConsumerRef {
        unimplemented!();
    }

    ///
    /// Returns a publisher that will write to a particular address relative to this hub
    ///
    pub fn publish_to<T: ToTreeAddress>(&mut self, address: &T) -> PublisherRef {
        let publisher   = ImmediatePublisher::new();
        let consumer    = publisher.create_consumer();

        let subscription = consumer.subscribe()

        unimplemented!();
    }

    ///
    /// Attaches a component that reads from a particular address and publishes its results to another
    ///
    pub fn add_component<TComponent: ConvertToComponent, TFrom: ToTreeAddress, TTo: ToTreeAddress>(&mut self, component: TComponent, read_from: &TFrom, publish_to: &TTo) {
        let consumer    = self.read_from(read_from);
        let publisher   = self.publish_to(publish_to);

        self.components.push(component.into_component(consumer, publisher));
    }

    ///
    /// Pumps any messages waiting for this hub
    ///
    #[inline]
    pub fn pump(&mut self) {
        self.bus.pump();
    }

    ///
    /// Processes messages for this hub until there are no more to be processed
    ///
    #[inline]
    pub fn flush(&mut self) {
        self.bus.flush();
    }
}
<commit_msg>Implement the publish_to method in the hub<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Hub
//!
//! A hub provides a way to connect components into a tree. Hubs don't store changes, but can be used with things like
//! `ComponentEndPoint` to make component results user accessible.
//!

use super::super::tree::*;
use super::component::*;
use super::bus_publisher::*;
use super::immediate_publisher::*;

///
///
///
pub struct Hub {
    ///
    /// Passes changes between components
    ///
    bus: TreeChangeBus,

    ///
    /// Components attached to this hub
    ///
    components: Vec<ComponentRef>
}

impl Hub {
    ///
    /// Creates a new hub
    ///
    pub fn new() -> Hub {
        Hub { bus: TreeChangeBus::new(), components: vec![] }
    }

    ///
    /// Returns a consumer that will read from a particular address relative to this hub
    ///
    pub fn read_from<T: ToTreeAddress>(&mut self, address: &T) -> ConsumerRef {
        unimplemented!();
    }

    ///
    /// Returns a publisher that will write to a particular address relative to this hub
    ///
    pub fn publish_to<T: ToTreeAddress>(&mut self, address: &T) -> PublisherRef {
        let publisher           = ImmediatePublisher::new();
        let mut consumer        = publisher.create_consumer();
        let mut bus_publisher   = self.bus.create_publisher();
        let target_address      = address.to_tree_address();

        consumer.subscribe(TreeAddress::Here, TreeExtent::SubTree, Box::new(move |change| {
            let relative_change = change.relative_to(&target_address);

            if let Some(relative_change) = relative_change {
                bus_publisher.publish(relative_change);
            }
        }));

        publisher
    }

    ///
    /// Attaches a component that reads from a particular address and publishes its results to another
    ///
    pub fn add_component<TComponent: ConvertToComponent, TFrom: ToTreeAddress, TTo: ToTreeAddress>(&mut self, component: TComponent, read_from: &TFrom, publish_to: &TTo) {
        let consumer    = self.read_from(read_from);
        let publisher   = self.publish_to(publish_to);

        self.components.push(component.into_component(consumer, publisher));
    }

    ///
    /// Pumps any messages waiting for this hub
    ///
    #[inline]
    pub fn pump(&mut self) {
        self.bus.pump();
    }

    ///
    /// Processes messages for this hub until there are no more to be processed
    ///
    #[inline]
    pub fn flush(&mut self) {
        self.bus.flush();
    }
}
<|endoftext|>