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

use std::io::{self, Write};
use std::cell::RefCell;
use std::fmt::Write as FmtWrite;

use time::{self, Duration};
use bytes::{BytesMut, BufMut};
use futures::{Async, Poll};
use tokio_io::AsyncWrite;
use http::{Version, HttpTryFrom};
use http::header::{HeaderValue, DATE,
                   CONNECTION, CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING};
use flate2::Compression;
use flate2::write::{GzEncoder, DeflateEncoder};
use brotli2::write::BrotliEncoder;

use body::{Body, Binary};
use headers::ContentEncoding;
use server::WriterState;
use server::shared::SharedBytes;
use server::encoding::{ContentEncoder, TransferEncoding};

use client::ClientRequest;

const AVERAGE_HEADER_SIZE: usize = 30;

bitflags! {
    struct Flags: u8 {
        const STARTED = 0b0000_0001;
        const UPGRADE = 0b0000_0010;
        const KEEPALIVE = 0b0000_0100;
        const DISCONNECTED = 0b0000_1000;
    }
}

pub(crate) struct HttpClientWriter {
    flags: Flags,
    written: u64,
    headers_size: u32,
    buffer: SharedBytes,
    buffer_capacity: usize,
    encoder: ContentEncoder,
}

impl HttpClientWriter {

    pub fn new(buffer: SharedBytes) -> HttpClientWriter {
        let encoder = ContentEncoder::Identity(TransferEncoding::eof(buffer.clone()));
        HttpClientWriter {
            flags: Flags::empty(),
            written: 0,
            headers_size: 0,
            buffer_capacity: 0,
            buffer,
            encoder,
        }
    }

    pub fn disconnected(&mut self) {
        self.buffer.take();
    }

    // pub fn keepalive(&self) -> bool {
    //    self.flags.contains(Flags::KEEPALIVE) && !self.flags.contains(Flags::UPGRADE)
    // }

    fn write_to_stream<T: AsyncWrite>(&mut self, stream: &mut T) -> io::Result<WriterState> {
        while !self.buffer.is_empty() {
            match stream.write(self.buffer.as_ref()) {
                Ok(0) => {
                    self.disconnected();
                    return Ok(WriterState::Done);
                },
                Ok(n) => {
                    let _ = self.buffer.split_to(n);
                },
                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                    if self.buffer.len() > self.buffer_capacity {
                        return Ok(WriterState::Pause)
                    } else {
                        return Ok(WriterState::Done)
                    }
                }
                Err(err) => return Err(err),
            }
        }
        Ok(WriterState::Done)
    }
}

impl HttpClientWriter {

    pub fn start(&mut self, msg: &mut ClientRequest) -> io::Result<()> {
        // prepare task
        self.flags.insert(Flags::STARTED);
        self.encoder = content_encoder(self.buffer.clone(), msg);

        // render message
        {
            let mut buffer = self.buffer.get_mut();
            if let Body::Binary(ref bytes) = *msg.body() {
                buffer.reserve(256 + msg.headers().len() * AVERAGE_HEADER_SIZE + bytes.len());
            } else {
                buffer.reserve(256 + msg.headers().len() * AVERAGE_HEADER_SIZE);
            }

            if msg.upgrade() {
                self.flags.insert(Flags::UPGRADE);
            }

            // status line
            let _ = write!(buffer, "{} {} {:?}\r\n",
                           msg.method(),
                           msg.uri().path_and_query().map(|u| u.as_str()).unwrap_or(""),
                           msg.version());

            // write headers
            for (key, value) in msg.headers() {
                let v = value.as_ref();
                let k = key.as_str().as_bytes();
                buffer.reserve(k.len() + v.len() + 4);
                buffer.put_slice(k);
                buffer.put_slice(b": ");
                buffer.put_slice(v);
                buffer.put_slice(b"\r\n");
            }

            // set date header
            if !msg.headers().contains_key(DATE) {
                buffer.extend_from_slice(b"date: ");
                set_date(&mut buffer);
                buffer.extend_from_slice(b"\r\n\r\n");
            } else {
                buffer.extend_from_slice(b"\r\n");
            }
            self.headers_size = buffer.len() as u32;

            if msg.body().is_binary() {
                if let Body::Binary(bytes) = msg.replace_body(Body::Empty) {
                    self.written += bytes.len() as u64;
                    self.encoder.write(bytes)?;
                }
            } else {
                self.buffer_capacity = msg.write_buffer_capacity();
            }
        }
        Ok(())
    }

    pub fn write(&mut self, payload: Binary) -> io::Result<WriterState> {
        self.written += payload.len() as u64;
        if !self.flags.contains(Flags::DISCONNECTED) {
            if self.flags.contains(Flags::UPGRADE) {
                self.buffer.extend(payload);
            } else {
                self.encoder.write(payload)?;
            }
        }

        if self.buffer.len() > self.buffer_capacity {
            Ok(WriterState::Pause)
        } else {
            Ok(WriterState::Done)
        }
    }

    pub fn write_eof(&mut self) -> io::Result<()> {
        self.encoder.write_eof()?;

        if self.encoder.is_eof() {
            Ok(())
        } else {
            Err(io::Error::new(io::ErrorKind::Other,
                               "Last payload item, but eof is not reached"))
        }
    }

    #[inline]
    pub fn poll_completed<T: AsyncWrite>(&mut self, stream: &mut T, shutdown: bool)
                                         -> Poll<(), io::Error>
    {
        match self.write_to_stream(stream) {
            Ok(WriterState::Done) => {
                if shutdown {
                    stream.shutdown()
                } else {
                    Ok(Async::Ready(()))
                }
            },
            Ok(WriterState::Pause) => Ok(Async::NotReady),
            Err(err) => Err(err)
        }
    }
}

fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder {
    let version = req.version();
    let mut body = req.replace_body(Body::Empty);
    let mut encoding = req.content_encoding();

    let transfer = match body {
        Body::Empty => {
            req.headers_mut().remove(CONTENT_LENGTH);
            TransferEncoding::length(0, buf)
        },
        Body::Binary(ref mut bytes) => {
            if encoding.is_compression() {
                let tmp = SharedBytes::default();
                let transfer = TransferEncoding::eof(tmp.clone());
                let mut enc = match encoding {
                    ContentEncoding::Deflate => ContentEncoder::Deflate(
                        DeflateEncoder::new(transfer, Compression::default())),
                    ContentEncoding::Gzip => ContentEncoder::Gzip(
                        GzEncoder::new(transfer, Compression::default())),
                    ContentEncoding::Br => ContentEncoder::Br(
                        BrotliEncoder::new(transfer, 5)),
                    ContentEncoding::Identity => ContentEncoder::Identity(transfer),
                    ContentEncoding::Auto => unreachable!()
                };
                // TODO return error!
                let _ = enc.write(bytes.clone());
                let _ = enc.write_eof();
                *bytes = Binary::from(tmp.take());

                req.headers_mut().insert(
                    CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
                encoding = ContentEncoding::Identity;
            }
            let mut b = BytesMut::new();
            let _ = write!(b, "{}", bytes.len());
            req.headers_mut().insert(
                CONTENT_LENGTH, HeaderValue::try_from(b.freeze()).unwrap());
            TransferEncoding::eof(buf)
        },
        Body::Streaming(_) | Body::Actor(_) => {
            if req.upgrade() {
                if version == Version::HTTP_2 {
                    error!("Connection upgrade is forbidden for HTTP/2");
                } else {
                    req.headers_mut().insert(CONNECTION, HeaderValue::from_static("upgrade"));
                }
                if encoding != ContentEncoding::Identity {
                    encoding = ContentEncoding::Identity;
                    req.headers_mut().remove(CONTENT_ENCODING);
                }
                TransferEncoding::eof(buf)
            } else {
                streaming_encoding(buf, version, req)
            }
        }
    };

    if encoding.is_compression() {
        req.headers_mut().insert(
            CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
    }

    req.replace_body(body);
    match encoding {
        ContentEncoding::Deflate => ContentEncoder::Deflate(
            DeflateEncoder::new(transfer, Compression::default())),
        ContentEncoding::Gzip => ContentEncoder::Gzip(
            GzEncoder::new(transfer, Compression::default())),
        ContentEncoding::Br => ContentEncoder::Br(
            BrotliEncoder::new(transfer, 5)),
        ContentEncoding::Identity | ContentEncoding::Auto => ContentEncoder::Identity(transfer),
    }
}

fn streaming_encoding(buf: SharedBytes, version: Version, req: &mut ClientRequest)
                      -> TransferEncoding {
    if req.chunked() {
        // Enable transfer encoding
        req.headers_mut().remove(CONTENT_LENGTH);
        if version == Version::HTTP_2 {
            req.headers_mut().remove(TRANSFER_ENCODING);
            TransferEncoding::eof(buf)
        } else {
            req.headers_mut().insert(
                TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
            TransferEncoding::chunked(buf)
        }
    } else {
        // if Content-Length is specified, then use it as length hint
        let (len, chunked) =
            if let Some(len) = req.headers().get(CONTENT_LENGTH) {
                // Content-Length
                if let Ok(s) = len.to_str() {
                    if let Ok(len) = s.parse::<u64>() {
                        (Some(len), false)
                    } else {
                        error!("illegal Content-Length: {:?}", len);
                        (None, false)
                    }
                } else {
                    error!("illegal Content-Length: {:?}", len);
                    (None, false)
                }
            } else {
                (None, true)
            };

        if !chunked {
            if let Some(len) = len {
                TransferEncoding::length(len, buf)
            } else {
                TransferEncoding::eof(buf)
            }
        } else {
            // Enable transfer encoding
            match version {
                Version::HTTP_11 => {
                    req.headers_mut().insert(
                        TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
                    TransferEncoding::chunked(buf)
                },
                _ => {
                    req.headers_mut().remove(TRANSFER_ENCODING);
                    TransferEncoding::eof(buf)
                }
            }
        }
    }
}

// "Sun, 06 Nov 1994 08:49:37 GMT".len()
pub const DATE_VALUE_LENGTH: usize = 29;

fn set_date(dst: &mut BytesMut) {
    CACHED.with(|cache| {
        let mut cache = cache.borrow_mut();
        let now = time::get_time();
        if now > cache.next_update {
            cache.update(now);
        }
        dst.extend_from_slice(cache.buffer());
    })
}

struct CachedDate {
    bytes: [u8; DATE_VALUE_LENGTH],
    next_update: time::Timespec,
}

thread_local!(static CACHED: RefCell<CachedDate> = RefCell::new(CachedDate {
    bytes: [0; DATE_VALUE_LENGTH],
    next_update: time::Timespec::new(0, 0),
}));

impl CachedDate {
    fn buffer(&self) -> &[u8] {
        &self.bytes[..]
    }

    fn update(&mut self, now: time::Timespec) {
        write!(&mut self.bytes[..], "{}", time::at_utc(now).rfc822()).unwrap();
        self.next_update = now + Duration::seconds(1);
        self.next_update.nsec = 0;
    }
}
<commit_msg>If no path is available from the URI request /<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]

use std::io::{self, Write};
use std::cell::RefCell;
use std::fmt::Write as FmtWrite;

use time::{self, Duration};
use bytes::{BytesMut, BufMut};
use futures::{Async, Poll};
use tokio_io::AsyncWrite;
use http::{Version, HttpTryFrom};
use http::header::{HeaderValue, DATE,
                   CONNECTION, CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING};
use flate2::Compression;
use flate2::write::{GzEncoder, DeflateEncoder};
use brotli2::write::BrotliEncoder;

use body::{Body, Binary};
use headers::ContentEncoding;
use server::WriterState;
use server::shared::SharedBytes;
use server::encoding::{ContentEncoder, TransferEncoding};

use client::ClientRequest;

const AVERAGE_HEADER_SIZE: usize = 30;

bitflags! {
    struct Flags: u8 {
        const STARTED = 0b0000_0001;
        const UPGRADE = 0b0000_0010;
        const KEEPALIVE = 0b0000_0100;
        const DISCONNECTED = 0b0000_1000;
    }
}

pub(crate) struct HttpClientWriter {
    flags: Flags,
    written: u64,
    headers_size: u32,
    buffer: SharedBytes,
    buffer_capacity: usize,
    encoder: ContentEncoder,
}

impl HttpClientWriter {

    pub fn new(buffer: SharedBytes) -> HttpClientWriter {
        let encoder = ContentEncoder::Identity(TransferEncoding::eof(buffer.clone()));
        HttpClientWriter {
            flags: Flags::empty(),
            written: 0,
            headers_size: 0,
            buffer_capacity: 0,
            buffer,
            encoder,
        }
    }

    pub fn disconnected(&mut self) {
        self.buffer.take();
    }

    // pub fn keepalive(&self) -> bool {
    //    self.flags.contains(Flags::KEEPALIVE) && !self.flags.contains(Flags::UPGRADE)
    // }

    fn write_to_stream<T: AsyncWrite>(&mut self, stream: &mut T) -> io::Result<WriterState> {
        while !self.buffer.is_empty() {
            match stream.write(self.buffer.as_ref()) {
                Ok(0) => {
                    self.disconnected();
                    return Ok(WriterState::Done);
                },
                Ok(n) => {
                    let _ = self.buffer.split_to(n);
                },
                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                    if self.buffer.len() > self.buffer_capacity {
                        return Ok(WriterState::Pause)
                    } else {
                        return Ok(WriterState::Done)
                    }
                }
                Err(err) => return Err(err),
            }
        }
        Ok(WriterState::Done)
    }
}

impl HttpClientWriter {

    pub fn start(&mut self, msg: &mut ClientRequest) -> io::Result<()> {
        // prepare task
        self.flags.insert(Flags::STARTED);
        self.encoder = content_encoder(self.buffer.clone(), msg);

        // render message
        {
            let mut buffer = self.buffer.get_mut();
            if let Body::Binary(ref bytes) = *msg.body() {
                buffer.reserve(256 + msg.headers().len() * AVERAGE_HEADER_SIZE + bytes.len());
            } else {
                buffer.reserve(256 + msg.headers().len() * AVERAGE_HEADER_SIZE);
            }

            if msg.upgrade() {
                self.flags.insert(Flags::UPGRADE);
            }

            // status line
            let _ = write!(buffer, "{} {} {:?}\r\n",
                           msg.method(),
                           msg.uri().path_and_query().map(|u| u.as_str()).unwrap_or("/"),
                           msg.version());

            // write headers
            for (key, value) in msg.headers() {
                let v = value.as_ref();
                let k = key.as_str().as_bytes();
                buffer.reserve(k.len() + v.len() + 4);
                buffer.put_slice(k);
                buffer.put_slice(b": ");
                buffer.put_slice(v);
                buffer.put_slice(b"\r\n");
            }

            // set date header
            if !msg.headers().contains_key(DATE) {
                buffer.extend_from_slice(b"date: ");
                set_date(&mut buffer);
                buffer.extend_from_slice(b"\r\n\r\n");
            } else {
                buffer.extend_from_slice(b"\r\n");
            }
            self.headers_size = buffer.len() as u32;

            if msg.body().is_binary() {
                if let Body::Binary(bytes) = msg.replace_body(Body::Empty) {
                    self.written += bytes.len() as u64;
                    self.encoder.write(bytes)?;
                }
            } else {
                self.buffer_capacity = msg.write_buffer_capacity();
            }
        }
        Ok(())
    }

    pub fn write(&mut self, payload: Binary) -> io::Result<WriterState> {
        self.written += payload.len() as u64;
        if !self.flags.contains(Flags::DISCONNECTED) {
            if self.flags.contains(Flags::UPGRADE) {
                self.buffer.extend(payload);
            } else {
                self.encoder.write(payload)?;
            }
        }

        if self.buffer.len() > self.buffer_capacity {
            Ok(WriterState::Pause)
        } else {
            Ok(WriterState::Done)
        }
    }

    pub fn write_eof(&mut self) -> io::Result<()> {
        self.encoder.write_eof()?;

        if self.encoder.is_eof() {
            Ok(())
        } else {
            Err(io::Error::new(io::ErrorKind::Other,
                               "Last payload item, but eof is not reached"))
        }
    }

    #[inline]
    pub fn poll_completed<T: AsyncWrite>(&mut self, stream: &mut T, shutdown: bool)
                                         -> Poll<(), io::Error>
    {
        match self.write_to_stream(stream) {
            Ok(WriterState::Done) => {
                if shutdown {
                    stream.shutdown()
                } else {
                    Ok(Async::Ready(()))
                }
            },
            Ok(WriterState::Pause) => Ok(Async::NotReady),
            Err(err) => Err(err)
        }
    }
}

fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder {
    let version = req.version();
    let mut body = req.replace_body(Body::Empty);
    let mut encoding = req.content_encoding();

    let transfer = match body {
        Body::Empty => {
            req.headers_mut().remove(CONTENT_LENGTH);
            TransferEncoding::length(0, buf)
        },
        Body::Binary(ref mut bytes) => {
            if encoding.is_compression() {
                let tmp = SharedBytes::default();
                let transfer = TransferEncoding::eof(tmp.clone());
                let mut enc = match encoding {
                    ContentEncoding::Deflate => ContentEncoder::Deflate(
                        DeflateEncoder::new(transfer, Compression::default())),
                    ContentEncoding::Gzip => ContentEncoder::Gzip(
                        GzEncoder::new(transfer, Compression::default())),
                    ContentEncoding::Br => ContentEncoder::Br(
                        BrotliEncoder::new(transfer, 5)),
                    ContentEncoding::Identity => ContentEncoder::Identity(transfer),
                    ContentEncoding::Auto => unreachable!()
                };
                // TODO return error!
                let _ = enc.write(bytes.clone());
                let _ = enc.write_eof();
                *bytes = Binary::from(tmp.take());

                req.headers_mut().insert(
                    CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
                encoding = ContentEncoding::Identity;
            }
            let mut b = BytesMut::new();
            let _ = write!(b, "{}", bytes.len());
            req.headers_mut().insert(
                CONTENT_LENGTH, HeaderValue::try_from(b.freeze()).unwrap());
            TransferEncoding::eof(buf)
        },
        Body::Streaming(_) | Body::Actor(_) => {
            if req.upgrade() {
                if version == Version::HTTP_2 {
                    error!("Connection upgrade is forbidden for HTTP/2");
                } else {
                    req.headers_mut().insert(CONNECTION, HeaderValue::from_static("upgrade"));
                }
                if encoding != ContentEncoding::Identity {
                    encoding = ContentEncoding::Identity;
                    req.headers_mut().remove(CONTENT_ENCODING);
                }
                TransferEncoding::eof(buf)
            } else {
                streaming_encoding(buf, version, req)
            }
        }
    };

    if encoding.is_compression() {
        req.headers_mut().insert(
            CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
    }

    req.replace_body(body);
    match encoding {
        ContentEncoding::Deflate => ContentEncoder::Deflate(
            DeflateEncoder::new(transfer, Compression::default())),
        ContentEncoding::Gzip => ContentEncoder::Gzip(
            GzEncoder::new(transfer, Compression::default())),
        ContentEncoding::Br => ContentEncoder::Br(
            BrotliEncoder::new(transfer, 5)),
        ContentEncoding::Identity | ContentEncoding::Auto => ContentEncoder::Identity(transfer),
    }
}

fn streaming_encoding(buf: SharedBytes, version: Version, req: &mut ClientRequest)
                      -> TransferEncoding {
    if req.chunked() {
        // Enable transfer encoding
        req.headers_mut().remove(CONTENT_LENGTH);
        if version == Version::HTTP_2 {
            req.headers_mut().remove(TRANSFER_ENCODING);
            TransferEncoding::eof(buf)
        } else {
            req.headers_mut().insert(
                TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
            TransferEncoding::chunked(buf)
        }
    } else {
        // if Content-Length is specified, then use it as length hint
        let (len, chunked) =
            if let Some(len) = req.headers().get(CONTENT_LENGTH) {
                // Content-Length
                if let Ok(s) = len.to_str() {
                    if let Ok(len) = s.parse::<u64>() {
                        (Some(len), false)
                    } else {
                        error!("illegal Content-Length: {:?}", len);
                        (None, false)
                    }
                } else {
                    error!("illegal Content-Length: {:?}", len);
                    (None, false)
                }
            } else {
                (None, true)
            };

        if !chunked {
            if let Some(len) = len {
                TransferEncoding::length(len, buf)
            } else {
                TransferEncoding::eof(buf)
            }
        } else {
            // Enable transfer encoding
            match version {
                Version::HTTP_11 => {
                    req.headers_mut().insert(
                        TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
                    TransferEncoding::chunked(buf)
                },
                _ => {
                    req.headers_mut().remove(TRANSFER_ENCODING);
                    TransferEncoding::eof(buf)
                }
            }
        }
    }
}

// "Sun, 06 Nov 1994 08:49:37 GMT".len()
pub const DATE_VALUE_LENGTH: usize = 29;

fn set_date(dst: &mut BytesMut) {
    CACHED.with(|cache| {
        let mut cache = cache.borrow_mut();
        let now = time::get_time();
        if now > cache.next_update {
            cache.update(now);
        }
        dst.extend_from_slice(cache.buffer());
    })
}

struct CachedDate {
    bytes: [u8; DATE_VALUE_LENGTH],
    next_update: time::Timespec,
}

thread_local!(static CACHED: RefCell<CachedDate> = RefCell::new(CachedDate {
    bytes: [0; DATE_VALUE_LENGTH],
    next_update: time::Timespec::new(0, 0),
}));

impl CachedDate {
    fn buffer(&self) -> &[u8] {
        &self.bytes[..]
    }

    fn update(&mut self, now: time::Timespec) {
        write!(&mut self.bytes[..], "{}", time::at_utc(now).rfc822()).unwrap();
        self.next_update = now + Duration::seconds(1);
        self.next_update.nsec = 0;
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use llvm_sys::core;
use llvm_sys::prelude::{
  LLVMContextRef,
  LLVMTypeRef
};
use libc::c_uint;

pub struct Ty(pub LLVMTypeRef);
impl_display!(Ty, LLVMPrintTypeToString);

impl Ty {
  #[inline(always)]
  pub fn as_ptr(&self) -> LLVMTypeRef { self.0 }
}

pub trait LLVMTy {
  fn llvm_ty(ctx: LLVMContextRef) -> Ty;
}

macro_rules! impl_llvm_ty (
  ($ty:ty, $func:expr) => (
    impl LLVMTy for $ty {
      fn llvm_ty(ctx: LLVMContextRef) -> Ty
      {
        Ty(unsafe{$func(ctx)})
      }
    }
  );
);

impl_llvm_ty!(i8,  core::LLVMInt8TypeInContext);
impl_llvm_ty!(u8,  core::LLVMInt8TypeInContext);
impl_llvm_ty!(i16, core::LLVMInt16TypeInContext);
impl_llvm_ty!(u16, core::LLVMInt16TypeInContext);
impl_llvm_ty!(i32, core::LLVMInt32TypeInContext);
impl_llvm_ty!(u32, core::LLVMInt32TypeInContext);
impl_llvm_ty!(i64, core::LLVMInt64TypeInContext);
impl_llvm_ty!(u64, core::LLVMInt64TypeInContext);
impl_llvm_ty!(f32, core::LLVMFloatTypeInContext);
impl_llvm_ty!(f64, core::LLVMDoubleTypeInContext);

impl LLVMTy for usize {
  fn llvm_ty(ctx: LLVMContextRef) -> Ty
  {
    Ty(unsafe{core::LLVMIntTypeInContext(ctx, ::std::mem::size_of::<isize>() as c_uint * 8)})
  }
}

impl LLVMTy for isize {
  fn llvm_ty(ctx: LLVMContextRef) -> Ty
  {
    Ty(unsafe{core::LLVMIntTypeInContext(ctx, ::std::mem::size_of::<isize>() as c_uint * 8)})
  }
}

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

	#[test]
	pub fn test_types()
	{
		let jit = JitCompiler::new("test").ok().unwrap();
    let ctx = jit.context();
		assert_eq!("i8",     format!("{}", i8::llvm_ty(ctx)));
		assert_eq!("i16",    format!("{}", i16::llvm_ty(ctx)));
		assert_eq!("i32",    format!("{}", i32::llvm_ty(ctx)));
		assert_eq!("i64",    format!("{}", i64::llvm_ty(ctx)));
		assert_eq!("float",  format!("{}", f32::llvm_ty(ctx)));
		assert_eq!("double", format!("{}", f64::llvm_ty(ctx)));

		//assert_eq!("[10 x double]",  format!("{}", Type::array_ty(&Type::f64_ty(&ctx), 10)));
	}
}<commit_msg>Add FunctionType and its APIs.<commit_after>#![allow(dead_code)]
use std::fmt;
use std::mem;

use llvm_sys::core;
use llvm_sys::prelude::{
  LLVMContextRef,
  LLVMTypeRef
};
use libc::c_uint;

pub struct Ty(pub LLVMTypeRef);
impl_display!(Ty, LLVMPrintTypeToString);

impl Ty {
  #[inline(always)]
  pub fn as_ptr(&self) -> LLVMTypeRef { self.0 }
}

/// A function signature type.
pub struct FunctionType(pub LLVMTypeRef);
impl_display!(FunctionType, LLVMPrintTypeToString);

impl FunctionType {

  /// Returns the number of parameters this signature takes.
  pub fn num_params(&self) -> usize {
    unsafe { core::LLVMCountParamTypes(self.0) as usize }
  }

  /// Returns a vector of this signature's parameters' types.
  pub fn get_params(&self) -> Vec<Ty> {
  	unsafe {
    	let count = core::LLVMCountParamTypes(self.0);
      let mut types: Vec<LLVMTypeRef> = (0..count).map(|_| mem::uninitialized()).collect();
      core::LLVMGetParamTypes(self.0, types.as_mut_ptr() as *mut LLVMTypeRef);
      types.into_iter().map(|t| Ty(t)).collect::<Vec<Ty>>()
    }
  }

  /// Returns the type that this function returns.
  pub fn get_return(&self) -> Ty {
    Ty(unsafe { core::LLVMGetReturnType(self.0)})
  }
}

/*
impl From<FunctionType> for Ty {
  fn from(ty: FunctionType) -> Ty {
    Ty(ty.0)
  }
}

impl From<Ty> for FunctionType {
  fn from(ty: Ty) -> FunctionType {
    FunctionType(ty.0)
  }
}
*/

pub trait LLVMTy {
  fn llvm_ty(ctx: LLVMContextRef) -> Ty;
}

macro_rules! impl_llvm_ty (
  ($ty:ty, $func:expr) => (
    impl LLVMTy for $ty {
      fn llvm_ty(ctx: LLVMContextRef) -> Ty
      {
        Ty(unsafe{$func(ctx)})
      }
    }
  );
);

impl_llvm_ty!(i8,  core::LLVMInt8TypeInContext);
impl_llvm_ty!(u8,  core::LLVMInt8TypeInContext);
impl_llvm_ty!(i16, core::LLVMInt16TypeInContext);
impl_llvm_ty!(u16, core::LLVMInt16TypeInContext);
impl_llvm_ty!(i32, core::LLVMInt32TypeInContext);
impl_llvm_ty!(u32, core::LLVMInt32TypeInContext);
impl_llvm_ty!(i64, core::LLVMInt64TypeInContext);
impl_llvm_ty!(u64, core::LLVMInt64TypeInContext);
impl_llvm_ty!(f32, core::LLVMFloatTypeInContext);
impl_llvm_ty!(f64, core::LLVMDoubleTypeInContext);

impl LLVMTy for usize {
  fn llvm_ty(ctx: LLVMContextRef) -> Ty
  {
    Ty(unsafe{core::LLVMIntTypeInContext(ctx, ::std::mem::size_of::<isize>() as c_uint * 8)})
  }
}

impl LLVMTy for isize {
  fn llvm_ty(ctx: LLVMContextRef) -> Ty
  {
    Ty(unsafe{core::LLVMIntTypeInContext(ctx, ::std::mem::size_of::<isize>() as c_uint * 8)})
  }
}

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

	#[test]
	pub fn test_types()
	{
		let jit = JitCompiler::new("test").ok().unwrap();
    let ctx = jit.context();
		assert_eq!("i8",     format!("{}", i8::llvm_ty(ctx)));
		assert_eq!("i16",    format!("{}", i16::llvm_ty(ctx)));
		assert_eq!("i32",    format!("{}", i32::llvm_ty(ctx)));
		assert_eq!("i64",    format!("{}", i64::llvm_ty(ctx)));
		assert_eq!("float",  format!("{}", f32::llvm_ty(ctx)));
		assert_eq!("double", format!("{}", f64::llvm_ty(ctx)));

		//assert_eq!("[10 x double]",  format!("{}", Type::array_ty(&Type::f64_ty(&ctx), 10)));
	}
}<|endoftext|>


<commit_before>use crate::discord_client::CommandHandler;

pub struct PingCommand;

impl CommandHandler for PingCommand {
    fn process_command(
        &self,
        _command: &str,
        send_message_callback: &Fn(&str) -> (),
    ) -> Result<(), Box<std::error::Error>> {
        send_message_callback("Pong!");

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use std::sync::{Arc, Mutex};
    use std::thread;
    use std::time::{Duration, Instant};
    use super::*;

    #[test]
    fn test_ping() {
        let ping = PingCommand;

        let result = Arc::new(Mutex::new(Box::new(String::new())));
        let closure_result = result.clone();
        assert!(ping.process_command("", &|message| *closure_result.lock().unwrap() = Box::new(String::from(message))).is_ok());

        let expected_message = String::from("Pong!");
        let timeout = Instant::now();
        while (timeout.elapsed() < Duration::from_secs(2)) && (**result.lock().unwrap() != expected_message) {
            thread::sleep(Duration::from_millis(200));
        }

        assert_eq!(expected_message, **result.lock().unwrap());
    }
}<commit_msg>run rustfmt<commit_after>use crate::discord_client::CommandHandler;

pub struct PingCommand;

impl CommandHandler for PingCommand {
    fn process_command(
        &self,
        _command: &str,
        send_message_callback: &Fn(&str) -> (),
    ) -> Result<(), Box<std::error::Error>> {
        send_message_callback("Pong!");

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::{Arc, Mutex};
    use std::thread;
    use std::time::{Duration, Instant};

    #[test]
    fn test_ping() {
        let ping = PingCommand;

        let result = Arc::new(Mutex::new(Box::new(String::new())));
        let closure_result = result.clone();
        assert!(ping
            .process_command("", &|message| *closure_result.lock().unwrap() =
                Box::new(String::from(message)))
            .is_ok());

        let expected_message = String::from("Pong!");
        let timeout = Instant::now();
        while (timeout.elapsed() < Duration::from_secs(2))
            && (**result.lock().unwrap() != expected_message)
        {
            thread::sleep(Duration::from_millis(200));
        }

        assert_eq!(expected_message, **result.lock().unwrap());
    }
}
<|endoftext|>


<commit_before>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

extern crate ini;

// use std::str::FromStr;
// use std::fmt::Display;
use std::net::IpAddr;
use std::net::SocketAddr;

use self::ini::Ini;

use super::defaults;
use super::config::Config;
use super::config::ConfigListen;
use super::config::ConfigProxy;
use super::config::ConfigMemcached;

pub struct ReaderBuilder;
pub struct Reader;
struct ReaderGetter;

impl ReaderBuilder {
    pub fn new() -> Reader {
        Reader {}
    }
}

impl Reader {
    pub fn read(&self, path: &str) -> Config {
        debug!("reading config file: {}", path);

        let conf = Ini::load_from_file(path).unwrap();

        debug!("read config file: {}", path);

        self.make(&conf)
    }

    fn make(&self, conf: &Ini) -> Config {
        Config {
            listen: ConfigListen {
                inet: ReaderGetter::get_inet(&conf, "listen", "inet",
                "host", "port", defaults::LISTEN_HOST,
                defaults::LISTEN_PORT)
            },

            proxy: ConfigProxy {
                shard: ReaderGetter::get_u8(&conf, "proxy",
                "shard", defaults::PROXY_SHARD),

                inet: ReaderGetter::get_inet(&conf, "proxy", "inet",
                "host", "port", defaults::PROXY_HOST,
                defaults::PROXY_PORT)
            },

            memcached: ConfigMemcached {
                inet: ReaderGetter::get_inet(&conf, "memcached", "inet",
                "host", "port", defaults::MEMCACHED_HOST,
                defaults::MEMCACHED_PORT),

                max_key_size: ReaderGetter::get_u32(&conf, "memcached",
                "max_key_size", defaults::MEMCACHED_MAX_KEY_SIZE),

                max_key_expiration: ReaderGetter::get_u32(&conf, "memcached",
                "max_key_expiration", defaults::MEMCACHED_MAX_KEY_EXPIRATION),

                pool_size: ReaderGetter::get_u8(&conf, "memcached",
                "pool_size", defaults::MEMCACHED_POOL_SIZE),

                reconnect: ReaderGetter::get_u16(&conf, "memcached",
                "reconnect", defaults::MEMCACHED_RECONNECT),

                timeout: ReaderGetter::get_u16(&conf, "memcached",
                "timeout", defaults::MEMCACHED_TIMEOUT)
            }
        }
    }
}

impl ReaderGetter {
    fn get_inet(
        conf: &Ini, group: &'static str, key: &'static str,
        key_host: &'static str, key_port: &'static str,
        default_host: &'static str, default_port: &'static str
    ) -> SocketAddr {
        let value_host = (*conf).get_from_or(Some(group), key_host,
            default_host).parse::<IpAddr>().unwrap();

        let value_port = (*conf).get_from_or(Some(group), key_port,
            default_port).parse::<u16>().unwrap();

        let value_inet = SocketAddr::new(value_host, value_port);

        debug!("parsed @{}:{} <inet> => {}", group, key,
            value_inet);

        value_inet
    }

    // fn get_generic<T>(
    //     conf: &Ini, group: &'static str, key: &'static str,
    //     default: &'static str
    // ) -> T where T: FromStr + Display {
    //     let value = (*conf).get_from_or(Some(group), key,
    //         default).parse::<T>().unwrap();

    //     debug!("parsed @{}:{} <T> => {}", group, key, value);

    //     value
    // }

    fn get_u8(
        conf: &Ini, group: &'static str, key: &'static str,
        default: &'static str
    ) -> u8 {
        let value_u8 = (*conf).get_from_or(Some(group), key,
            default).parse::<u8>().unwrap();

        debug!("parsed @{}:{} <u8> => {}", group, key, value_u8);

        value_u8
    }

    fn get_u16(
        conf: &Ini, group: &'static str, key: &'static str,
        default: &'static str
    ) -> u16 {
        let value_u16 = (*conf).get_from_or(Some(group), key,
            default).parse::<u16>().unwrap();

        debug!("parsed @{}:{} <u16> => {}", group, key, value_u16);

        value_u16
    }

    fn get_u32(
        conf: &Ini, group: &'static str, key: &'static str,
        default: &'static str
    ) -> u32 {
        let value_u32 = (*conf).get_from_or(Some(group), key,
            default).parse::<u32>().unwrap();

        debug!("parsed @{}:{} <u32> => {}", group, key, value_u32);

        value_u32
    }
}
<commit_msg>Generics on config. reader<commit_after>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

extern crate ini;

use std::str::FromStr;
use std::fmt::Debug;
use std::fmt::Display;
use std::net::IpAddr;
use std::net::SocketAddr;

use self::ini::Ini;

use super::defaults;
use super::config::Config;
use super::config::ConfigListen;
use super::config::ConfigProxy;
use super::config::ConfigMemcached;

pub struct ReaderBuilder;
pub struct Reader;
struct ReaderGetter;

impl ReaderBuilder {
    pub fn new() -> Reader {
        Reader {}
    }
}

impl Reader {
    pub fn read(&self, path: &str) -> Config {
        debug!("reading config file: {}", path);

        let conf = Ini::load_from_file(path).unwrap();

        debug!("read config file: {}", path);

        self.make(&conf)
    }

    fn make(&self, conf: &Ini) -> Config {
        Config {
            listen: ConfigListen {
                inet: ReaderGetter::get_inet(&conf, "listen", "inet",
                "host", "port", defaults::LISTEN_HOST,
                defaults::LISTEN_PORT)
            },

            proxy: ConfigProxy {
                shard: ReaderGetter::get_generic(&conf, "proxy",
                "shard", defaults::PROXY_SHARD),

                inet: ReaderGetter::get_inet(&conf, "proxy", "inet",
                "host", "port", defaults::PROXY_HOST,
                defaults::PROXY_PORT)
            },

            memcached: ConfigMemcached {
                inet: ReaderGetter::get_inet(&conf, "memcached", "inet",
                "host", "port", defaults::MEMCACHED_HOST,
                defaults::MEMCACHED_PORT),

                max_key_size: ReaderGetter::get_generic(&conf, "memcached",
                "max_key_size", defaults::MEMCACHED_MAX_KEY_SIZE),

                max_key_expiration: ReaderGetter::get_generic(&conf,
                    "memcached", "max_key_expiration",
                    defaults::MEMCACHED_MAX_KEY_EXPIRATION),

                pool_size: ReaderGetter::get_generic(&conf, "memcached",
                "pool_size", defaults::MEMCACHED_POOL_SIZE),

                reconnect: ReaderGetter::get_generic(&conf, "memcached",
                "reconnect", defaults::MEMCACHED_RECONNECT),

                timeout: ReaderGetter::get_generic(&conf, "memcached",
                "timeout", defaults::MEMCACHED_TIMEOUT)
            }
        }
    }
}

impl ReaderGetter {
    fn get_inet(
        conf: &Ini, group: &'static str, key: &'static str,
        key_host: &'static str, key_port: &'static str,
        default_host: &'static str, default_port: &'static str
    ) -> SocketAddr {
        let value_host = (*conf).get_from_or(Some(group), key_host,
            default_host).parse::<IpAddr>().unwrap();

        let value_port = (*conf).get_from_or(Some(group), key_port,
            default_port).parse::<u16>().unwrap();

        let value_inet = SocketAddr::new(value_host, value_port);

        debug!("parsed @{}:{} => {}", group, key,
            value_inet);

        value_inet
    }

    fn get_generic<T>(
        conf: &Ini, group: &'static str, key: &'static str,
        default: &'static str
    ) -> T where T: Display + FromStr, <T as FromStr>::Err: Debug {
        let value = (*conf).get_from_or(Some(group), key,
            default).parse::<T>().unwrap();

        debug!("parsed @{}:{} => {}", group, key, value);

        value
    }
}
<|endoftext|>


<commit_before>use std;
import std::io;
import std::io::{writer_util, reader_util};
import std::map;
import result;

export rowreader, rowaccess, rowiter,
       new_reader, new_reader_readlen,
       hashmap_iter, hashmap_iter_cols,
       hashmap_iter_with_map;

enum state {
    fieldstart(bool),
    infield(uint, uint),
    inescapedfield(uint, uint),
    inquote(uint, uint)
}

type rowreader = {
    readlen: uint,
    delim: char,
    quote: char,
    f : io::reader,
    mutable offset : uint,
    mutable buffers : [@[char]],
    mutable state : state
};

type row = {
    fields : [ fieldtype ]
};

type bufferdescr = {
    escaped: bool,
    buffers: [@[char]],
    start: uint,
    end: uint
};

enum fieldtype {
    emptyfield(),
    bufferfield(bufferdescr)
}

iface rowiter {
    fn readrow() -> result::t<row, str>;
}

iface rowaccess {
    fn len() -> uint;
    fn getchars(uint) -> [char];
    fn getstr(uint) -> str;
}

fn new_reader(+f: io::reader, +delim: char, +quote: char) -> rowreader {
    {
        readlen: 1024u,
        delim: delim,
        quote: quote,
        f: f,
        mutable offset : 0u,
        mutable buffers : [],
        mutable state : fieldstart(false)
    }
}

fn new_reader_readlen(+f: io::reader, +delim: char, +quote: char, rl: uint) -> rowreader {
    {
        readlen: rl,
        delim: delim,
        quote: quote,
        f: f,
        mutable offset : 0u,
        mutable buffers : [],
        mutable state : fieldstart(false)
    }
}

impl of rowaccess for row {
    fn len() -> uint {
        vec::len(self.fields)
    }
    fn getchars(field: uint) -> [char] {
        fn unescape(escaped: [char]) -> [char] {
            let r : [char] = [];
            vec::reserve(r, vec::len(escaped));
            let in_q = false;
            for c in escaped {
                if in_q {
                    assert(c == '"');
                    in_q = false;
                } else {
                    in_q = c == '"';
                    r += [c];
                }
            }
            ret r;
        }
        alt self.fields[field] {
            emptyfield() { ret []; }
            bufferfield(desc) {
                let buf = [];
                {
                    let i = 0u;
                    while i < vec::len(desc.buffers) {
                        let from = if (i == 0u)
                            { desc.start } else { 0u };
                        let to = if (i == vec::len(desc.buffers) - 1u)
                            { desc.end } else { vec::len(*desc.buffers[i]) };
                        buf += vec::slice(*desc.buffers[i], from, to);
                        i = i + 1u;
                    }
                }
                if desc.escaped {
                    buf = unescape(buf);
                }
                ret buf;
            }
        };
    }
    fn getstr(field: uint) -> str {
        ret str::from_chars(self.getchars(field));
    }
    fn getall() -> [str] {
        let a = [];
        self.map() { |s|
            a += [s];
        }
        ret a;
    }
    fn map(f: fn(s: str)) {
        let i = 0u;
        let len = self.len();
        while i < len {
            f(self.getstr(i));
            i += 1u;
        }
    }
}

impl of rowiter for rowreader {
    fn readrow() -> result::t<row, str> {
        fn row_from_buf(self: rowreader, &fields: [fieldtype]) -> bool {
            fn new_bufferfield(self: rowreader, escaped: bool, sb: uint, so: uint, eo: uint) -> fieldtype {
                let eb = vec::len(self.buffers);
                let sb = sb, so = so, eo = eo;
                if escaped {
                    so += 1u;
                    if so > vec::len(*self.buffers[sb]) {
                        sb += 1u;
                        so = vec::len(*self.buffers[sb]) - 1u;
                    }
                    if eo > 0u {
                        eo -= 1u;
                    } else {
                        eb -= 1u;
                        eo = vec::len(*self.buffers[sb]) - 1u;
                    }
                }
                bufferfield({ escaped: escaped, buffers: vec::slice(self.buffers, sb, eb), start: so, end: eo })
            }
            let cbuffer = vec::len(self.buffers) - 1u;
            let buf: @[char] = self.buffers[cbuffer];
            while self.offset < vec::len(*buf) {
                let coffset = self.offset;
                let c : char = buf[coffset];
                self.offset += 1u;
                alt self.state {
                    fieldstart(after_delim) {
                        if c == self.quote {
                            self.state = inescapedfield(cbuffer, coffset);
                        } else if c == '\n' {
                            if after_delim {
                                fields += [emptyfield];
                            }
                            ret true;
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [emptyfield];
                        } else {
                            self.state = infield(cbuffer, coffset);
                        }
                    }
                    infield(b,o) {
                        if c == '\n' {
                            fields += [new_bufferfield(self, false, b, o, coffset)];
                            ret true;
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, false, b, o, coffset)];
                        }
                    }
                    inescapedfield(b, o) {
                        if c == self.quote {
                            self.state = inquote(b, o);
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                        }
                    }
                    inquote(b, o) {
                        if c == '\n' {
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                            ret true;
                        } else if c == self.quote {
                            self.state = inescapedfield(b, o);
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                        }
                        // swallow odd chars, eg. space between field and "
                    }
                }
            }
            ret false;
        }

        self.state = fieldstart(false);
        let do_read = vec::len(self.buffers) == 0u;
        let fields = [];
        while true {
            if do_read {
                let data: @[char] = @self.f.read_chars(self.readlen);
                if vec::len(*data) == 0u {
                    ret result::err("EOF");
                }
                self.buffers += [data];
                self.offset = 0u;
            }

            if row_from_buf(self, fields) {
                let r: row = { fields: fields };
                fields = [];
                if vec::len(self.buffers) > 1u {
                    self.buffers = vec::slice(self.buffers, vec::len(self.buffers) - 1u, vec::len(self.buffers));
                }
                ret result::ok(r);
            }
            do_read = true;
        }
        ret result::err("unreachable");
    }
}

fn hashmap_iter_cols(r: rowreader, cols: [str], f: fn(map::hashmap<str, str>)) {
    while true {
        let res = r.readrow();
        if result::failure(res) {
            break;
        }
        let m : map::hashmap<str, str> = map::new_str_hash();
        let col = 0u;
        result::get(res).map() { |s|
            m.insert(cols[col], s);
            col += 1u;
        };
        f(m);
    }
}

// reads the first row as a header, to derive keys for a hashmap
// emitted for each subsequent row
fn hashmap_iter(r: rowreader, f: fn(map::hashmap<str, str>)) {
    let res = r.readrow();
    alt res {
        result::ok(row) {
            hashmap_iter_cols(r, result::get(res).getall(), f);
        }
        result::err(_) { }
    }
}

// as hashmap_iter, but first apply 'hc' to each header; allows
// cleaning up headers
fn hashmap_iter_with_map(r: rowreader, hc: fn(&&h: str) -> str, f: fn(map::hashmap<str, str>)) {
    let res = r.readrow();
    alt res {
        result::ok(row) {
            let cols : [str] = vec::map(result::get(res).getall(), hc);
            hashmap_iter_cols(r, cols, f);
        }
        result::err(_) { }
    }
}

#[cfg(test)]
mod test {
    fn rowmatch(testdata: str, expected: [[str]]) {
        let chk = fn@(mk: fn(io::reader) -> rowreader) {
            let f = io::string_reader(testdata);
            let r = mk(f);
            let i = 0u;
            while true {
                let res = r.readrow();
                if result::failure(res) {
                    break;
                }
                let row = result::get(res);
                let expect = expected[i];

                assert(row.len() == vec::len(expect));
                let j = 0u;
                while j < row.len() {
                    assert(row.getstr(j) == expect[j]);
                    j += 1u;
                }
                i += 1u;
            }
            assert(i == vec::len(expected));
        };
        // test default reader params
        chk() { |inp|
            new_reader_readlen(inp, ',', '"', 2u)
        };
        // test continuations over read buffers
        let j = 1u;
        while j < str::len(testdata) {
            chk() { |inp|
                new_reader_readlen(inp, ',', '"', j)
            };
            j += 1u;
        }
    }

    #[test]
    fn test_simple() {
        rowmatch("a,b,c,d\n1,2,3,4\n",
                 [["a", "b", "c", "d"], ["1", "2", "3", "4"]]);
    }

    #[test]
    fn test_trailing_comma() {
        rowmatch("a,b,c,d\n1,2,3,4,\n",
                 [["a", "b", "c", "d"], ["1", "2", "3", "4", ""]]);
    }

    #[test]
    fn test_leading_comma() {
        rowmatch("a,b,c,d\n,1,2,3,4\n",
                 [["a", "b", "c", "d"], ["", "1", "2", "3", "4"]]);
    }

    #[test]
    fn test_quote_simple() {
        rowmatch("\"Hello\",\"There\"\na,b,\"c\",d\n",
                 [["Hello", "There"], ["a", "b", "c", "d"]]);
    }

    #[test]
    fn test_quote_nested() {
        rowmatch("\"Hello\",\"There is a \"\"fly\"\" in my soup\"\na,b,\"c\",d\n",
                 [["Hello", "There is a \"fly\" in my soup"], ["a", "b", "c", "d"]]);
    }

    #[test]
    fn test_blank_line() {
        rowmatch("\n\n", [[], []]);
    }
}

<commit_msg>iter changes<commit_after>use std;
import std::io;
import std::io::{writer_util, reader_util};
import std::map;
import result;

export rowreader, rowaccess, rowiter,
       new_reader, new_reader_readlen,
       hashmap_iter, hashmap_iter_full;

enum state {
    fieldstart(bool),
    infield(uint, uint),
    inescapedfield(uint, uint),
    inquote(uint, uint)
}

type rowreader = {
    readlen: uint,
    delim: char,
    quote: char,
    f : io::reader,
    mutable offset : uint,
    mutable buffers : [@[char]],
    mutable state : state
};

type row = {
    fields : [ fieldtype ]
};

type bufferdescr = {
    escaped: bool,
    buffers: [@[char]],
    start: uint,
    end: uint
};

enum fieldtype {
    emptyfield(),
    bufferfield(bufferdescr)
}

iface rowiter {
    fn readrow() -> result::t<row, str>;
}

iface rowaccess {
    fn len() -> uint;
    fn getchars(uint) -> [char];
    fn getstr(uint) -> str;
}

fn new_reader(+f: io::reader, +delim: char, +quote: char) -> rowreader {
    {
        readlen: 1024u,
        delim: delim,
        quote: quote,
        f: f,
        mutable offset : 0u,
        mutable buffers : [],
        mutable state : fieldstart(false)
    }
}

fn new_reader_readlen(+f: io::reader, +delim: char, +quote: char, rl: uint) -> rowreader {
    {
        readlen: rl,
        delim: delim,
        quote: quote,
        f: f,
        mutable offset : 0u,
        mutable buffers : [],
        mutable state : fieldstart(false)
    }
}

impl of rowaccess for row {
    fn len() -> uint {
        vec::len(self.fields)
    }
    fn getchars(field: uint) -> [char] {
        fn unescape(escaped: [char]) -> [char] {
            let r : [char] = [];
            vec::reserve(r, vec::len(escaped));
            let in_q = false;
            for c in escaped {
                if in_q {
                    assert(c == '"');
                    in_q = false;
                } else {
                    in_q = c == '"';
                    r += [c];
                }
            }
            ret r;
        }
        alt self.fields[field] {
            emptyfield() { ret []; }
            bufferfield(desc) {
                let buf = [];
                {
                    let i = 0u;
                    while i < vec::len(desc.buffers) {
                        let from = if (i == 0u)
                            { desc.start } else { 0u };
                        let to = if (i == vec::len(desc.buffers) - 1u)
                            { desc.end } else { vec::len(*desc.buffers[i]) };
                        buf += vec::slice(*desc.buffers[i], from, to);
                        i = i + 1u;
                    }
                }
                if desc.escaped {
                    buf = unescape(buf);
                }
                ret buf;
            }
        };
    }
    fn getstr(field: uint) -> str {
        ret str::from_chars(self.getchars(field));
    }
    fn getall() -> [str] {
        let a = [];
        self.map() { |s|
            a += [s];
        }
        ret a;
    }
    fn map(f: fn(s: str)) {
        let i = 0u;
        let len = self.len();
        while i < len {
            f(self.getstr(i));
            i += 1u;
        }
    }
}

impl of rowiter for rowreader {
    fn readrow() -> result::t<row, str> {
        fn row_from_buf(self: rowreader, &fields: [fieldtype]) -> bool {
            fn new_bufferfield(self: rowreader, escaped: bool, sb: uint, so: uint, eo: uint) -> fieldtype {
                let eb = vec::len(self.buffers);
                let sb = sb, so = so, eo = eo;
                if escaped {
                    so += 1u;
                    if so > vec::len(*self.buffers[sb]) {
                        sb += 1u;
                        so = vec::len(*self.buffers[sb]) - 1u;
                    }
                    if eo > 0u {
                        eo -= 1u;
                    } else {
                        eb -= 1u;
                        eo = vec::len(*self.buffers[sb]) - 1u;
                    }
                }
                bufferfield({ escaped: escaped, buffers: vec::slice(self.buffers, sb, eb), start: so, end: eo })
            }
            let cbuffer = vec::len(self.buffers) - 1u;
            let buf: @[char] = self.buffers[cbuffer];
            while self.offset < vec::len(*buf) {
                let coffset = self.offset;
                let c : char = buf[coffset];
                self.offset += 1u;
                alt self.state {
                    fieldstart(after_delim) {
                        if c == self.quote {
                            self.state = inescapedfield(cbuffer, coffset);
                        } else if c == '\n' {
                            if after_delim {
                                fields += [emptyfield];
                            }
                            ret true;
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [emptyfield];
                        } else {
                            self.state = infield(cbuffer, coffset);
                        }
                    }
                    infield(b,o) {
                        if c == '\n' {
                            fields += [new_bufferfield(self, false, b, o, coffset)];
                            ret true;
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, false, b, o, coffset)];
                        }
                    }
                    inescapedfield(b, o) {
                        if c == self.quote {
                            self.state = inquote(b, o);
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                        }
                    }
                    inquote(b, o) {
                        if c == '\n' {
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                            ret true;
                        } else if c == self.quote {
                            self.state = inescapedfield(b, o);
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                        }
                        // swallow odd chars, eg. space between field and "
                    }
                }
            }
            ret false;
        }

        self.state = fieldstart(false);
        let do_read = vec::len(self.buffers) == 0u;
        let fields = [];
        while true {
            if do_read {
                let data: @[char] = @self.f.read_chars(self.readlen);
                if vec::len(*data) == 0u {
                    ret result::err("EOF");
                }
                self.buffers += [data];
                self.offset = 0u;
            }

            if row_from_buf(self, fields) {
                let r: row = { fields: fields };
                fields = [];
                if vec::len(self.buffers) > 1u {
                    self.buffers = vec::slice(self.buffers, vec::len(self.buffers) - 1u, vec::len(self.buffers));
                }
                ret result::ok(r);
            }
            do_read = true;
        }
        ret result::err("unreachable");
    }
}

fn hashmap_iter_cols(r: rowreader, cols: [str], f: fn(map::hashmap<str, str>)) {
    while true {
        let res = r.readrow();
        if result::failure(res) {
            break;
        }
        let m : map::hashmap<str, str> = map::new_str_hash();
        let col = 0u;
        result::get(res).map() { |s|
            m.insert(cols[col], s);
            col += 1u;
        };
        f(m);
    }
}

// reads the first row as a header, to derive keys for a hashmap
// emitted for each subsequent row
fn hashmap_iter(r: rowreader, f: fn(map::hashmap<str, str>)) {
    let res = r.readrow();
    alt res {
        result::ok(row) {
            hashmap_iter_cols(r, result::get(res).getall(), f);
        }
        result::err(_) { }
    }
}

// as hashmap_iter, but first apply 'hc' to each header; allows
// cleaning up headers; also allows verification that heads are
// satisfactory
fn hashmap_iter_full(r: rowreader, hmap: fn(&&h: str) -> str, hver: fn(cols: [str]) -> bool, f: fn(map::hashmap<str, str>)) {
    let res = r.readrow();
    alt res {
        result::ok(row) {
            let cols : [str] = vec::map(result::get(res).getall(), hmap);
            if !hver(cols) {
                ret;
            }
            hashmap_iter_cols(r, cols, f);
        }
        result::err(_) { }
    }
}

#[cfg(test)]
mod test {
    fn rowmatch(testdata: str, expected: [[str]]) {
        let chk = fn@(mk: fn(io::reader) -> rowreader) {
            let f = io::string_reader(testdata);
            let r = mk(f);
            let i = 0u;
            while true {
                let res = r.readrow();
                if result::failure(res) {
                    break;
                }
                let row = result::get(res);
                let expect = expected[i];

                assert(row.len() == vec::len(expect));
                let j = 0u;
                while j < row.len() {
                    assert(row.getstr(j) == expect[j]);
                    j += 1u;
                }
                i += 1u;
            }
            assert(i == vec::len(expected));
        };
        // test default reader params
        chk() { |inp|
            new_reader_readlen(inp, ',', '"', 2u)
        };
        // test continuations over read buffers
        let j = 1u;
        while j < str::len(testdata) {
            chk() { |inp|
                new_reader_readlen(inp, ',', '"', j)
            };
            j += 1u;
        }
    }

    #[test]
    fn test_simple() {
        rowmatch("a,b,c,d\n1,2,3,4\n",
                 [["a", "b", "c", "d"], ["1", "2", "3", "4"]]);
    }

    #[test]
    fn test_trailing_comma() {
        rowmatch("a,b,c,d\n1,2,3,4,\n",
                 [["a", "b", "c", "d"], ["1", "2", "3", "4", ""]]);
    }

    #[test]
    fn test_leading_comma() {
        rowmatch("a,b,c,d\n,1,2,3,4\n",
                 [["a", "b", "c", "d"], ["", "1", "2", "3", "4"]]);
    }

    #[test]
    fn test_quote_simple() {
        rowmatch("\"Hello\",\"There\"\na,b,\"c\",d\n",
                 [["Hello", "There"], ["a", "b", "c", "d"]]);
    }

    #[test]
    fn test_quote_nested() {
        rowmatch("\"Hello\",\"There is a \"\"fly\"\" in my soup\"\na,b,\"c\",d\n",
                 [["Hello", "There is a \"fly\" in my soup"], ["a", "b", "c", "d"]]);
    }

    #[test]
    fn test_blank_line() {
        rowmatch("\n\n", [[], []]);
    }
}

<|endoftext|>


<commit_before>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg(test)]
mod tests;

#[doc(include = "char.md")]
#[cfg(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_char = u8;
#[doc(include = "char.md")]
#[cfg(not(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
)))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_char = i8;
#[doc(include = "schar.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_schar = i8;
#[doc(include = "uchar.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_uchar = u8;
#[doc(include = "short.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_short = i16;
#[doc(include = "ushort.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_ushort = u16;
#[doc(include = "int.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_int = i32;
#[doc(include = "uint.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_uint = u32;
#[doc(include = "long.md")]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_long = i32;
#[doc(include = "ulong.md")]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_ulong = u32;
#[doc(include = "long.md")]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_long = i64;
#[doc(include = "ulong.md")]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_ulong = u64;
#[doc(include = "longlong.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_longlong = i64;
#[doc(include = "ulonglong.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_ulonglong = u64;
#[doc(include = "float.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_float = f32;
#[doc(include = "double.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_double = f64;

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;
<commit_msg>library/std: raw: Add support for RISC-V 32-bit<commit_after>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg(test)]
mod tests;

#[doc(include = "char.md")]
#[cfg(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_char = u8;
#[doc(include = "char.md")]
#[cfg(not(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
)))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_char = i8;
#[doc(include = "schar.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_schar = i8;
#[doc(include = "uchar.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_uchar = u8;
#[doc(include = "short.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_short = i16;
#[doc(include = "ushort.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_ushort = u16;
#[doc(include = "int.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_int = i32;
#[doc(include = "uint.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_uint = u32;
#[doc(include = "long.md")]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_long = i32;
#[doc(include = "ulong.md")]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_ulong = u32;
#[doc(include = "long.md")]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_long = i64;
#[doc(include = "ulong.md")]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_ulong = u64;
#[doc(include = "longlong.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_longlong = i64;
#[doc(include = "ulonglong.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_ulonglong = u64;
#[doc(include = "float.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_float = f32;
#[doc(include = "double.md")]
#[stable(feature = "raw_os", since = "1.1.0")]
pub type c_double = f64;

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;
<|endoftext|>


<commit_before>
pub struct Events {
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

impl Events {
    pub fn is_up() -> bool {
        self.up
    }

    pub fn is_down() -> bool {
        self.down
    }

    pub fn is_left() -> bool {
        self.left
    }

    pub fn is_right() -> bool {
        self.right
    }

    pub fn handle_input() {
    }
}
<commit_msg>Events: process_input<commit_after>
pub struct Events {
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

impl Events {
    pub fn is_up() -> bool {
        self.up
    }

    pub fn is_down() -> bool {
        self.down
    }

    pub fn is_left() -> bool {
        self.left
    }

    pub fn is_right() -> bool {
        self.right
    }

    pub fn process_input(&mut self, input: &piston_window::Input) {
        use piston_window::{Input, Button, Key};

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = true; }
                    Button::Keyboard(Key::Down) => { self.down = true; }
                    Button::Keyboard(Key::Left) => { self.left = true; }
                    Button::Keyboard(Key::Right) => { self.right = true; }
                    _ => {}
                }
            }
            &Input::Release(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = false; }
                    Button::Keyboard(Key::Down) => { self.down = false; }
                    Button::Keyboard(Key::Left) => { self.left = false; }
                    Button::Keyboard(Key::Right) => { self.right = false; }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}
<|endoftext|>


<commit_before>
use std::collections::VecMap;
use std::collections::vec_map::Iter;
use std::sync::Arc;

use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};

use collect::{cow_trie_map, cow_trie_set};
use collect::{CowTrieMap, CowTrieSet};
use collect::iter::{OrderedMapIterator, OrderedSetIterator};

use Entity;

/// a Static table should be used for infrequently updated data
pub struct Static<T: Send+Sync+Clone>(CowTrieMap<T>);

impl<T: Send+Clone+Sync> Clone for Static<T> {
    fn clone(&self) -> Static<T> {
        Static(match self { &Static(ref t) => t.clone() })
    }
}

impl<T: Send+Clone+Sync> Static<T> {
    pub fn new() -> Static<T> {
        Static(CowTrieMap::new())
    }

    pub fn insert(&mut self, key: Entity, value: T) -> bool {
        match self { &mut Static(ref mut t) => t.insert(key as usize, value).is_some() }
    }

    pub fn get(&self, key: Entity) -> Option<&T> {
        let key = key as usize;
        match self { &Static(ref t) => t.get(&key) }
    }

    pub fn get_mut(&mut self, key: Entity) -> Option<&mut T> {
        let key = key as usize;
        match self { &mut Static(ref mut t) => t.get_mut(&key) }
    }

    pub fn remove(&mut self, key: Entity) -> bool {
        let key = key as usize;
        match self { &mut Static(ref mut t) => t.remove(&key).is_some() }
    }

    pub fn iter(&self) -> StaticIterator<T> {
        StaticIterator {
            iter: match self { &Static(ref t) => t.iter() }
        }
    }

    pub fn len(&self) -> uint {
        match self { &Static(ref t) => t.len() }
    }
}

pub struct StaticIterator<'a, T:'a> {
    iter: cow_trie_map::Iter<'a, T>
}

impl<'a, T: Send+Sync> Iterator for StaticIterator<'a, T> {
    type Item = (Entity, &'a T);

    fn next(&mut self) -> Option<(Entity, &'a T)> {
        match self.iter.next() {
            None => None,
            Some((key, value)) => Some((key as Entity, value))
        }
    }
}

impl<T:Send+Sync+Clone+Encodable> Encodable for Static<T> {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<T:Send+Sync+Clone+Decodable> Decodable for Static<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<Static<T>, D::Error> {
        d.read_map(|d, len| {
            let mut map = Static::new();
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

#[derive(Clone, Default)]
pub struct StaticSet(CowTrieSet);

impl StaticSet {
    pub fn new() -> StaticSet {
        StaticSet(CowTrieSet::new())
    }

    pub fn insert(&mut self, key: Entity) -> bool {
        match self { &mut StaticSet(ref mut t) => t.insert(key as usize) }
    }

    pub fn remove(&mut self, key: Entity) -> bool {
        let key = key as usize;
        match self { &mut StaticSet(ref mut t) => t.remove(&key) }
    }

    pub fn iter(&self) -> StaticSetIterator {
        StaticSetIterator {
            iter: match self { &StaticSet(ref t) => t.iter() }
        }
    }

    pub fn len(&self) -> uint {
        match self { &StaticSet(ref t) => t.len() }
    }
}

pub struct StaticSetIterator<'a> {
    iter: cow_trie_set::Iter<'a>
}

impl<'a> Iterator for StaticSetIterator<'a> {
    type Item = Entity;

    fn next(&mut self) -> Option<Entity> {
        match self.iter.next() {
            None => None,
            Some(key) => Some(key as Entity)
        }
    }
}

impl Encodable for StaticSet {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl Decodable for StaticSet {
    fn decode<D: Decoder>(d: &mut D) -> Result<StaticSet, D::Error> {
        d.read_seq(|d, len| {
            let mut set = StaticSet::new();
            for i in range(0u, len) {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

#[derive(Default, RustcEncodable, RustcDecodable)]
pub struct Dynamic<T: Send+Sync+Clone>(Arc<VecMap<T>>);

impl<T: Send+Clone+Sync> Clone for Dynamic<T> {
    fn clone(&self) -> Dynamic<T> {
        Dynamic(match self { &Dynamic(ref t) => t.clone() })
    }
}

impl<T: Send+Sync+Clone> Dynamic<T> {
    pub fn new() -> Dynamic<T> {
        Dynamic(Arc::new(VecMap::new()))
    }

    pub fn get(&self, key: Entity) -> Option<&T> {
        match self { &Dynamic(ref t) => t.get(&(key as uint)) }
    }

    pub fn get_mut(&mut self, key: Entity) -> Option<&mut T> {
        match self { &mut Dynamic(ref mut t) => t.make_unique().get_mut(&(key as uint)) }
    }

    pub fn insert(&mut self, key: Entity, value: T) -> bool {
        match self { &mut Dynamic(ref mut t) => t.make_unique().insert(key as uint, value) }.is_some()
    }

    pub fn remove(&mut self, key: Entity) -> bool {
        match self { &mut Dynamic(ref mut t) => t.make_unique().remove(&(key as uint)) }.is_some()
    }

    pub fn iter(&self) -> DynamicIterator<T> {
        DynamicIterator {
            iter: match self { &Dynamic(ref t) => t.iter() }
        }
    }

    pub fn len(&self) -> uint {
        match self { &Dynamic(ref t) => t.len() }
    }
}

pub struct DynamicIterator<'a, T:'a> {
    iter: Iter<'a, T>
}

impl<'a, T: Send+Sync> Iterator for DynamicIterator<'a, T> {
    type Item = (Entity, &'a T);

    fn next(&mut self) -> Option<(Entity, &'a T)> {
        match self.iter.next() {
            None => None,
            Some((key, value)) => Some((key as Entity, value))
        }
    }
}

impl<'a, T: Send+Sync> OrderedMapIterator<Entity, &'a T> for StaticIterator<'a, T> {}
impl<'a> OrderedSetIterator<Entity> for StaticSetIterator<'a> {}
impl<'a, T: Send+Sync> OrderedMapIterator<Entity, &'a T> for DynamicIterator<'a, T> {}

<commit_msg>wrap the statictable with an arc pointer<commit_after>
use std::collections::VecMap;
use std::collections::vec_map::Iter;
use std::sync::Arc;

use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};

use collect::{cow_trie_map, cow_trie_set};
use collect::{CowTrieMap, CowTrieSet};
use collect::iter::{OrderedMapIterator, OrderedSetIterator};

use Entity;

/// a Static table should be used for infrequently updated data
pub struct Static<T: Send+Sync+Clone>(Arc<CowTrieMap<T>>);

impl<T: Send+Clone+Sync> Clone for Static<T> {
    fn clone(&self) -> Static<T> {
        Static(match self { &Static(ref t) => t.clone() })
    }
}

impl<T: Send+Clone+Sync> Static<T> {
    pub fn new() -> Static<T> {
        Static(Arc::new(CowTrieMap::new()))
    }

    pub fn insert(&mut self, key: Entity, value: T) -> bool {
        match self { &mut Static(ref mut t) => t.make_unique().insert(key as usize, value).is_some() }
    }

    pub fn get(&self, key: Entity) -> Option<&T> {
        let key = key as usize;
        match self { &Static(ref t) => t.get(&key) }
    }

    pub fn get_mut(&mut self, key: Entity) -> Option<&mut T> {
        let key = key as usize;
        match self { &mut Static(ref mut t) => t.make_unique().get_mut(&key) }
    }

    pub fn remove(&mut self, key: Entity) -> bool {
        let key = key as usize;
        match self { &mut Static(ref mut t) => t.make_unique().remove(&key).is_some() }
    }

    pub fn iter(&self) -> StaticIterator<T> {
        StaticIterator {
            iter: match self { &Static(ref t) => t.iter() }
        }
    }

    pub fn len(&self) -> uint {
        match self { &Static(ref t) => t.len() }
    }
}

pub struct StaticIterator<'a, T:'a> {
    iter: cow_trie_map::Iter<'a, T>
}

impl<'a, T: Send+Sync> Iterator for StaticIterator<'a, T> {
    type Item = (Entity, &'a T);

    fn next(&mut self) -> Option<(Entity, &'a T)> {
        match self.iter.next() {
            None => None,
            Some((key, value)) => Some((key as Entity, value))
        }
    }
}

impl<T:Send+Sync+Clone+Encodable> Encodable for Static<T> {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<T:Send+Sync+Clone+Decodable> Decodable for Static<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<Static<T>, D::Error> {
        d.read_map(|d, len| {
            let mut map = Static::new();
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

#[derive(Clone, Default)]
pub struct StaticSet(CowTrieSet);

impl StaticSet {
    pub fn new() -> StaticSet {
        StaticSet(CowTrieSet::new())
    }

    pub fn insert(&mut self, key: Entity) -> bool {
        match self { &mut StaticSet(ref mut t) => t.insert(key as usize) }
    }

    pub fn remove(&mut self, key: Entity) -> bool {
        let key = key as usize;
        match self { &mut StaticSet(ref mut t) => t.remove(&key) }
    }

    pub fn iter(&self) -> StaticSetIterator {
        StaticSetIterator {
            iter: match self { &StaticSet(ref t) => t.iter() }
        }
    }

    pub fn len(&self) -> uint {
        match self { &StaticSet(ref t) => t.len() }
    }
}

pub struct StaticSetIterator<'a> {
    iter: cow_trie_set::Iter<'a>
}

impl<'a> Iterator for StaticSetIterator<'a> {
    type Item = Entity;

    fn next(&mut self) -> Option<Entity> {
        match self.iter.next() {
            None => None,
            Some(key) => Some(key as Entity)
        }
    }
}

impl Encodable for StaticSet {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl Decodable for StaticSet {
    fn decode<D: Decoder>(d: &mut D) -> Result<StaticSet, D::Error> {
        d.read_seq(|d, len| {
            let mut set = StaticSet::new();
            for i in range(0u, len) {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

#[derive(Default, RustcEncodable, RustcDecodable)]
pub struct Dynamic<T: Send+Sync+Clone>(Arc<VecMap<T>>);

impl<T: Send+Clone+Sync> Clone for Dynamic<T> {
    fn clone(&self) -> Dynamic<T> {
        Dynamic(match self { &Dynamic(ref t) => t.clone() })
    }
}

impl<T: Send+Sync+Clone> Dynamic<T> {
    pub fn new() -> Dynamic<T> {
        Dynamic(Arc::new(VecMap::new()))
    }

    pub fn get(&self, key: Entity) -> Option<&T> {
        match self { &Dynamic(ref t) => t.get(&(key as uint)) }
    }

    pub fn get_mut(&mut self, key: Entity) -> Option<&mut T> {
        match self { &mut Dynamic(ref mut t) => t.make_unique().get_mut(&(key as uint)) }
    }

    pub fn insert(&mut self, key: Entity, value: T) -> bool {
        match self { &mut Dynamic(ref mut t) => t.make_unique().insert(key as uint, value) }.is_some()
    }

    pub fn remove(&mut self, key: Entity) -> bool {
        match self { &mut Dynamic(ref mut t) => t.make_unique().remove(&(key as uint)) }.is_some()
    }

    pub fn iter(&self) -> DynamicIterator<T> {
        DynamicIterator {
            iter: match self { &Dynamic(ref t) => t.iter() }
        }
    }

    pub fn len(&self) -> uint {
        match self { &Dynamic(ref t) => t.len() }
    }
}

pub struct DynamicIterator<'a, T:'a> {
    iter: Iter<'a, T>
}

impl<'a, T: Send+Sync> Iterator for DynamicIterator<'a, T> {
    type Item = (Entity, &'a T);

    fn next(&mut self) -> Option<(Entity, &'a T)> {
        match self.iter.next() {
            None => None,
            Some((key, value)) => Some((key as Entity, value))
        }
    }
}

impl<'a, T: Send+Sync> OrderedMapIterator<Entity, &'a T> for StaticIterator<'a, T> {}
impl<'a> OrderedSetIterator<Entity> for StaticSetIterator<'a> {}
impl<'a, T: Send+Sync> OrderedMapIterator<Entity, &'a T> for DynamicIterator<'a, T> {}

<|endoftext|>


<commit_before>//! A set of constants used by the library.

/// The maximum length of the textual size of an embed.
pub const EMBED_MAX_LENGTH: u16 = 6000;
/// The gateway version used by the library. The gateway URI is retrieved via
/// the REST API.
pub const GATEWAY_VERSION: u8 = 6;
/// The voice gateway version used by the library.
pub const VOICE_GATEWAY_VERSION: u8 = 3;
/// The large threshold to send on identify.
pub const LARGE_THRESHOLD: u8 = 250;
/// The maximum unicode code points allowed within a message by Discord.
pub const MESSAGE_CODE_LIMIT: u16 = 2000;
/// The [UserAgent] sent along with every request.
///
/// [UserAgent]: ../../hyper/header/struct.UserAgent.html
pub const USER_AGENT: &str = concat!(
    "DiscordBot (https://github.com/serenity-rs/serenity, ",
    env!("CARGO_PKG_VERSION"),
    ")"
);

/// List of messages Discord shows on member join.
pub static JOIN_MESSAGES: &'static [&'static str] = &[
    "$user just joined the server - glhf!",
    "$user just joined. Everyone, look busy!",
    "$user just joined. Can I get a heal?",
    "$user joined your party.",
    "$user joined. You must construct additional pylons.",
    "Ermagherd. $user is here.",
    "Welcome, $user. Stay awhile and listen.",
    "Welcome, $user. We were expecting you ( ͡° ͜ʖ ͡°)",
    "Welcome, $user. We hope you brought pizza.",
    "Welcome $user. Leave your weapons by the door.",
    "A wild $user appeared.",
    "Swoooosh. $user just landed.",
    "Brace yourselves. $user just joined the server.",
    "$user just joined. Hide your bananas.",
    "$user just arrived. Seems OP - please nerf.",
    "$user just slid into the server.",
    "A $user has spawned in the server.",
    "Big $user showed up!",
    "Where’s $user? In the server!",
    "$user hopped into the server. Kangaroo!!",
    "$user just showed up. Hold my beer.",
    "Challenger approaching - $user has appeared!",
    "It's a bird! It's a plane! Nevermind, it's just $user.",
    r"It's $user! Praise the sun! \[T]/",
    "Never gonna give $user up. Never gonna let $user down.",
    "Ha! $user has joined! You activated my trap card!",
    "Cheers, love! $user's here!",
    "Hey! Listen! $user has joined!",
    "We've been expecting you $user",
    "It's dangerous to go alone, take $user!",
    "$user has joined the server! It's super effective!",
    "Cheers, love! $user is here!",
    "$user is here, as the prophecy foretold.",
    "$user has arrived. Party's over.",
    "Ready player $user",
    "$user is here to kick butt and chew bubblegum. And $user is all out of gum.",
    "Hello. Is it $user you're looking for?",
    "$user has joined. Stay a while and listen!",
    "Roses are red, violets are blue, $user joined this server with you",
];

/// Enum to map gateway opcodes.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum OpCode {
    /// Dispatches an event.
    Event = 0,
    /// Used for ping checking.
    Heartbeat = 1,
    /// Used for client handshake.
    Identify = 2,
    /// Used to update the client status.
    StatusUpdate = 3,
    /// Used to join/move/leave voice channels.
    VoiceStateUpdate = 4,
    /// Used for voice ping checking.
    VoiceServerPing = 5,
    /// Used to resume a closed connection.
    Resume = 6,
    /// Used to tell clients to reconnect to the gateway.
    Reconnect = 7,
    /// Used to request guild members.
    GetGuildMembers = 8,
    /// Used to notify clients that they have an invalid session Id.
    InvalidSession = 9,
    /// Sent immediately after connection, contains heartbeat + server info.
    Hello = 10,
    /// Sent immediately following a client heartbeat that was received.
    HeartbeatAck = 11,
}

enum_number!(
    OpCode {
        Event,
        Heartbeat,
        Identify,
        StatusUpdate,
        VoiceStateUpdate,
        VoiceServerPing,
        Resume,
        Reconnect,
        GetGuildMembers,
        InvalidSession,
        Hello,
        HeartbeatAck,
    }
);

impl OpCode {
    pub fn num(&self) -> u64 {
        match *self {
            OpCode::Event => 0,
            OpCode::Heartbeat => 1,
            OpCode::Identify => 2,
            OpCode::StatusUpdate => 3,
            OpCode::VoiceStateUpdate => 4,
            OpCode::VoiceServerPing => 5,
            OpCode::Resume => 6,
            OpCode::Reconnect => 7,
            OpCode::GetGuildMembers => 8,
            OpCode::InvalidSession => 9,
            OpCode::Hello => 10,
            OpCode::HeartbeatAck => 11,
        }
    }
}

/// Enum to map voice opcodes.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum VoiceOpCode {
    /// Used to begin a voice websocket connection.
    Identify = 0,
    /// Used to select the voice protocol.
    SelectProtocol = 1,
    /// Used to complete the websocket handshake.
    Hello = 2,
    /// Used to keep the websocket connection alive.
    KeepAlive = 3,
    /// Used to describe the session.
    SessionDescription = 4,
    /// Used to indicate which users are speaking.
    Speaking = 5,
    /// Used to heartbeat.
    Heartbeat = 8,
}

enum_number!(
    VoiceOpCode {
        Identify,
        SelectProtocol,
        Hello,
        KeepAlive,
        SessionDescription,
        Speaking,
        Heartbeat,
    }
);

impl VoiceOpCode {
    pub fn num(&self) -> u64 {
        match *self {
            VoiceOpCode::Identify => 0,
            VoiceOpCode::SelectProtocol => 1,
            VoiceOpCode::Hello => 2,
            VoiceOpCode::KeepAlive => 3,
            VoiceOpCode::SessionDescription => 4,
            VoiceOpCode::Speaking => 5,
            VoiceOpCode::Heartbeat => 8,
        }
    }
}

pub mod close_codes {
    /// Unknown error; try reconnecting?
    ///
    /// Can reconnect.
    pub const UNKNOWN_ERROR: u16 = 4000;
    /// Invalid Gateway OP Code.
    ///
    /// Can resume.
    pub const UNKNOWN_OPCODE: u16 = 4001;
    /// An invalid payload was sent.
    ///
    /// Can resume.
    pub const DECODE_ERROR: u16 = 4002;
    /// A payload was sent prior to identifying.
    ///
    /// Cannot reconnect.
    pub const NOT_AUTHENTICATED: u16 = 4003;
    /// The account token sent with the identify payload was incorrect.
    ///
    /// Cannot reconnect.
    pub const AUTHENTICATION_FAILED: u16 = 4004;
    /// More than one identify payload was sent.
    ///
    /// Can reconnect.
    pub const ALREADY_AUTHENTICATED: u16 = 4005;
    /// The sequence sent when resuming the session was invalid.
    ///
    /// Can reconnect.
    pub const INVALID_SEQUENCE: u16 = 4007;
    /// Payloads were being sent too quickly.
    ///
    /// Can resume.
    pub const RATE_LIMITED: u16 = 4008;
    /// A session timed out.
    ///
    /// Can reconnect.
    pub const SESSION_TIMEOUT: u16 = 4009;
    /// An invalid shard when identifying was sent.
    ///
    /// Cannot reconnect.
    pub const INVALID_SHARD: u16 = 4010;
    /// The session would have handled too many guilds.
    ///
    /// Cannot reconnect.
    pub const SHARDING_REQUIRED: u16 = 4011;
}
<commit_msg>Updated the Discord's welcome messages as of 2018-12-19 (#452)<commit_after>//! A set of constants used by the library.

/// The maximum length of the textual size of an embed.
pub const EMBED_MAX_LENGTH: u16 = 6000;
/// The gateway version used by the library. The gateway URI is retrieved via
/// the REST API.
pub const GATEWAY_VERSION: u8 = 6;
/// The voice gateway version used by the library.
pub const VOICE_GATEWAY_VERSION: u8 = 3;
/// The large threshold to send on identify.
pub const LARGE_THRESHOLD: u8 = 250;
/// The maximum unicode code points allowed within a message by Discord.
pub const MESSAGE_CODE_LIMIT: u16 = 2000;
/// The [UserAgent] sent along with every request.
///
/// [UserAgent]: ../../hyper/header/struct.UserAgent.html
pub const USER_AGENT: &str = concat!(
    "DiscordBot (https://github.com/serenity-rs/serenity, ",
    env!("CARGO_PKG_VERSION"),
    ")"
);

/// List of messages Discord shows on member join.
pub static JOIN_MESSAGES: &'static [&'static str] = &[
    "$user just joined the server - glhf!",
    "$user just joined. Everyone, look busy!",
    "$user just joined. Can I get a heal?",
    "$user joined your party.",
    "$user joined. You must construct additional pylons.",
    "Ermagherd. $user is here.",
    "Welcome, $user. Stay awhile and listen.",
    "Welcome, $user. We were expecting you ( ͡° ͜ʖ ͡°)",
    "Welcome, $user. We hope you brought pizza.",
    "Welcome $user. Leave your weapons by the door.",
    "A wild $user appeared.",
    "Swoooosh. $user just landed.",
    "Brace yourselves. $user just joined the server.",
    "$user just joined... or did they?",
    "$user just arrived. Seems OP - please nerf.",
    "$user just slid into the server.",
    "A $user has spawned in the server.",
    "Big $user showed up!",
    "Where’s $user? In the server!",
    "$user hopped into the server. Kangaroo!!",
    "$user just showed up. Hold my beer.",
    "Challenger approaching - $user has appeared!",
    "It's a bird! It's a plane! Nevermind, it's just $user.",
    r"It's $user! Praise the sun! \[T]/",
    "Never gonna give $user up. Never gonna let $user down.",
    "$user has joined the battle bus.",
    "Cheers, love! $user's here!",
    "Hey! Listen! $user has joined!",
    "We've been expecting you $user",
    "It's dangerous to go alone, take $user!",
    "$user has joined the server! It's super effective!",
    "Cheers, love! $user is here!",
    "$user is here, as the prophecy foretold.",
    "$user has arrived. Party's over.",
    "Ready player $user",
    "$user is here to kick butt and chew bubblegum. And $user is all out of gum.",
    "Hello. Is it $user you're looking for?",
    "$user has joined. Stay a while and listen!",
    "Roses are red, violets are blue, $user joined this server with you",
];

/// Enum to map gateway opcodes.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum OpCode {
    /// Dispatches an event.
    Event = 0,
    /// Used for ping checking.
    Heartbeat = 1,
    /// Used for client handshake.
    Identify = 2,
    /// Used to update the client status.
    StatusUpdate = 3,
    /// Used to join/move/leave voice channels.
    VoiceStateUpdate = 4,
    /// Used for voice ping checking.
    VoiceServerPing = 5,
    /// Used to resume a closed connection.
    Resume = 6,
    /// Used to tell clients to reconnect to the gateway.
    Reconnect = 7,
    /// Used to request guild members.
    GetGuildMembers = 8,
    /// Used to notify clients that they have an invalid session Id.
    InvalidSession = 9,
    /// Sent immediately after connection, contains heartbeat + server info.
    Hello = 10,
    /// Sent immediately following a client heartbeat that was received.
    HeartbeatAck = 11,
}

enum_number!(
    OpCode {
        Event,
        Heartbeat,
        Identify,
        StatusUpdate,
        VoiceStateUpdate,
        VoiceServerPing,
        Resume,
        Reconnect,
        GetGuildMembers,
        InvalidSession,
        Hello,
        HeartbeatAck,
    }
);

impl OpCode {
    pub fn num(&self) -> u64 {
        match *self {
            OpCode::Event => 0,
            OpCode::Heartbeat => 1,
            OpCode::Identify => 2,
            OpCode::StatusUpdate => 3,
            OpCode::VoiceStateUpdate => 4,
            OpCode::VoiceServerPing => 5,
            OpCode::Resume => 6,
            OpCode::Reconnect => 7,
            OpCode::GetGuildMembers => 8,
            OpCode::InvalidSession => 9,
            OpCode::Hello => 10,
            OpCode::HeartbeatAck => 11,
        }
    }
}

/// Enum to map voice opcodes.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum VoiceOpCode {
    /// Used to begin a voice websocket connection.
    Identify = 0,
    /// Used to select the voice protocol.
    SelectProtocol = 1,
    /// Used to complete the websocket handshake.
    Hello = 2,
    /// Used to keep the websocket connection alive.
    KeepAlive = 3,
    /// Used to describe the session.
    SessionDescription = 4,
    /// Used to indicate which users are speaking.
    Speaking = 5,
    /// Used to heartbeat.
    Heartbeat = 8,
}

enum_number!(
    VoiceOpCode {
        Identify,
        SelectProtocol,
        Hello,
        KeepAlive,
        SessionDescription,
        Speaking,
        Heartbeat,
    }
);

impl VoiceOpCode {
    pub fn num(&self) -> u64 {
        match *self {
            VoiceOpCode::Identify => 0,
            VoiceOpCode::SelectProtocol => 1,
            VoiceOpCode::Hello => 2,
            VoiceOpCode::KeepAlive => 3,
            VoiceOpCode::SessionDescription => 4,
            VoiceOpCode::Speaking => 5,
            VoiceOpCode::Heartbeat => 8,
        }
    }
}

pub mod close_codes {
    /// Unknown error; try reconnecting?
    ///
    /// Can reconnect.
    pub const UNKNOWN_ERROR: u16 = 4000;
    /// Invalid Gateway OP Code.
    ///
    /// Can resume.
    pub const UNKNOWN_OPCODE: u16 = 4001;
    /// An invalid payload was sent.
    ///
    /// Can resume.
    pub const DECODE_ERROR: u16 = 4002;
    /// A payload was sent prior to identifying.
    ///
    /// Cannot reconnect.
    pub const NOT_AUTHENTICATED: u16 = 4003;
    /// The account token sent with the identify payload was incorrect.
    ///
    /// Cannot reconnect.
    pub const AUTHENTICATION_FAILED: u16 = 4004;
    /// More than one identify payload was sent.
    ///
    /// Can reconnect.
    pub const ALREADY_AUTHENTICATED: u16 = 4005;
    /// The sequence sent when resuming the session was invalid.
    ///
    /// Can reconnect.
    pub const INVALID_SEQUENCE: u16 = 4007;
    /// Payloads were being sent too quickly.
    ///
    /// Can resume.
    pub const RATE_LIMITED: u16 = 4008;
    /// A session timed out.
    ///
    /// Can reconnect.
    pub const SESSION_TIMEOUT: u16 = 4009;
    /// An invalid shard when identifying was sent.
    ///
    /// Cannot reconnect.
    pub const INVALID_SHARD: u16 = 4010;
    /// The session would have handled too many guilds.
    ///
    /// Cannot reconnect.
    pub const SHARDING_REQUIRED: u16 = 4011;
}
<|endoftext|>