<commit_before>// Copyright 2015 The tiny-http Contributors
// Copyright 2015 The rust-chunked-transfer Contributors
//
// 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.

use std::io::Result as IoResult;
use std::io::Write;

/// Splits the incoming data into HTTP chunks.
///
/// # Example
///
/// ```
/// use chunked_transfer::Encoder;
/// use std::io::Write;
///
/// let mut decoded = "hello world";
/// let mut encoded: Vec<u8> = vec![];
///
/// {
///     let mut encoder = Encoder::with_chunks_size(&mut encoded, 5);
///     encoder.write_all(decoded.as_bytes());
/// }
///
/// assert_eq!(encoded, b"5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n");
/// ```
pub struct Encoder<W>
where
    W: Write,
{
    // where to send the result
    output: W,

    // size of each chunk
    chunks_size: usize,

    // data waiting to be sent is stored here
    // This will always be at least 6 bytes long. The first 6 bytes
    // are reserved for the chunk size and \r\n.
    buffer: Vec<u8>,

    // Flushes the internal buffer after each write. This might be useful
    // if data should be sent immediately to downstream consumers
    flush_after_write: bool,
}

const MAX_CHUNK_SIZE: usize = std::u32::MAX as usize;
const HEADER_SIZE: usize = 6;

impl<W> Encoder<W>
where
    W: Write,
{
    pub fn new(output: W) -> Encoder<W> {
        Encoder::with_chunks_size(output, 8192)
    }

    pub fn with_chunks_size(output: W, chunks: usize) -> Encoder<W> {
        let chunks_size = chunks.min(MAX_CHUNK_SIZE);
        let mut encoder = Encoder {
            output,
            chunks_size,
            buffer: Vec::with_capacity(0),
            flush_after_write: false,
        };
        encoder.reset_buffer();
        encoder
    }

    pub fn with_flush_after_write(output: W) -> Encoder<W> {
        let mut encoder = Encoder {
            output,
            chunks_size: 8192,
            buffer: Vec::with_capacity(0),
            flush_after_write: true,
        };
        encoder.reset_buffer();
        encoder
    }

    fn reset_buffer(&mut self) {
        // Reset buffer
        self.buffer.clear();
        // Arbitrary bytes to take up space. Should never be seen in output.
        let placeholder: [u8; HEADER_SIZE] = *b"DACE\r\n";
        self.buffer.extend_from_slice(&placeholder);
    }

    fn is_buffer_empty(&self) -> bool {
        self.buffer.len() == HEADER_SIZE
    }

    fn send(&mut self) -> IoResult<()> {
        // Never send an empty buffer, because that would be interpreted
        // as the end of the stream, which we indicate explicitly on drop.
        if self.is_buffer_empty() {
            return Ok(());
        }
        // Prepend the length and \r\n to the buffer.
        let prelude = format!("{:x}\r\n", self.buffer.len() - HEADER_SIZE);
        let prelude = prelude.as_bytes();

        // This should never happen because MAX_CHUNK_SIZE of u32::MAX
        // can always be encoded in 4 hex bytes.
        assert!(HEADER_SIZE <= prelude.len(), "invariant failed: prelude longer than HEADER_SIZE");

        // Copy the prelude into the buffer. For small chunks, this won't necessarily
        // take up all the space that was reserved for the prelude.
        let offset = HEADER_SIZE - prelude.len();
        self.buffer[offset..HEADER_SIZE].clone_from_slice(&prelude);

        // Append the chunk-finishing \r\n to the buffer.
        self.buffer.write_all(b"\r\n")?;

        self.output.write_all(&self.buffer[offset..])?;
        self.reset_buffer();

        Ok(())
    }
}

impl<W> Write for Encoder<W>
where
    W: Write,
{
    fn write(&mut self, data: &[u8]) -> IoResult<usize> {
        let buffer_size = self.buffer.len() - HEADER_SIZE;
        let remaining_buffer_space = self.chunks_size - buffer_size;
        let bytes_to_buffer = std::cmp::min(remaining_buffer_space, data.len());
        self.buffer.extend_from_slice(&data[0..bytes_to_buffer]);
        let more_to_write: bool = bytes_to_buffer < data.len();
        if self.flush_after_write || more_to_write {
            self.send()?;
        }

        // If we didn't write the whole thing, keep working on it.
        if more_to_write {
            self.write_all(&data[bytes_to_buffer..])?;
        }
        Ok(data.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        self.send()
    }
}

impl<W> Drop for Encoder<W>
where
    W: Write,
{
    fn drop(&mut self) {
        self.flush().ok();
        write!(self.output, "0\r\n\r\n").ok();
    }
}

#[cfg(test)]
mod test {
    use super::Encoder;
    use std::io;
    use std::io::Write;
    use std::str::from_utf8;

    #[test]
    fn test() {
        let mut source = io::Cursor::new("hello world".to_string().into_bytes());
        let mut dest: Vec<u8> = vec![];

        {
            let mut encoder = Encoder::with_chunks_size(dest.by_ref(), 5);
            io::copy(&mut source, &mut encoder).unwrap();
            assert!(!encoder.is_buffer_empty());
        }

        let output = from_utf8(&dest).unwrap();

        assert_eq!(output, "5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n");
    }
    #[test]
    fn flush_after_write() {
        let mut source = io::Cursor::new("hello world".to_string().into_bytes());
        let mut dest: Vec<u8> = vec![];

        {
            let mut encoder = Encoder::with_flush_after_write(dest.by_ref());
            io::copy(&mut source, &mut encoder).unwrap();
            // The internal buffer has been flushed.
            assert!(encoder.is_buffer_empty());
        }

        let output = from_utf8(&dest).unwrap();

        assert_eq!(output, "b\r\nhello world\r\n0\r\n\r\n");
    }
}
<commit_msg>Rename header constant; add helper method to find size of buffer data<commit_after>// Copyright 2015 The tiny-http Contributors
// Copyright 2015 The rust-chunked-transfer Contributors
//
// 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.

use std::io::Result as IoResult;
use std::io::Write;

/// Splits the incoming data into HTTP chunks.
///
/// # Example
///
/// ```
/// use chunked_transfer::Encoder;
/// use std::io::Write;
///
/// let mut decoded = "hello world";
/// let mut encoded: Vec<u8> = vec![];
///
/// {
///     let mut encoder = Encoder::with_chunks_size(&mut encoded, 5);
///     encoder.write_all(decoded.as_bytes());
/// }
///
/// assert_eq!(encoded, b"5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n");
/// ```
pub struct Encoder<W>
where
    W: Write,
{
    // where to send the result
    output: W,

    // size of each chunk
    chunks_size: usize,

    // data waiting to be sent is stored here
    // This will always be at least 6 bytes long. The first 6 bytes
    // are reserved for the chunk size and \r\n.
    buffer: Vec<u8>,

    // Flushes the internal buffer after each write. This might be useful
    // if data should be sent immediately to downstream consumers
    flush_after_write: bool,
}

const MAX_CHUNK_SIZE: usize = std::u32::MAX as usize;
const PLACEHOLDER_HEADER_SIZE: usize = 6;

impl<W> Encoder<W>
where
    W: Write,
{
    pub fn new(output: W) -> Encoder<W> {
        Encoder::with_chunks_size(output, 8192)
    }

    pub fn with_chunks_size(output: W, chunks: usize) -> Encoder<W> {
        let chunks_size = chunks.min(MAX_CHUNK_SIZE);
        let mut encoder = Encoder {
            output,
            chunks_size,
            buffer: Vec::with_capacity(0),
            flush_after_write: false,
        };
        encoder.reset_buffer();
        encoder
    }

    pub fn with_flush_after_write(output: W) -> Encoder<W> {
        let mut encoder = Encoder {
            output,
            chunks_size: 8192,
            buffer: Vec::with_capacity(0),
            flush_after_write: true,
        };
        encoder.reset_buffer();
        encoder
    }

    fn reset_buffer(&mut self) {
        // Reset buffer
        self.buffer.clear();
        // Arbitrary bytes to take up space. Should never be seen in output.
        let placeholder: [u8; PLACEHOLDER_HEADER_SIZE] = *b"DACE\r\n";
        self.buffer.extend_from_slice(&placeholder);
    }

    fn is_buffer_empty(&self) -> bool {
        self.buffer.len() == PLACEHOLDER_HEADER_SIZE
    }

    fn buffer_len(&self) -> usize {
        self.buffer.len() - PLACEHOLDER_HEADER_SIZE
    }

    fn send(&mut self) -> IoResult<()> {
        // Never send an empty buffer, because that would be interpreted
        // as the end of the stream, which we indicate explicitly on drop.
        if self.is_buffer_empty() {
            return Ok(());
        }
        // Prepend the length and \r\n to the buffer.
        let prelude = format!("{:x}\r\n", self.buffer_len());
        let prelude = prelude.as_bytes();

        // This should never happen because MAX_CHUNK_SIZE of u32::MAX
        // can always be encoded in 4 hex bytes.
        assert!(PLACEHOLDER_HEADER_SIZE <= prelude.len(), "invariant failed: prelude longer than PLACEHOLDER_HEADER_SIZE");

        // Copy the prelude into the buffer. For small chunks, this won't necessarily
        // take up all the space that was reserved for the prelude.
        let offset = PLACEHOLDER_HEADER_SIZE - prelude.len();
        self.buffer[offset..PLACEHOLDER_HEADER_SIZE].clone_from_slice(&prelude);

        // Append the chunk-finishing \r\n to the buffer.
        self.buffer.write_all(b"\r\n")?;

        self.output.write_all(&self.buffer[offset..])?;
        self.reset_buffer();

        Ok(())
    }
}

impl<W> Write for Encoder<W>
where
    W: Write,
{
    fn write(&mut self, data: &[u8]) -> IoResult<usize> {
        let remaining_buffer_space = self.chunks_size - self.buffer_len();
        let bytes_to_buffer = std::cmp::min(remaining_buffer_space, data.len());
        self.buffer.extend_from_slice(&data[0..bytes_to_buffer]);
        let more_to_write: bool = bytes_to_buffer < data.len();
        if self.flush_after_write || more_to_write {
            self.send()?;
        }

        // If we didn't write the whole thing, keep working on it.
        if more_to_write {
            self.write_all(&data[bytes_to_buffer..])?;
        }
        Ok(data.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        self.send()
    }
}

impl<W> Drop for Encoder<W>
where
    W: Write,
{
    fn drop(&mut self) {
        self.flush().ok();
        write!(self.output, "0\r\n\r\n").ok();
    }
}

#[cfg(test)]
mod test {
    use super::Encoder;
    use std::io;
    use std::io::Write;
    use std::str::from_utf8;

    #[test]
    fn test() {
        let mut source = io::Cursor::new("hello world".to_string().into_bytes());
        let mut dest: Vec<u8> = vec![];

        {
            let mut encoder = Encoder::with_chunks_size(dest.by_ref(), 5);
            io::copy(&mut source, &mut encoder).unwrap();
            assert!(!encoder.is_buffer_empty());
        }

        let output = from_utf8(&dest).unwrap();

        assert_eq!(output, "5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n");
    }
    #[test]
    fn flush_after_write() {
        let mut source = io::Cursor::new("hello world".to_string().into_bytes());
        let mut dest: Vec<u8> = vec![];

        {
            let mut encoder = Encoder::with_flush_after_write(dest.by_ref());
            io::copy(&mut source, &mut encoder).unwrap();
            // The internal buffer has been flushed.
            assert!(encoder.is_buffer_empty());
        }

        let output = from_utf8(&dest).unwrap();

        assert_eq!(output, "b\r\nhello world\r\n0\r\n\r\n");
    }
}
<|endoftext|>


<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

#[inline]
fn header_parser(input: &[u8]) -> IResult<&[u8], &[u8], ErrorKind> {
  tag!(input, "fLaC").map_err(to_custom_error!(HeaderParser))
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parse!(slice, header_parser);

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<commit_msg>Inline the header_parser<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<|endoftext|>


<commit_before>use result::NSSResult;
use ffi::nspr;
use ffi::nspr::PRBool;
use libc::{c_uint, c_uchar};
use std::{mem, ptr};
use std::marker::ContravariantLifetime;

#[must_use]
#[repr(C)]
#[allow(dead_code)] // List all available options
pub enum SECStatus
{
    WouldBlock = -2,
    Failure = -1,
    Success = 0
}

impl SECStatus
{
    pub fn to_result(&self) -> ::result::NSSResult<()>
    {
        match *self
        {
            SECStatus::Success => Ok(()),
            SECStatus::Failure => Err(nspr::get_error_code()),
            SECStatus::WouldBlock => panic!("Unexpectedly got SECWouldBlock"),
        }
    }
}

#[repr(C)]
#[allow(dead_code)] // We just list all available in NSS
enum SECItemType
{
    Buffer = 0,
    ClearDataBuffer = 1,
    CipherDataBuffer = 2,
    DERCertBuffer = 3,
    EncodedCertBuffer = 4,
    DERNameBuffer = 5,
    EncodedNameBuffer = 6,
    AsciiNameString = 7,
    AsciiString = 8,
    DEROID = 9,
    UnsignedInteger = 10,
    UTCTime = 11,
    GeneralizedTime = 12,
    VisibleString = 13,
    UTF8String = 14,
    BMPString = 15,
}

#[repr(C)]
pub struct SECItemFFI
{
    typ: SECItemType,
    data: *const c_uchar,
    len: c_uint,
}

pub enum SECItem<'a>
{
    Boxed(*mut SECItemFFI),
    Data(SECItemFFI, ContravariantLifetime<'a>)
}

impl SECItem<'static>
{
    pub fn wrap(data: *mut SECItemFFI) -> NSSResult<SECItem<'static>>
    {
        match data.is_null()
        {
            true => Err(nspr::get_error_code()),
            false => Ok(SECItem::Boxed(data)),
        }
    }

    pub fn empty() -> SECItem<'static>
    {
        SECItem::Data(SECItemFFI {
            typ: SECItemType::Buffer,
            data: ptr::null(),
            len: 0,
        }, ContravariantLifetime)
    }
}

impl<'a> SECItem<'a>
{
    pub fn from_buf(buffer: &'a [u8]) -> SECItem<'a>
    {
        let si = SECItemFFI
        {
            typ: SECItemType::Buffer,
            data: buffer.as_ptr(),
            len: buffer.len() as c_uint,
        };
        SECItem::Data(si, ContravariantLifetime)
    }

    pub fn from_struct<T>(data: &'a T) -> SECItem<'a>
    {
        let len = mem::size_of::<T>() as c_uint;
        let ptr = match len
        {
            0 => ptr::null(),
            _ => unsafe { mem::transmute(data) },
        };
        let si = SECItemFFI
        {
            typ: SECItemType::Buffer,
            data: ptr,
            len: len,
        };
        SECItem::Data(si, ContravariantLifetime)
    }

    pub fn get<'b>(&'b self) -> &'b SECItemFFI
    {
        match *self
        {
            SECItem::Boxed(ptr) => unsafe { ptr.as_ref().unwrap() },
            SECItem::Data(ref si, _) => si,
        }
    }

    pub fn get_mut<'b>(&'b mut self) -> &'b mut SECItemFFI
    {
        match *self
        {
            SECItem::Boxed(ptr) => unsafe { ptr.as_mut().unwrap() },
            SECItem::Data(ref mut si, _) => si,
        }
    }

    pub fn copy_buf(&self) -> Vec<u8>
    {
        let si = self.get();
        let buf : &[u8] = unsafe { ::std::slice::from_raw_buf(&si.data, si.len as usize) };
        buf.to_vec()
    }
}

#[unsafe_destructor]
impl<'a> Drop for SECItem<'a>
{
    fn drop(&mut self)
    {
        match *self
        {
            SECItem::Boxed(ptr) => unsafe { SECITEM_FreeItem(ptr, PRBool::True) },
            _ => {},
        }
    }
}

#[link(name="nss3")]
extern "C"
{
    fn SECITEM_FreeItem(item: *mut SECItemFFI, freeitem: PRBool);
}
<commit_msg>from_raw_buf -> from_raw_parts<commit_after>use result::NSSResult;
use ffi::nspr;
use ffi::nspr::PRBool;
use libc::{c_uint, c_uchar};
use std::{mem, ptr};
use std::marker::ContravariantLifetime;

#[must_use]
#[repr(C)]
#[allow(dead_code)] // List all available options
pub enum SECStatus
{
    WouldBlock = -2,
    Failure = -1,
    Success = 0
}

impl SECStatus
{
    pub fn to_result(&self) -> ::result::NSSResult<()>
    {
        match *self
        {
            SECStatus::Success => Ok(()),
            SECStatus::Failure => Err(nspr::get_error_code()),
            SECStatus::WouldBlock => panic!("Unexpectedly got SECWouldBlock"),
        }
    }
}

#[repr(C)]
#[allow(dead_code)] // We just list all available in NSS
enum SECItemType
{
    Buffer = 0,
    ClearDataBuffer = 1,
    CipherDataBuffer = 2,
    DERCertBuffer = 3,
    EncodedCertBuffer = 4,
    DERNameBuffer = 5,
    EncodedNameBuffer = 6,
    AsciiNameString = 7,
    AsciiString = 8,
    DEROID = 9,
    UnsignedInteger = 10,
    UTCTime = 11,
    GeneralizedTime = 12,
    VisibleString = 13,
    UTF8String = 14,
    BMPString = 15,
}

#[repr(C)]
pub struct SECItemFFI
{
    typ: SECItemType,
    data: *const c_uchar,
    len: c_uint,
}

pub enum SECItem<'a>
{
    Boxed(*mut SECItemFFI),
    Data(SECItemFFI, ContravariantLifetime<'a>)
}

impl SECItem<'static>
{
    pub fn wrap(data: *mut SECItemFFI) -> NSSResult<SECItem<'static>>
    {
        match data.is_null()
        {
            true => Err(nspr::get_error_code()),
            false => Ok(SECItem::Boxed(data)),
        }
    }

    pub fn empty() -> SECItem<'static>
    {
        SECItem::Data(SECItemFFI {
            typ: SECItemType::Buffer,
            data: ptr::null(),
            len: 0,
        }, ContravariantLifetime)
    }
}

impl<'a> SECItem<'a>
{
    pub fn from_buf(buffer: &'a [u8]) -> SECItem<'a>
    {
        let si = SECItemFFI
        {
            typ: SECItemType::Buffer,
            data: buffer.as_ptr(),
            len: buffer.len() as c_uint,
        };
        SECItem::Data(si, ContravariantLifetime)
    }

    pub fn from_struct<T>(data: &'a T) -> SECItem<'a>
    {
        let len = mem::size_of::<T>() as c_uint;
        let ptr = match len
        {
            0 => ptr::null(),
            _ => unsafe { mem::transmute(data) },
        };
        let si = SECItemFFI
        {
            typ: SECItemType::Buffer,
            data: ptr,
            len: len,
        };
        SECItem::Data(si, ContravariantLifetime)
    }

    pub fn get<'b>(&'b self) -> &'b SECItemFFI
    {
        match *self
        {
            SECItem::Boxed(ptr) => unsafe { ptr.as_ref().unwrap() },
            SECItem::Data(ref si, _) => si,
        }
    }

    pub fn get_mut<'b>(&'b mut self) -> &'b mut SECItemFFI
    {
        match *self
        {
            SECItem::Boxed(ptr) => unsafe { ptr.as_mut().unwrap() },
            SECItem::Data(ref mut si, _) => si,
        }
    }

    pub fn copy_buf(&self) -> Vec<u8>
    {
        let si = self.get();
        let buf : &[u8] = unsafe { ::std::slice::from_raw_parts(si.data, si.len as usize) };
        buf.to_vec()
    }
}

#[unsafe_destructor]
impl<'a> Drop for SECItem<'a>
{
    fn drop(&mut self)
    {
        match *self
        {
            SECItem::Boxed(ptr) => unsafe { SECITEM_FreeItem(ptr, PRBool::True) },
            _ => {},
        }
    }
}

#[link(name="nss3")]
extern "C"
{
    fn SECITEM_FreeItem(item: *mut SECItemFFI, freeitem: PRBool);
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]

#[macro_use] extern crate bitflags;

extern crate fsevent_sys as fsevent;
extern crate libc;

use fsevent::core_foundation as cf;
use fsevent::fsevent as fs;

use std::ptr;
use std::slice;
use std::slice::from_raw_parts_mut;
use std::str::from_utf8;
use std::ffi::CStr;
use std::convert::AsRef;

use std::sync::mpsc::{Sender};

pub const NULL: cf::CFRef = cf::NULL;

pub struct FsEvent {
  paths: cf::CFMutableArrayRef,
  since_when: fs::FSEventStreamEventId,
  latency: cf::CFTimeInterval,
  flags: fs::FSEventStreamCreateFlags,
  sender: Sender<Event>,
}

#[derive(Debug)]
pub struct Event {
  pub event_id: u64,
  pub flag: StreamFlags,
  pub path: String,
}

pub type FsEventCallback = fn(Vec<Event>);

// Synchronize with
// /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/Headers/FSEvents.h
bitflags! {
  #[repr(C)]
  pub struct StreamFlags: u32 {
    const NONE = 0x00000000;
    const MUST_SCAN_SUBDIRS = 0x00000001;
    const USER_DROPPED = 0x00000002;
    const KERNEL_DROPPED = 0x00000004;
    const IDS_WRAPPED = 0x00000008;
    const HISTORY_DONE = 0x00000010;
    const ROOT_CHANGED = 0x00000020;
    const MOUNT = 0x00000040;
    const UNMOUNT = 0x00000080;
    const ITEM_CREATED = 0x00000100;
    const ITEM_REMOVED = 0x00000200;
    const INOTE_META_MOD = 0x00000400;
    const ITEM_RENAMED = 0x00000800;
    const ITEM_MODIFIED = 0x00001000;
    const FINDER_INFO_MOD = 0x00002000;
    const ITEM_CHANGE_OWNER = 0x00004000;
    const ITEM_XATTR_MOD = 0x00008000;
    const IS_FILE = 0x00010000;
    const IS_DIR = 0x00020000;
    const IS_SYMLIMK = 0x00040000;
    const OWN_EVENT = 0x00080000;
    const IS_HARDLINK = 0x00100000;
    const IS_LAST_HARDLINK = 0x00200000;
    const ITEM_CLONED = 0x400000;
  }
}

impl std::fmt::Display for StreamFlags {
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    if self.contains(StreamFlags::MUST_SCAN_SUBDIRS) {
      let _d = write!(f, "MUST_SCAN_SUBDIRS ");
    }
    if self.contains(StreamFlags::USER_DROPPED) {
      let _d = write!(f, "USER_DROPPED ");
    }
    if self.contains(StreamFlags::KERNEL_DROPPED) {
      let _d = write!(f, "KERNEL_DROPPED ");
    }
    if self.contains(StreamFlags::IDS_WRAPPED) {
      let _d = write!(f, "IDS_WRAPPED ");
    }
    if self.contains(StreamFlags::HISTORY_DONE) {
      let _d = write!(f, "HISTORY_DONE ");
    }
    if self.contains(StreamFlags::ROOT_CHANGED) {
      let _d = write!(f, "ROOT_CHANGED ");
    }
    if self.contains(StreamFlags::MOUNT) {
      let _d = write!(f, "MOUNT ");
    }
    if self.contains(StreamFlags::UNMOUNT) {
      let _d = write!(f, "UNMOUNT ");
    }
    if self.contains(StreamFlags::ITEM_CREATED) {
      let _d = write!(f, "ITEM_CREATED ");
    }
    if self.contains(StreamFlags::ITEM_REMOVED) {
      let _d = write!(f, "ITEM_REMOVED ");
    }
    if self.contains(StreamFlags::INOTE_META_MOD) {
      let _d = write!(f, "INOTE_META_MOD ");
    }
    if self.contains(StreamFlags::ITEM_RENAMED) {
      let _d = write!(f, "ITEM_RENAMED ");
    }
    if self.contains(StreamFlags::ITEM_MODIFIED) {
      let _d = write!(f, "ITEM_MODIFIED ");
    }
    if self.contains(StreamFlags::FINDER_INFO_MOD) {
      let _d = write!(f, "FINDER_INFO_MOD ");
    }
    if self.contains(StreamFlags::ITEM_CHANGE_OWNER) {
      let _d = write!(f, "ITEM_CHANGE_OWNER ");
    }
    if self.contains(StreamFlags::ITEM_XATTR_MOD) {
      let _d = write!(f, "ITEM_XATTR_MOD ");
    }
    if self.contains(StreamFlags::IS_FILE) {
      let _d = write!(f, "IS_FILE ");
    }
    if self.contains(StreamFlags::IS_DIR) {
      let _d = write!(f, "IS_DIR ");
    }
    if self.contains(StreamFlags::IS_SYMLIMK) {
      let _d = write!(f, "IS_SYMLIMK ");
    }
    if self.contains(StreamFlags::OWN_EVENT) {
      let _d = write!(f, "OWN_EVENT ");
    }
    if self.contains(StreamFlags::IS_LAST_HARDLINK) {
      let _d = write!(f, "IS_LAST_HARDLINK ");
    }
    if self.contains(StreamFlags::IS_HARDLINK) {
      let _d = write!(f, "IS_HARDLINK ");
    }
    if self.contains(StreamFlags::ITEM_CLONED) {
      let
      _d = write!(f, "ITEM_CLONED ");
    }
    write!(f, "")
  }
}

pub fn is_api_available() -> (bool, String) {
  let ma = cf::system_version_major();
  let mi = cf::system_version_minor();

  if ma == 10 && mi < 5 {
    (false, "This version of OSX does not support the FSEvent library, cannot proceed".to_string())
  } else {
    (true, "ok".to_string())
  }
}

fn default_stream_context(info: *const FsEvent) -> fs::FSEventStreamContext {
  let ptr = info as *mut libc::c_void;
  fs::FSEventStreamContext {
    version: 0,
    info: ptr,
    retain: cf::NULL,
    copy_description: cf::NULL
  }
}

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

#[derive(Debug)]
pub struct Error {
    msg: String,
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        &self.msg
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.msg.fmt(f)
    }
}

impl FsEvent {
  pub fn new(sender: Sender<Event>) -> FsEvent {
    let fsevent: FsEvent;

    unsafe {
      fsevent = FsEvent{
        paths: cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks),
        since_when: fs::kFSEventStreamEventIdSinceNow,
        latency: 0.0,
        flags: fs::kFSEventStreamCreateFlagFileEvents | fs::kFSEventStreamCreateFlagNoDefer,
        sender: sender,
      };
    }
    fsevent
  }

  // https://github.com/thibaudgg/rb-fsevent/blob/master/ext/fsevent_watch/main.c
  pub fn append_path(&self,source: &str) -> Result<()> {
    unsafe {
      let mut err = ptr::null_mut();
      let cf_path = cf::str_path_to_cfstring_ref(source, &mut err);
      if !err.is_null() {
          let cf_str = cf::CFCopyDescription(err as cf::CFRef);
          let mut buf = [0; 1024];
          cf::CFStringGetCString(cf_str, buf.as_mut_ptr(), buf.len() as cf::CFIndex, cf::kCFStringEncodingUTF8);
          Err(Error { msg: CStr::from_ptr(buf.as_ptr()).to_str().unwrap_or("Unknown error").to_string() })
      } else {
          cf::CFArrayAppendValue(self.paths, cf_path);
          cf::CFRelease(cf_path);
          Ok(())
      }
    }
  }
  pub fn observe(&self) {
    let stream_context = default_stream_context(self);

    let cb = callback as *mut _;

    unsafe {
      let stream = fs::FSEventStreamCreate(cf::kCFAllocatorDefault,
       cb,
       &stream_context,
       self.paths,
       self.since_when,
       self.latency,
       self.flags);

      // fs::FSEventStreamShow(stream);

      fs::FSEventStreamScheduleWithRunLoop(stream,
        cf::CFRunLoopGetCurrent(),
        cf::kCFRunLoopDefaultMode);

      fs::FSEventStreamStart(stream);
      cf::CFRunLoopRun();

      fs::FSEventStreamFlushSync(stream);
      fs::FSEventStreamStop(stream);

    }
  }
}

#[allow(unused_variables)]
pub fn callback(
    stream_ref: fs::FSEventStreamRef,
    info: *mut libc::c_void,
    num_events: libc::size_t,      // size_t numEvents
    event_paths: *const *const libc::c_char, // void *eventPaths
    event_flags: *mut libc::c_void, // const FSEventStreamEventFlags eventFlags[]
    event_ids: *mut libc::c_void,  // const FSEventStreamEventId eventIds[]
  ) {
  let num = num_events as usize;
  let e_ptr = event_flags as *mut u32;
  let i_ptr = event_ids as *mut u64;
  let fs_event = info as *mut FsEvent;

  unsafe {
    let paths: &[*const libc::c_char] = std::mem::transmute(slice::from_raw_parts(event_paths, num));
    let flags = from_raw_parts_mut(e_ptr, num);
    let ids = from_raw_parts_mut(i_ptr, num);

    for p in 0..num {
      let i = CStr::from_ptr(paths[p]).to_bytes();
      let path = from_utf8(i).ok().expect("Invalid UTF8 string.");
      let flag: StreamFlags = StreamFlags::from_bits(flags[p] as u32)
      .expect(format!("Unable to decode StreamFlags: {} for {}", flags[p] as u32, path).as_ref());
      // println!("{}: {}", ids[p], flag);

      let event = Event{event_id: ids[p], flag: flag, path: path.to_string()};
      let _s = (*fs_event).sender.send(event);
    }
  }
}
<commit_msg>clippy: Call expect directly on the Result.<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]

#[macro_use] extern crate bitflags;

extern crate fsevent_sys as fsevent;
extern crate libc;

use fsevent::core_foundation as cf;
use fsevent::fsevent as fs;

use std::ptr;
use std::slice;
use std::slice::from_raw_parts_mut;
use std::str::from_utf8;
use std::ffi::CStr;
use std::convert::AsRef;

use std::sync::mpsc::{Sender};

pub const NULL: cf::CFRef = cf::NULL;

pub struct FsEvent {
  paths: cf::CFMutableArrayRef,
  since_when: fs::FSEventStreamEventId,
  latency: cf::CFTimeInterval,
  flags: fs::FSEventStreamCreateFlags,
  sender: Sender<Event>,
}

#[derive(Debug)]
pub struct Event {
  pub event_id: u64,
  pub flag: StreamFlags,
  pub path: String,
}

pub type FsEventCallback = fn(Vec<Event>);

// Synchronize with
// /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/Headers/FSEvents.h
bitflags! {
  #[repr(C)]
  pub struct StreamFlags: u32 {
    const NONE = 0x00000000;
    const MUST_SCAN_SUBDIRS = 0x00000001;
    const USER_DROPPED = 0x00000002;
    const KERNEL_DROPPED = 0x00000004;
    const IDS_WRAPPED = 0x00000008;
    const HISTORY_DONE = 0x00000010;
    const ROOT_CHANGED = 0x00000020;
    const MOUNT = 0x00000040;
    const UNMOUNT = 0x00000080;
    const ITEM_CREATED = 0x00000100;
    const ITEM_REMOVED = 0x00000200;
    const INOTE_META_MOD = 0x00000400;
    const ITEM_RENAMED = 0x00000800;
    const ITEM_MODIFIED = 0x00001000;
    const FINDER_INFO_MOD = 0x00002000;
    const ITEM_CHANGE_OWNER = 0x00004000;
    const ITEM_XATTR_MOD = 0x00008000;
    const IS_FILE = 0x00010000;
    const IS_DIR = 0x00020000;
    const IS_SYMLIMK = 0x00040000;
    const OWN_EVENT = 0x00080000;
    const IS_HARDLINK = 0x00100000;
    const IS_LAST_HARDLINK = 0x00200000;
    const ITEM_CLONED = 0x400000;
  }
}

impl std::fmt::Display for StreamFlags {
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    if self.contains(StreamFlags::MUST_SCAN_SUBDIRS) {
      let _d = write!(f, "MUST_SCAN_SUBDIRS ");
    }
    if self.contains(StreamFlags::USER_DROPPED) {
      let _d = write!(f, "USER_DROPPED ");
    }
    if self.contains(StreamFlags::KERNEL_DROPPED) {
      let _d = write!(f, "KERNEL_DROPPED ");
    }
    if self.contains(StreamFlags::IDS_WRAPPED) {
      let _d = write!(f, "IDS_WRAPPED ");
    }
    if self.contains(StreamFlags::HISTORY_DONE) {
      let _d = write!(f, "HISTORY_DONE ");
    }
    if self.contains(StreamFlags::ROOT_CHANGED) {
      let _d = write!(f, "ROOT_CHANGED ");
    }
    if self.contains(StreamFlags::MOUNT) {
      let _d = write!(f, "MOUNT ");
    }
    if self.contains(StreamFlags::UNMOUNT) {
      let _d = write!(f, "UNMOUNT ");
    }
    if self.contains(StreamFlags::ITEM_CREATED) {
      let _d = write!(f, "ITEM_CREATED ");
    }
    if self.contains(StreamFlags::ITEM_REMOVED) {
      let _d = write!(f, "ITEM_REMOVED ");
    }
    if self.contains(StreamFlags::INOTE_META_MOD) {
      let _d = write!(f, "INOTE_META_MOD ");
    }
    if self.contains(StreamFlags::ITEM_RENAMED) {
      let _d = write!(f, "ITEM_RENAMED ");
    }
    if self.contains(StreamFlags::ITEM_MODIFIED) {
      let _d = write!(f, "ITEM_MODIFIED ");
    }
    if self.contains(StreamFlags::FINDER_INFO_MOD) {
      let _d = write!(f, "FINDER_INFO_MOD ");
    }
    if self.contains(StreamFlags::ITEM_CHANGE_OWNER) {
      let _d = write!(f, "ITEM_CHANGE_OWNER ");
    }
    if self.contains(StreamFlags::ITEM_XATTR_MOD) {
      let _d = write!(f, "ITEM_XATTR_MOD ");
    }
    if self.contains(StreamFlags::IS_FILE) {
      let _d = write!(f, "IS_FILE ");
    }
    if self.contains(StreamFlags::IS_DIR) {
      let _d = write!(f, "IS_DIR ");
    }
    if self.contains(StreamFlags::IS_SYMLIMK) {
      let _d = write!(f, "IS_SYMLIMK ");
    }
    if self.contains(StreamFlags::OWN_EVENT) {
      let _d = write!(f, "OWN_EVENT ");
    }
    if self.contains(StreamFlags::IS_LAST_HARDLINK) {
      let _d = write!(f, "IS_LAST_HARDLINK ");
    }
    if self.contains(StreamFlags::IS_HARDLINK) {
      let _d = write!(f, "IS_HARDLINK ");
    }
    if self.contains(StreamFlags::ITEM_CLONED) {
      let
      _d = write!(f, "ITEM_CLONED ");
    }
    write!(f, "")
  }
}

pub fn is_api_available() -> (bool, String) {
  let ma = cf::system_version_major();
  let mi = cf::system_version_minor();

  if ma == 10 && mi < 5 {
    (false, "This version of OSX does not support the FSEvent library, cannot proceed".to_string())
  } else {
    (true, "ok".to_string())
  }
}

fn default_stream_context(info: *const FsEvent) -> fs::FSEventStreamContext {
  let ptr = info as *mut libc::c_void;
  fs::FSEventStreamContext {
    version: 0,
    info: ptr,
    retain: cf::NULL,
    copy_description: cf::NULL
  }
}

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

#[derive(Debug)]
pub struct Error {
    msg: String,
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        &self.msg
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.msg.fmt(f)
    }
}

impl FsEvent {
  pub fn new(sender: Sender<Event>) -> FsEvent {
    let fsevent: FsEvent;

    unsafe {
      fsevent = FsEvent{
        paths: cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks),
        since_when: fs::kFSEventStreamEventIdSinceNow,
        latency: 0.0,
        flags: fs::kFSEventStreamCreateFlagFileEvents | fs::kFSEventStreamCreateFlagNoDefer,
        sender: sender,
      };
    }
    fsevent
  }

  // https://github.com/thibaudgg/rb-fsevent/blob/master/ext/fsevent_watch/main.c
  pub fn append_path(&self,source: &str) -> Result<()> {
    unsafe {
      let mut err = ptr::null_mut();
      let cf_path = cf::str_path_to_cfstring_ref(source, &mut err);
      if !err.is_null() {
          let cf_str = cf::CFCopyDescription(err as cf::CFRef);
          let mut buf = [0; 1024];
          cf::CFStringGetCString(cf_str, buf.as_mut_ptr(), buf.len() as cf::CFIndex, cf::kCFStringEncodingUTF8);
          Err(Error { msg: CStr::from_ptr(buf.as_ptr()).to_str().unwrap_or("Unknown error").to_string() })
      } else {
          cf::CFArrayAppendValue(self.paths, cf_path);
          cf::CFRelease(cf_path);
          Ok(())
      }
    }
  }
  pub fn observe(&self) {
    let stream_context = default_stream_context(self);

    let cb = callback as *mut _;

    unsafe {
      let stream = fs::FSEventStreamCreate(cf::kCFAllocatorDefault,
       cb,
       &stream_context,
       self.paths,
       self.since_when,
       self.latency,
       self.flags);

      // fs::FSEventStreamShow(stream);

      fs::FSEventStreamScheduleWithRunLoop(stream,
        cf::CFRunLoopGetCurrent(),
        cf::kCFRunLoopDefaultMode);

      fs::FSEventStreamStart(stream);
      cf::CFRunLoopRun();

      fs::FSEventStreamFlushSync(stream);
      fs::FSEventStreamStop(stream);

    }
  }
}

#[allow(unused_variables)]
pub fn callback(
    stream_ref: fs::FSEventStreamRef,
    info: *mut libc::c_void,
    num_events: libc::size_t,      // size_t numEvents
    event_paths: *const *const libc::c_char, // void *eventPaths
    event_flags: *mut libc::c_void, // const FSEventStreamEventFlags eventFlags[]
    event_ids: *mut libc::c_void,  // const FSEventStreamEventId eventIds[]
  ) {
  let num = num_events as usize;
  let e_ptr = event_flags as *mut u32;
  let i_ptr = event_ids as *mut u64;
  let fs_event = info as *mut FsEvent;

  unsafe {
    let paths: &[*const libc::c_char] = std::mem::transmute(slice::from_raw_parts(event_paths, num));
    let flags = from_raw_parts_mut(e_ptr, num);
    let ids = from_raw_parts_mut(i_ptr, num);

    for p in 0..num {
      let i = CStr::from_ptr(paths[p]).to_bytes();
      let path = from_utf8(i).expect("Invalid UTF8 string.");
      let flag: StreamFlags = StreamFlags::from_bits(flags[p] as u32)
      .expect(format!("Unable to decode StreamFlags: {} for {}", flags[p] as u32, path).as_ref());
      // println!("{}: {}", ids[p], flag);

      let event = Event{event_id: ids[p], flag: flag, path: path.to_string()};
      let _s = (*fs_event).sender.send(event);
    }
  }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;

use gbe::memory::MMU;
use gbe::registers::*;

#[derive(Debug)]
pub struct CPU {
    pub reg: Registers,
    pub mem: Rc<RefCell<MMU>>,
}

impl CPU {
    pub fn new() -> CPU {

        let r = Registers {
            af: Register16::new(0),
            bc: Register16::new(0),
            de: Register16::new(0),
            hl: Register16::new(0),
            pc: Register16::new(0),
            sp: Register16::new(0),
        };

        // TODO: this should be created only once and cloned for every struct
        let mmu = Rc::new(RefCell::new(MMU::new()));

        CPU { reg: r, mem: mmu }
    }

    /// executes the instruction
    pub fn dispatch(&mut self, opcode: u8) {}

    /// reads instructions and executes them
    pub fn fetch_and_exec() {
        let mut cpu = CPU::new();

        loop {
            // fetch
            // the block is needed so that the borrow of cpu.memory ends
            // before dispatch, which will mutably borrow cpu
            let opcode = {
                let mem = cpu.mem.borrow();
                mem.read_b(cpu.reg.pc.get())
            };

            // execute
            cpu.dispatch(opcode);
            // increase PC
            cpu.reg.pc.add(1);
            // TODO: compute clock timings
        }
    }

    pub fn LD_nn_n(reg1: &mut Register8, value: u8) {
        reg1.set(value);
    }

    // Computes the flags and result for an ADD instruction.
    pub fn compute_add(&mut self, lhs: u8, rhs: u8) {
        let result = lhs.wrapping_add(rhs);

        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        // checked add returns None if add overflows
        if let None = lhs.checked_add(rhs) {
            self.reg.set_flag(Flags::Carry);
        }

        let low_result = (rhs & 0x0F) + (lhs & 0x0F);
        // check if bit 4 is set
        if (low_result >> 4) == 1 {
            self.reg.set_flag(Flags::HalfCarry);
        }

        self.reg.af.high.set(result);
    }

    // Computes the flags and result for a SUB instruction.
    pub fn compute_sub(&mut self, lhs: u8, rhs: u8)  {
        let result = lhs.wrapping_sub(rhs);

        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.set_flag(Flags::Sub);

        // checked sub returns None if sub borrows (carry flag)
        if let None = lhs.checked_sub(rhs) {
            self.reg.set_flag(Flags::Carry);
        }

        // same as carry flag but values limited to their 4 low bits (half carry flag)
        if let None = (lhs & 0xF).checked_sub(rhs & 0xF) {
            self.reg.set_flag(Flags::HalfCarry);
        }

        self.reg.af.high.set(result);
    }

    // Computes the flags for a CP instruction.
    // this has the same effect as a SUB, but the result discarded.
    pub fn compute_cp(&mut self, lhs: u8, rhs: u8)  {
        let result = lhs.wrapping_sub(rhs);

        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.set_flag(Flags::Sub);

        if let None = lhs.checked_sub(rhs) {
            self.reg.set_flag(Flags::Carry);
        }

        if let None = (lhs & 0xF).checked_sub(rhs & 0xF) {
            self.reg.set_flag(Flags::HalfCarry);
        }
    }

    // Computes the flags and result for an AND instruction.
    // lhs is always the register A
    pub fn compute_and(&mut self, rhs: u8) {
        let result = self.reg.af.high.get() & rhs;

        // HC flag is always set, other flags always cleared except zero.
        self.reg.clear_all_flags();
        self.reg.set_flag(Flags::HalfCarry);

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.af.high.set(result);
    }

    // Computes the flags and result for an OR instruction.
    // lhs is always the register A
    pub fn compute_or(&mut self, rhs: u8) {
        let result = self.reg.af.high.get() | rhs;

        // all flags are cleared except zero.
        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.af.high.set(result);
    }

    // Computes the flags and result for an XOR instruction.
    // lhs is always the register A
    pub fn compute_xor(&mut self, rhs: u8) {
        let result = self.reg.af.high.get() ^ rhs;

        // all flags are cleared except zero.
        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.af.high.set(result);
    }

    /// Pushes on the stack a 16-bit register value,
    /// it decrements SP and pushes the LSB before the MSB.
    pub fn push_stack(&mut self, reg: u16) {
        self.reg.sp.sub(1);
        let addr = self.reg.sp.get();
        let low = (reg & 0x00FF) as u8;
        self.mem.borrow_mut().write_b(addr, low);

        self.reg.sp.sub(1);
        let addr = self.reg.sp.get();
        let high = ((reg >> 8) & 0x00FF) as u8;
        self.mem.borrow_mut().write_b(addr, high);
    }

    /// Pops a 16-bit value from the stack, MSB first, returning the u16 value.
    pub fn pop_stack(&mut self) -> u16 {
        let high = self.mem.borrow().read_b(self.reg.sp.get());
        self.reg.sp.add(1);

        let low = self.mem.borrow().read_b(self.reg.sp.get());
        self.reg.sp.add(1);

        ((high as u16) << 8) & (low as u16)
    }

    /// Retrieves an immediate 8-bit value.
    /// Immediates are retrieved by reading at the address in the PC register.
    pub fn get_immediate8(&mut self) -> u8 {
        let value = self.mem.borrow().read_b(self.reg.pc.get());
        self.reg.pc.add(1);

        value
    }

    /// Retrieves an immediate 16-bit value.
    /// 16-bit immediates are read as two 8-bit immediates, the first being the LSB.
    pub fn get_immediate16(&mut self) -> u16 {
        let low = self.get_immediate8();
        let high = self.get_immediate8();

        (high as u16) & (low as u16)
    }
}
<commit_msg>Fixed compute_cp function arguments<commit_after>use std::rc::Rc;
use std::cell::RefCell;

use gbe::memory::MMU;
use gbe::registers::*;

#[derive(Debug)]
pub struct CPU {
    pub reg: Registers,
    pub mem: Rc<RefCell<MMU>>,
}

impl CPU {
    pub fn new() -> CPU {

        let r = Registers {
            af: Register16::new(0),
            bc: Register16::new(0),
            de: Register16::new(0),
            hl: Register16::new(0),
            pc: Register16::new(0),
            sp: Register16::new(0),
        };

        // TODO: this should be created only once and cloned for every struct
        let mmu = Rc::new(RefCell::new(MMU::new()));

        CPU { reg: r, mem: mmu }
    }

    /// executes the instruction
    pub fn dispatch(&mut self, opcode: u8) {}

    /// reads instructions and executes them
    pub fn fetch_and_exec() {
        let mut cpu = CPU::new();

        loop {
            // fetch
            // the block is needed so that the borrow of cpu.memory ends
            // before dispatch, which will mutably borrow cpu
            let opcode = {
                let mem = cpu.mem.borrow();
                mem.read_b(cpu.reg.pc.get())
            };

            // execute
            cpu.dispatch(opcode);
            // increase PC
            cpu.reg.pc.add(1);
            // TODO: compute clock timings
        }
    }

    pub fn LD_nn_n(reg1: &mut Register8, value: u8) {
        reg1.set(value);
    }

    // Computes the flags and result for an ADD instruction.
    pub fn compute_add(&mut self, lhs: u8, rhs: u8) {
        let result = lhs.wrapping_add(rhs);

        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        // checked add returns None if add overflows
        if let None = lhs.checked_add(rhs) {
            self.reg.set_flag(Flags::Carry);
        }

        let low_result = (rhs & 0x0F) + (lhs & 0x0F);
        // check if bit 4 is set
        if (low_result >> 4) == 1 {
            self.reg.set_flag(Flags::HalfCarry);
        }

        self.reg.af.high.set(result);
    }

    // Computes the flags and result for a SUB instruction.
    pub fn compute_sub(&mut self, lhs: u8, rhs: u8)  {
        let result = lhs.wrapping_sub(rhs);

        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.set_flag(Flags::Sub);

        // checked sub returns None if sub borrows (carry flag)
        if let None = lhs.checked_sub(rhs) {
            self.reg.set_flag(Flags::Carry);
        }

        // same as carry flag but values limited to their 4 low bits (half carry flag)
        if let None = (lhs & 0xF).checked_sub(rhs & 0xF) {
            self.reg.set_flag(Flags::HalfCarry);
        }

        self.reg.af.high.set(result);
    }

    // Computes the flags for a CP instruction.
    // this has the same effect as a SUB, but the result discarded.
    pub fn compute_cp(&mut self, rhs: u8)  {
        let lhs = self.reg.af.high.get();
        let result = lhs.wrapping_sub(rhs);

        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.set_flag(Flags::Sub);

        if let None = lhs.checked_sub(rhs) {
            self.reg.set_flag(Flags::Carry);
        }

        if let None = (lhs & 0xF).checked_sub(rhs & 0xF) {
            self.reg.set_flag(Flags::HalfCarry);
        }
    }

    // Computes the flags and result for an AND instruction.
    // lhs is always the register A
    pub fn compute_and(&mut self, rhs: u8) {
        let result = self.reg.af.high.get() & rhs;

        // HC flag is always set, other flags always cleared except zero.
        self.reg.clear_all_flags();
        self.reg.set_flag(Flags::HalfCarry);

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.af.high.set(result);
    }

    // Computes the flags and result for an OR instruction.
    // lhs is always the register A
    pub fn compute_or(&mut self, rhs: u8) {
        let result = self.reg.af.high.get() | rhs;

        // all flags are cleared except zero.
        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.af.high.set(result);
    }

    // Computes the flags and result for an XOR instruction.
    // lhs is always the register A
    pub fn compute_xor(&mut self, rhs: u8) {
        let result = self.reg.af.high.get() ^ rhs;

        // all flags are cleared except zero.
        self.reg.clear_all_flags();

        if result == 0 {
            self.reg.set_flag(Flags::Zero);
        }

        self.reg.af.high.set(result);
    }

    /// Pushes on the stack a 16-bit register value,
    /// it decrements SP and pushes the LSB before the MSB.
    pub fn push_stack(&mut self, reg: u16) {
        self.reg.sp.sub(1);
        let addr = self.reg.sp.get();
        let low = (reg & 0x00FF) as u8;
        self.mem.borrow_mut().write_b(addr, low);

        self.reg.sp.sub(1);
        let addr = self.reg.sp.get();
        let high = ((reg >> 8) & 0x00FF) as u8;
        self.mem.borrow_mut().write_b(addr, high);
    }

    /// Pops a 16-bit value from the stack, MSB first, returning the u16 value.
    pub fn pop_stack(&mut self) -> u16 {
        let high = self.mem.borrow().read_b(self.reg.sp.get());
        self.reg.sp.add(1);

        let low = self.mem.borrow().read_b(self.reg.sp.get());
        self.reg.sp.add(1);

        ((high as u16) << 8) & (low as u16)
    }

    /// Retrieves an immediate 8-bit value.
    /// Immediates are retrieved by reading at the address in the PC register.
    pub fn get_immediate8(&mut self) -> u8 {
        let value = self.mem.borrow().read_b(self.reg.pc.get());
        self.reg.pc.add(1);

        value
    }

    /// Retrieves an immediate 16-bit value.
    /// 16-bit immediates are read as two 8-bit immediates, the first being the LSB.
    pub fn get_immediate16(&mut self) -> u16 {
        let low = self.get_immediate8();
        let high = self.get_immediate8();

        (high as u16) & (low as u16)
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(not(feature = "GTK_3_10"), allow(unused_variables, unused_mut))]

extern crate gtk;
extern crate gdk;

use gtk::traits::*;
use gtk::signal::Inhibit;
use gdk::enums::modifier_type;

/// Expands to its argument if GTK+ 3.10 support is configured and to `()` otherwise
#[macro_export]
#[cfg(not(feature = "GTK_3_10"))]
macro_rules! with_gtk_3_10 {
    ($ex:expr) => (
        ()
    );
    ($bl:block) => {
        ()
    }
}

/// Expands to its argument if GTK+ 3.10 support is configured and to `()` otherwise
#[macro_export]
#[cfg(feature = "GTK_3_10")]
macro_rules! with_gtk_3_10 {
    ($ex:expr) => (
        $ex
    );
    ($bl:block) => {
        $bl
    }
}

fn about_clicked(w: gtk::Button) {
    let dialog = gtk::AboutDialog::new().unwrap();

    let crew = [
        "James T. Kirk",
        "Spock",
        "Leonard McCoy",
    ];

    dialog.set_authors(&crew);
    dialog.set_artists(&crew[1..]);

    println!("Authors: {:?}", dialog.get_authors());
    println!("Artists: {:?}", dialog.get_artists());
    println!("Documenters: {:?}", dialog.get_documenters());

    dialog.run();
    dialog.destroy();
}

fn main() {
    gtk::init();
    println!("Major: {}, Minor: {}", gtk::get_major_version(), gtk::get_minor_version());
    let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    let frame = gtk::Frame::new(Some("Yep a frame")).unwrap();
    let _box = gtk::Box::new(gtk::Orientation::Horizontal, 10).unwrap();
    let v_box = gtk::Box::new(gtk::Orientation::Horizontal, 10).unwrap();
    let button_box = gtk::ButtonBox::new(gtk::Orientation::Horizontal).unwrap();
    let label = gtk::Label::new("Yeah a wonderful label too !").unwrap();
    let button = gtk::Button::new_with_label("Whattttt a button !").unwrap();
    let button_about = gtk::Button::new_with_label("About?").unwrap();
    let button_recent = gtk::Button::new_with_label("Choose a recent one !").unwrap();
    let button_font = gtk::Button::new_with_label("Choose a font !").unwrap();
    let app_button = gtk::Button::new_with_label("App ?").unwrap();
    let file_button = gtk::Button::new_with_label("file ?").unwrap();
    let font_button = gtk::FontButton::new().unwrap();
    let toggle_button = gtk::ToggleButton::new_with_label("Toggle Me !").unwrap();
    let check_button = gtk::CheckButton::new_with_label("Labeled check button").unwrap();
    let color_button = gtk::ColorButton::new().unwrap();
    let menu_button = with_gtk_3_10!(
        gtk::MenuButton::new().unwrap()
    );
    let link_button = gtk::LinkButton::new("www.rust-lang.org").unwrap();
    let volume_button = gtk::VolumeButton::new().unwrap();
    let entry = gtk::Entry::new().unwrap();
    let search_entry = with_gtk_3_10!(
        gtk::SearchEntry::new().unwrap()
    );
    let separator = gtk::Separator::new(gtk::Orientation::Horizontal).unwrap();
    let separator2 = gtk::Separator::new(gtk::Orientation::Horizontal).unwrap();
    let switch = gtk::Switch::new().unwrap();
    let switch2 = gtk::Switch::new().unwrap();
    let scale = gtk::Scale::new_with_range(gtk::Orientation::Horizontal, 0., 100., 1.).unwrap();
    let level_bar = with_gtk_3_10!(
        gtk::LevelBar::new_for_interval(0., 100.).unwrap()
    );
    let spin_button = gtk::SpinButton::new_with_range(0., 100., 1.).unwrap();
    let spinner = gtk::Spinner::new().unwrap();
    let image = gtk::Image::new_from_file("./test/resources/gtk.jpg").unwrap();
    let progress_bar = gtk::ProgressBar::new().unwrap();
    let arrow = gtk::Arrow::new(gtk::ArrowType::Right, gtk::ShadowType::EtchedOut).unwrap();
    let calendar = gtk::Calendar::new().unwrap();
    let info_bar = gtk::InfoBar::new().unwrap();
    let tmp_button = with_gtk_3_10!(
        gtk::Button::new_from_icon_name("edit-clear", gtk::IconSize::Button).unwrap()
    );

    println!("test");

    with_gtk_3_10! {{
        info_bar.show_close_button(true);
    }}

    /*info_bar.connect(signals::Response::new(|response_id| {
        info_bar.hide()
    }));*/ //TODO: Why does this not work?

    progress_bar.set_fraction(0.7);
    spinner.start();
    with_gtk_3_10! {{
        level_bar.set_value(37.);
    }}
    switch2.set_active(true);
    frame.set_border_width(10);
    _box.set_border_width(5);
    entry.set_placeholder("An Entry with a placeholder !");
    volume_button.set_orientation(gtk::Orientation::Horizontal);
    label.set_justify(gtk::Justification::Left);
    window.set_title("Yeah a beautiful window with rgtk !");
    window.set_window_position(gtk::WindowPosition::Center);
    window.add(&frame);

    let entry_clone = entry.clone();
    button.connect_clicked(move |_| {
        let dialog = gtk::Dialog::with_buttons(
            "Hello!", None, gtk::DialogFlags::Modal,
            [("No", 0), ("Yes", 1), ("Yes!", 2)]);

        let ret = dialog.run();

        dialog.destroy();

        entry_clone.set_text(&format!("Clicked {}", ret));
    });

    // use a plain function instead of a closure
    button_about.connect_clicked(about_clicked);

    button_font.connect_clicked(|_| {
        let dialog = gtk::FontChooserDialog::new("Font chooser test", None).unwrap();

        dialog.run();
        dialog.destroy();
    });

    button_recent.connect_clicked(|_| {
        let dialog = gtk::RecentChooserDialog::new(
            "Recent chooser test", None,
            [("Ok", gtk::ResponseType::Ok), ("Cancel", gtk::ResponseType::Cancel)]);

        dialog.run();
        dialog.destroy();
    });

    file_button.connect_clicked(|_| {
        //entry.set_text("Clicked!");
        let dialog = gtk::FileChooserDialog::new(
            "Choose a file", None, gtk::FileChooserAction::Open,
            [("Open", gtk::ResponseType::Ok), ("Cancel", gtk::ResponseType::Cancel)]);

        dialog.set_select_multiple(true);
        dialog.run();
        let files = dialog.get_filenames();
        dialog.destroy();

        println!("Files: {:?}", files);
    });

    app_button.connect_clicked(|_| {
        //entry.set_text("Clicked!");
        let dialog = gtk::AppChooserDialog::new_for_content_type(None, gtk::DialogFlags::Modal, "sh").unwrap();

        dialog.run();
        dialog.destroy();
    });

    let entry_clone = entry.clone();
    window.connect_key_press_event(move |_, key| {
        let keyval = key.keyval;
        let keystate = key.state;

        println!("key pressed: {} / {:?}", keyval, keystate);
        println!("text: {}", entry_clone.get_text().unwrap());

        if keystate.intersects(modifier_type::ControlMask) {
            println!("You pressed Ctrl!");
        }

        Inhibit(false)
    });

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(true)
    });

    frame.add(&_box);
    with_gtk_3_10! {{
        button_box.add(&tmp_button)
    }};
    button_box.add(&button);
    button_box.add(&button_about);
    button_box.add(&button_font);
    button_box.add(&button_recent);
    button_box.add(&file_button);
    button_box.add(&app_button);
    button_box.add(&font_button);
    button_box.add(&toggle_button);
    button_box.add(&color_button);
    button_box.add(&volume_button);
    v_box.add(&switch);
    with_gtk_3_10! {{
        v_box.add(&menu_button);
    }}
    v_box.add(&switch2);
    v_box.add(&check_button);
    v_box.add(&link_button);
    v_box.add(&spin_button);
    _box.add(&info_bar);
    _box.add(&v_box);
    _box.add(&scale);
    with_gtk_3_10! {{
        _box.add(&level_bar);
    }}
    _box.add(&button_box);
    _box.add(&progress_bar);
    _box.add(&separator);
    _box.add(&label);
    _box.add(&entry);
    _box.add(&separator2);
    with_gtk_3_10! {{
        _box.add(&search_entry);
    }}
    _box.add(&spinner);
    _box.add(&image);
    _box.add(&arrow);
    _box.add(&calendar);
    _box.set_orientation(gtk::Orientation::Vertical);
    // window.set_decorated(false);
    window.set_decorated(true);
    window.show_all();
    gtk::main();
}
<commit_msg>Spell the feature names in gtktest correctly<commit_after>#![cfg_attr(not(feature = "gtk_3_10"), allow(unused_variables, unused_mut))]

extern crate gtk;
extern crate gdk;

use gtk::traits::*;
use gtk::signal::Inhibit;
use gdk::enums::modifier_type;

/// Expands to its argument if GTK+ 3.10 support is configured and to `()` otherwise
#[cfg(not(feature = "gtk_3_10"))]
macro_rules! with_gtk_3_10 {
    ($ex:expr) => (
        ()
    );
    ($bl:block) => {
        ()
    }
}

/// Expands to its argument if GTK+ 3.10 support is configured and to `()` otherwise
#[cfg(feature = "gtk_3_10")]
macro_rules! with_gtk_3_10 {
    ($ex:expr) => (
        $ex
    );
    ($bl:block) => {
        $bl
    }
}

fn about_clicked(_: gtk::Button) {
    let dialog = gtk::AboutDialog::new().unwrap();

    let crew = [
        "James T. Kirk",
        "Spock",
        "Leonard McCoy",
    ];

    dialog.set_authors(&crew);
    dialog.set_artists(&crew[1..]);

    println!("Authors: {:?}", dialog.get_authors());
    println!("Artists: {:?}", dialog.get_artists());
    println!("Documenters: {:?}", dialog.get_documenters());

    dialog.run();
    dialog.destroy();
}

fn main() {
    gtk::init();
    println!("Major: {}, Minor: {}", gtk::get_major_version(), gtk::get_minor_version());
    let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    let frame = gtk::Frame::new(Some("Yep a frame")).unwrap();
    let _box = gtk::Box::new(gtk::Orientation::Horizontal, 10).unwrap();
    let v_box = gtk::Box::new(gtk::Orientation::Horizontal, 10).unwrap();
    let button_box = gtk::ButtonBox::new(gtk::Orientation::Horizontal).unwrap();
    let label = gtk::Label::new("Yeah a wonderful label too !").unwrap();
    let button = gtk::Button::new_with_label("Whattttt a button !").unwrap();
    let button_about = gtk::Button::new_with_label("About?").unwrap();
    let button_recent = gtk::Button::new_with_label("Choose a recent one !").unwrap();
    let button_font = gtk::Button::new_with_label("Choose a font !").unwrap();
    let app_button = gtk::Button::new_with_label("App ?").unwrap();
    let file_button = gtk::Button::new_with_label("file ?").unwrap();
    let font_button = gtk::FontButton::new().unwrap();
    let toggle_button = gtk::ToggleButton::new_with_label("Toggle Me !").unwrap();
    let check_button = gtk::CheckButton::new_with_label("Labeled check button").unwrap();
    let color_button = gtk::ColorButton::new().unwrap();
    let menu_button = with_gtk_3_10!(
        gtk::MenuButton::new().unwrap()
    );
    let link_button = gtk::LinkButton::new("www.rust-lang.org").unwrap();
    let volume_button = gtk::VolumeButton::new().unwrap();
    let entry = gtk::Entry::new().unwrap();
    let search_entry = with_gtk_3_10!(
        gtk::SearchEntry::new().unwrap()
    );
    let separator = gtk::Separator::new(gtk::Orientation::Horizontal).unwrap();
    let separator2 = gtk::Separator::new(gtk::Orientation::Horizontal).unwrap();
    let switch = gtk::Switch::new().unwrap();
    let switch2 = gtk::Switch::new().unwrap();
    let scale = gtk::Scale::new_with_range(gtk::Orientation::Horizontal, 0., 100., 1.).unwrap();
    let level_bar = with_gtk_3_10!(
        gtk::LevelBar::new_for_interval(0., 100.).unwrap()
    );
    let spin_button = gtk::SpinButton::new_with_range(0., 100., 1.).unwrap();
    let spinner = gtk::Spinner::new().unwrap();
    let image = gtk::Image::new_from_file("./test/resources/gtk.jpg").unwrap();
    let progress_bar = gtk::ProgressBar::new().unwrap();
    let arrow = gtk::Arrow::new(gtk::ArrowType::Right, gtk::ShadowType::EtchedOut).unwrap();
    let calendar = gtk::Calendar::new().unwrap();
    let info_bar = gtk::InfoBar::new().unwrap();
    let tmp_button = with_gtk_3_10!(
        gtk::Button::new_from_icon_name("edit-clear", gtk::IconSize::Button).unwrap()
    );

    println!("test");

    with_gtk_3_10! {{
        info_bar.show_close_button(true);
    }}

    /*info_bar.connect(signals::Response::new(|response_id| {
        info_bar.hide()
    }));*/ //TODO: Why does this not work?

    progress_bar.set_fraction(0.7);
    spinner.start();
    with_gtk_3_10! {{
        level_bar.set_value(37.);
    }}
    switch2.set_active(true);
    frame.set_border_width(10);
    _box.set_border_width(5);
    entry.set_placeholder("An Entry with a placeholder !");
    volume_button.set_orientation(gtk::Orientation::Horizontal);
    label.set_justify(gtk::Justification::Left);
    window.set_title("Yeah a beautiful window with rgtk !");
    window.set_window_position(gtk::WindowPosition::Center);
    window.add(&frame);

    let entry_clone = entry.clone();
    button.connect_clicked(move |_| {
        let dialog = gtk::Dialog::with_buttons(
            "Hello!", None, gtk::DialogFlags::Modal,
            [("No", 0), ("Yes", 1), ("Yes!", 2)]);

        let ret = dialog.run();

        dialog.destroy();

        entry_clone.set_text(&format!("Clicked {}", ret));
    });

    // use a plain function instead of a closure
    button_about.connect_clicked(about_clicked);

    button_font.connect_clicked(|_| {
        let dialog = gtk::FontChooserDialog::new("Font chooser test", None).unwrap();

        dialog.run();
        dialog.destroy();
    });

    button_recent.connect_clicked(|_| {
        let dialog = gtk::RecentChooserDialog::new(
            "Recent chooser test", None,
            [("Ok", gtk::ResponseType::Ok), ("Cancel", gtk::ResponseType::Cancel)]);

        dialog.run();
        dialog.destroy();
    });

    file_button.connect_clicked(|_| {
        //entry.set_text("Clicked!");
        let dialog = gtk::FileChooserDialog::new(
            "Choose a file", None, gtk::FileChooserAction::Open,
            [("Open", gtk::ResponseType::Ok), ("Cancel", gtk::ResponseType::Cancel)]);

        dialog.set_select_multiple(true);
        dialog.run();
        let files = dialog.get_filenames();
        dialog.destroy();

        println!("Files: {:?}", files);
    });

    app_button.connect_clicked(|_| {
        //entry.set_text("Clicked!");
        let dialog = gtk::AppChooserDialog::new_for_content_type(None, gtk::DialogFlags::Modal, "sh").unwrap();

        dialog.run();
        dialog.destroy();
    });

    let entry_clone = entry.clone();
    window.connect_key_press_event(move |_, key| {
        let keyval = key.keyval;
        let keystate = key.state;

        println!("key pressed: {} / {:?}", keyval, keystate);
        println!("text: {}", entry_clone.get_text().unwrap());

        if keystate.intersects(modifier_type::ControlMask) {
            println!("You pressed Ctrl!");
        }

        Inhibit(false)
    });

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(true)
    });

    frame.add(&_box);
    with_gtk_3_10! {{
        button_box.add(&tmp_button)
    }};
    button_box.add(&button);
    button_box.add(&button_about);
    button_box.add(&button_font);
    button_box.add(&button_recent);
    button_box.add(&file_button);
    button_box.add(&app_button);
    button_box.add(&font_button);
    button_box.add(&toggle_button);
    button_box.add(&color_button);
    button_box.add(&volume_button);
    v_box.add(&switch);
    with_gtk_3_10! {{
        v_box.add(&menu_button);
    }}
    v_box.add(&switch2);
    v_box.add(&check_button);
    v_box.add(&link_button);
    v_box.add(&spin_button);
    _box.add(&info_bar);
    _box.add(&v_box);
    _box.add(&scale);
    with_gtk_3_10! {{
        _box.add(&level_bar);
    }}
    _box.add(&button_box);
    _box.add(&progress_bar);
    _box.add(&separator);
    _box.add(&label);
    _box.add(&entry);
    _box.add(&separator2);
    with_gtk_3_10! {{
        _box.add(&search_entry);
    }}
    _box.add(&spinner);
    _box.add(&image);
    _box.add(&arrow);
    _box.add(&calendar);
    _box.set_orientation(gtk::Orientation::Vertical);
    // window.set_decorated(false);
    window.set_decorated(true);
    window.show_all();
    gtk::main();
}
<|endoftext|>


<commit_before>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                if let Ok(message) = decode(encoded_msg) {
                    let message: PeerMessage = message;

                    debug!(target: LIB_NAME, "I am using {:?}.", self.ws.token());

                    if let Some(demo_client) = self.demo_client.clone() {
                        if message.sender.as_str() == demo_client.as_str() {
                            info!(target: LIB_NAME, "Faking delay for messages from {}!", demo_client);
                            self.message_queue.push_back(message);
                            return self.ws.timeout(4000, DELAYED_MESSAGE);
                        }
                    }

                    self.message_handler(message);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Failed to serialize the binary message."))
                }
            }
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to client list", string);
                if let Ok(mut clocks) = self.clocks.lock() {
                    clocks.insert(string, 0u32);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Failed to serialize the string message."))
                }
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                if let Some(msg) = self.message_queue.pop_front() {
                    self.message_handler(msg);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Invalid timeout token encountered!"))
                }
            }
            _ => Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        // TODO: Remove disconnected client's clock from our vclock copy.
        info!(target: LIB_NAME, "Received an on_close call");
        if reason.is_empty() {
            // This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} d/c with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                if vclocks.get(&key.clone()).is_some() {
                    let lval = vclocks.get(&key.clone()).unwrap().clone();
                    let max_val = cmp::max(val, &lval);
                    vclocks.insert(key.clone(), *max_val);
                }
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        // Finishes the lifetime of the mutex holds so buffer_check can use it without blocking
        {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
            info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            for (key, val) in message.clocks.iter() {
                vclocks.insert(key.clone(), *val);
            }
        }
        self.buffer_check();
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}
<commit_msg>Panic if we're unable to send our peer name<commit_after>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                if let Ok(message) = decode(encoded_msg) {
                    let message: PeerMessage = message;

                    debug!(target: LIB_NAME, "I am using {:?}.", self.ws.token());

                    if let Some(demo_client) = self.demo_client.clone() {
                        if message.sender.as_str() == demo_client.as_str() {
                            info!(target: LIB_NAME, "Faking delay for messages from {}!", demo_client);
                            self.message_queue.push_back(message);
                            return self.ws.timeout(4000, DELAYED_MESSAGE);
                        }
                    }

                    self.message_handler(message);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Failed to serialize the binary message."))
                }
            }
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to client list", string);
                if let Ok(mut clocks) = self.clocks.lock() {
                    clocks.insert(string, 0u32);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Failed to serialize the string message."))
                }
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                if let Some(msg) = self.message_queue.pop_front() {
                    self.message_handler(msg);
                    Ok(())
                } else {
                    Err(ws::Error::new(ws::ErrorKind::Internal,
                                       "Invalid timeout token encountered!"))
                }
            }
            _ => Err(ws::Error::new(ws::ErrorKind::Internal,
                                    "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        // TODO: Remove disconnected client's clock from our vclock copy.
        info!(target: LIB_NAME, "Received an on_close call");
        if reason.is_empty() {
            // This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} d/c with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            debug!(target: LIB_NAME, "discrepency still exists");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                if vclocks.get(&key.clone()).is_some() {
                    let lval = vclocks.get(&key.clone()).unwrap().clone();
                    let max_val = cmp::max(val, &lval);
                    vclocks.insert(key.clone(), *max_val);
                }
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        // Finishes the lifetime of the mutex holds so buffer_check can use it without blocking
        {
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if key.as_str() == message.sender.as_str() {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        if *val != *lval + 1 {
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                            return;
                        }
                    }
                } else {
                    if let Some(lval) = vclocks.get(&key.clone()) {
                        debug!(target: LIB_NAME, "key: {} val: {} and lval: {}", key, val, lval);
                        if val <= lval {
                            debug!(target: LIB_NAME, "val <= lval");
                            continue;
                        } else {
                            // There's a clock that is greater than what we have
                            if let Ok(mut buffer) = self.buffer.lock() {
                                debug!(target: LIB_NAME, "pushing to buffer..");
                                buffer.push_back(message.clone());
                            }
                            debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                            return;
                        }
                    }
                }
            }

            // Update clocks
            debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
            info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            for (key, val) in message.clocks.iter() {
                vclocks.insert(key.clone(), *val);
            }
        }
        self.buffer_check();
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}", e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        if let Err(e) = ws.send(self.me.clone()) {
            panic!("Unable to send name to connected peer. Something is wrong..\n{}", e);
        }
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}
<|endoftext|>


<commit_before>use super::pool::Pool;
use iron::headers::ContentType;
use iron::prelude::*;
use prometheus::{Encoder, IntGauge, TextEncoder};

lazy_static! {
    static ref QUEUED_CRATES_COUNT: IntGauge = register_int_gauge!(
        "docsrs_queued_crates_count",
        "Number of crates in the build queue"
    )
    .unwrap();
    static ref FAILED_CRATES_COUNT: IntGauge = register_int_gauge!(
        "docsrs_failed_crates_count",
        "Number of crates that failed to build"
    )
    .unwrap();
}

pub fn metrics_handler(req: &mut Request) -> IronResult<Response> {
    let conn = extension!(req, Pool);

    QUEUED_CRATES_COUNT.set(
        ctry!(conn.query("SELECT COUNT(*) FROM queue WHERE attempt < 5;", &[]))
            .get(0)
            .get(0),
    );
    FAILED_CRATES_COUNT.set(
        ctry!(conn.query("SELECT COUNT(*) FROM queue WHERE attempt >= 5;", &[]))
            .get(0)
            .get(0),
    );

    let mut buffer = Vec::new();
    let families = prometheus::gather();
    ctry!(TextEncoder::new().encode(&families, &mut buffer));

    let mut resp = Response::with(buffer);
    resp.headers
        .set(ContentType("text/plain; version=0.0.4".parse().unwrap()));
    Ok(resp)
}
<commit_msg>metrics: actually return a 200 status code<commit_after>use super::pool::Pool;
use iron::headers::ContentType;
use iron::prelude::*;
use iron::status::Status;
use prometheus::{Encoder, IntGauge, TextEncoder};

lazy_static! {
    static ref QUEUED_CRATES_COUNT: IntGauge = register_int_gauge!(
        "docsrs_queued_crates_count",
        "Number of crates in the build queue"
    )
    .unwrap();
    static ref FAILED_CRATES_COUNT: IntGauge = register_int_gauge!(
        "docsrs_failed_crates_count",
        "Number of crates that failed to build"
    )
    .unwrap();
}

pub fn metrics_handler(req: &mut Request) -> IronResult<Response> {
    let conn = extension!(req, Pool);

    QUEUED_CRATES_COUNT.set(
        ctry!(conn.query("SELECT COUNT(*) FROM queue WHERE attempt < 5;", &[]))
            .get(0)
            .get(0),
    );
    FAILED_CRATES_COUNT.set(
        ctry!(conn.query("SELECT COUNT(*) FROM queue WHERE attempt >= 5;", &[]))
            .get(0)
            .get(0),
    );

    let mut buffer = Vec::new();
    let families = prometheus::gather();
    ctry!(TextEncoder::new().encode(&families, &mut buffer));

    let mut resp = Response::with(buffer);
    resp.status = Some(Status::Ok);
    resp.headers
        .set(ContentType("text/plain; version=0.0.4".parse().unwrap()));
    Ok(resp)
}
<|endoftext|>