<commit_before>use futures::{Async, Future, Poll, Stream};
use h2::Reason;
use h2::server::{Builder, Connection, Handshake, SendResponse};
use tokio_io::{AsyncRead, AsyncWrite};

use ::headers::content_length_parse_all;
use ::body::Payload;
use body::internal::FullDataArg;
use ::common::exec::H2Exec;
use ::headers;
use ::service::Service;
use ::proto::Dispatched;
use super::{PipeToSendStream, SendBuf};

use ::{Body, Response};

pub(crate) struct Server<T, S, B, E>
where
    S: Service,
    B: Payload,
{
    exec: E,
    service: S,
    state: State<T, B>,
}

enum State<T, B>
where
    B: Payload,
{
    Handshaking(Handshake<T, SendBuf<B::Data>>),
    Serving(Serving<T, B>),
    Closed,
}

struct Serving<T, B>
where
    B: Payload,
{
    conn: Connection<T, SendBuf<B::Data>>,
}

impl<T, S, B, E> Server<T, S, B, E>
where
    T: AsyncRead + AsyncWrite,
    S: Service<ReqBody=Body, ResBody=B>,
    S::Error: Into<Box<::std::error::Error + Send + Sync>>,
    //S::Future: Send + 'static,
    B: Payload,
    E: H2Exec<S::Future, B>,
{
    pub(crate) fn new(io: T, service: S, exec: E) -> Server<T, S, B, E> {
        let handshake = Builder::new()
            .handshake(io);
        Server {
            exec,
            state: State::Handshaking(handshake),
            service,
        }
    }

    pub fn graceful_shutdown(&mut self) {
        trace!("graceful_shutdown");
        match self.state {
            State::Handshaking(..) => {
                // fall-through, to replace state with Closed
            },
            State::Serving(ref mut srv) => {
                srv.conn.graceful_shutdown();
                return;
            },
            State::Closed => {
                return;
            }
        }
        self.state = State::Closed;
    }
}

impl<T, S, B, E> Future for Server<T, S, B, E>
where
    T: AsyncRead + AsyncWrite,
    S: Service<ReqBody=Body, ResBody=B>,
    S::Error: Into<Box<::std::error::Error + Send + Sync>>,
    //S::Future: Send + 'static,
    B: Payload,
    E: H2Exec<S::Future, B>,
{
    type Item = Dispatched;
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let next = match self.state {
                State::Handshaking(ref mut h) => {
                    let conn = try_ready!(h.poll().map_err(::Error::new_h2));
                    State::Serving(Serving {
                        conn: conn,
                    })
                },
                State::Serving(ref mut srv) => {
                    try_ready!(srv.poll_server(&mut self.service, &self.exec));
                    return Ok(Async::Ready(Dispatched::Shutdown));
                }
                State::Closed => {
                    // graceful_shutdown was called before handshaking finished,
                    // nothing to do here...
                    return Ok(Async::Ready(Dispatched::Shutdown));
                }
            };
            self.state = next;
        }
    }
}

impl<T, B> Serving<T, B>
where
    T: AsyncRead + AsyncWrite,
    B: Payload,
{
    fn poll_server<S, E>(&mut self, service: &mut S, exec: &E) -> Poll<(), ::Error>
    where
        S: Service<
            ReqBody=Body,
            ResBody=B,
        >,
        S::Error: Into<Box<::std::error::Error + Send + Sync>>,
        E: H2Exec<S::Future, B>,
    {
        while let Some((req, respond)) = try_ready!(self.conn.poll().map_err(::Error::new_h2)) {
            trace!("incoming request");
            let content_length = content_length_parse_all(req.headers());
            let req = req.map(|stream| {
                ::Body::h2(stream, content_length)
            });
            let mut fut = H2Stream::new(service.call(req), respond);

            // try to eagerly poll the future, so that we might
            // not need to allocate a new task...
            match fut.poll() {
                Ok(Async::Ready(())) | Err(()) => (),
                Ok(Async::NotReady) => {
                    exec.execute_h2stream(fut)?;
                }
            }
        }

        // no more incoming streams...
        trace!("incoming connection complete");
        Ok(Async::Ready(()))
    }
}

#[allow(missing_debug_implementations)]
pub struct H2Stream<F, B>
where
    B: Payload,
{
    reply: SendResponse<SendBuf<B::Data>>,
    state: H2StreamState<F, B>,
}

enum H2StreamState<F, B>
where
    B: Payload,
{
    Service(F),
    Body(PipeToSendStream<B>),
}

impl<F, B> H2Stream<F, B>
where
    F: Future<Item=Response<B>>,
    F::Error: Into<Box<::std::error::Error + Send + Sync>>,
    B: Payload,
{
    fn new(fut: F, respond: SendResponse<SendBuf<B::Data>>) -> H2Stream<F, B> {
        H2Stream {
            reply: respond,
            state: H2StreamState::Service(fut),
        }
    }

    fn poll2(&mut self) -> Poll<(), ::Error> {
        loop {
            let next = match self.state {
                H2StreamState::Service(ref mut h) => {
                    let res = match h.poll() {
                        Ok(Async::Ready(r)) => r,
                        Ok(Async::NotReady) => {
                            // Body is not yet ready, so we want to check if the client has sent a
                            // RST_STREAM frame which would cancel the current request.
                            if let Async::Ready(reason) =
                                self.reply.poll_reset().map_err(|e| ::Error::new_h2(e))?
                            {
                                debug!("stream received RST_STREAM: {:?}", reason);
                                return Err(::Error::new_h2(reason.into()));
                            }
                            return Ok(Async::NotReady);
                        }
                        Err(e) => return Err(::Error::new_user_service(e)),
                    };

                    let (head, mut body) = res.into_parts();
                    let mut res = ::http::Response::from_parts(head, ());
                    super::strip_connection_headers(res.headers_mut(), false);

                    // set Date header if it isn't already set...
                    res
                        .headers_mut()
                        .entry(::http::header::DATE)
                        .expect("DATE is a valid HeaderName")
                        .or_insert_with(::proto::h1::date::update_and_header_value);

                    macro_rules! reply {
                        ($eos:expr) => ({
                            match self.reply.send_response(res, $eos) {
                                Ok(tx) => tx,
                                Err(e) => {
                                    trace!("send response error: {}", e);
                                    self.reply.send_reset(Reason::INTERNAL_ERROR);
                                    return Err(::Error::new_h2(e));
                                }
                            }
                        })
                    }

                    if let Some(full) = body.__hyper_full_data(FullDataArg(())).0 {
                        let mut body_tx = reply!(false);
                        let buf = SendBuf(Some(full));
                        body_tx
                            .send_data(buf, true)
                            .map_err(::Error::new_body_write)?;
                        return Ok(Async::Ready(()));
                    }

                    // automatically set Content-Length from body...
                    if let Some(len) = body.content_length() {
                        headers::set_content_length_if_missing(res.headers_mut(), len);
                    }
                    if !body.is_end_stream() {
                        let body_tx = reply!(false);
                        H2StreamState::Body(PipeToSendStream::new(body, body_tx))
                    } else {
                        reply!(true);
                        return Ok(Async::Ready(()));
                    }
                },
                H2StreamState::Body(ref mut pipe) => {
                    return pipe.poll();
                }
            };
            self.state = next;
        }
    }
}

impl<F, B> Future for H2Stream<F, B>
where
    F: Future<Item=Response<B>>,
    F::Error: Into<Box<::std::error::Error + Send + Sync>>,
    B: Payload,
{
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.poll2()
            .map_err(|e| debug!("stream error: {}", e))
    }
}

<commit_msg>refactor(http2): set content-length even when full_data is available<commit_after>use futures::{Async, Future, Poll, Stream};
use h2::Reason;
use h2::server::{Builder, Connection, Handshake, SendResponse};
use tokio_io::{AsyncRead, AsyncWrite};

use ::headers::content_length_parse_all;
use ::body::Payload;
use body::internal::FullDataArg;
use ::common::exec::H2Exec;
use ::headers;
use ::service::Service;
use ::proto::Dispatched;
use super::{PipeToSendStream, SendBuf};

use ::{Body, Response};

pub(crate) struct Server<T, S, B, E>
where
    S: Service,
    B: Payload,
{
    exec: E,
    service: S,
    state: State<T, B>,
}

enum State<T, B>
where
    B: Payload,
{
    Handshaking(Handshake<T, SendBuf<B::Data>>),
    Serving(Serving<T, B>),
    Closed,
}

struct Serving<T, B>
where
    B: Payload,
{
    conn: Connection<T, SendBuf<B::Data>>,
}

impl<T, S, B, E> Server<T, S, B, E>
where
    T: AsyncRead + AsyncWrite,
    S: Service<ReqBody=Body, ResBody=B>,
    S::Error: Into<Box<::std::error::Error + Send + Sync>>,
    //S::Future: Send + 'static,
    B: Payload,
    E: H2Exec<S::Future, B>,
{
    pub(crate) fn new(io: T, service: S, exec: E) -> Server<T, S, B, E> {
        let handshake = Builder::new()
            .handshake(io);
        Server {
            exec,
            state: State::Handshaking(handshake),
            service,
        }
    }

    pub fn graceful_shutdown(&mut self) {
        trace!("graceful_shutdown");
        match self.state {
            State::Handshaking(..) => {
                // fall-through, to replace state with Closed
            },
            State::Serving(ref mut srv) => {
                srv.conn.graceful_shutdown();
                return;
            },
            State::Closed => {
                return;
            }
        }
        self.state = State::Closed;
    }
}

impl<T, S, B, E> Future for Server<T, S, B, E>
where
    T: AsyncRead + AsyncWrite,
    S: Service<ReqBody=Body, ResBody=B>,
    S::Error: Into<Box<::std::error::Error + Send + Sync>>,
    //S::Future: Send + 'static,
    B: Payload,
    E: H2Exec<S::Future, B>,
{
    type Item = Dispatched;
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let next = match self.state {
                State::Handshaking(ref mut h) => {
                    let conn = try_ready!(h.poll().map_err(::Error::new_h2));
                    State::Serving(Serving {
                        conn: conn,
                    })
                },
                State::Serving(ref mut srv) => {
                    try_ready!(srv.poll_server(&mut self.service, &self.exec));
                    return Ok(Async::Ready(Dispatched::Shutdown));
                }
                State::Closed => {
                    // graceful_shutdown was called before handshaking finished,
                    // nothing to do here...
                    return Ok(Async::Ready(Dispatched::Shutdown));
                }
            };
            self.state = next;
        }
    }
}

impl<T, B> Serving<T, B>
where
    T: AsyncRead + AsyncWrite,
    B: Payload,
{
    fn poll_server<S, E>(&mut self, service: &mut S, exec: &E) -> Poll<(), ::Error>
    where
        S: Service<
            ReqBody=Body,
            ResBody=B,
        >,
        S::Error: Into<Box<::std::error::Error + Send + Sync>>,
        E: H2Exec<S::Future, B>,
    {
        while let Some((req, respond)) = try_ready!(self.conn.poll().map_err(::Error::new_h2)) {
            trace!("incoming request");
            let content_length = content_length_parse_all(req.headers());
            let req = req.map(|stream| {
                ::Body::h2(stream, content_length)
            });
            let mut fut = H2Stream::new(service.call(req), respond);

            // try to eagerly poll the future, so that we might
            // not need to allocate a new task...
            match fut.poll() {
                Ok(Async::Ready(())) | Err(()) => (),
                Ok(Async::NotReady) => {
                    exec.execute_h2stream(fut)?;
                }
            }
        }

        // no more incoming streams...
        trace!("incoming connection complete");
        Ok(Async::Ready(()))
    }
}

#[allow(missing_debug_implementations)]
pub struct H2Stream<F, B>
where
    B: Payload,
{
    reply: SendResponse<SendBuf<B::Data>>,
    state: H2StreamState<F, B>,
}

enum H2StreamState<F, B>
where
    B: Payload,
{
    Service(F),
    Body(PipeToSendStream<B>),
}

impl<F, B> H2Stream<F, B>
where
    F: Future<Item=Response<B>>,
    F::Error: Into<Box<::std::error::Error + Send + Sync>>,
    B: Payload,
{
    fn new(fut: F, respond: SendResponse<SendBuf<B::Data>>) -> H2Stream<F, B> {
        H2Stream {
            reply: respond,
            state: H2StreamState::Service(fut),
        }
    }

    fn poll2(&mut self) -> Poll<(), ::Error> {
        loop {
            let next = match self.state {
                H2StreamState::Service(ref mut h) => {
                    let res = match h.poll() {
                        Ok(Async::Ready(r)) => r,
                        Ok(Async::NotReady) => {
                            // Body is not yet ready, so we want to check if the client has sent a
                            // RST_STREAM frame which would cancel the current request.
                            if let Async::Ready(reason) =
                                self.reply.poll_reset().map_err(|e| ::Error::new_h2(e))?
                            {
                                debug!("stream received RST_STREAM: {:?}", reason);
                                return Err(::Error::new_h2(reason.into()));
                            }
                            return Ok(Async::NotReady);
                        }
                        Err(e) => return Err(::Error::new_user_service(e)),
                    };

                    let (head, mut body) = res.into_parts();
                    let mut res = ::http::Response::from_parts(head, ());
                    super::strip_connection_headers(res.headers_mut(), false);

                    // set Date header if it isn't already set...
                    res
                        .headers_mut()
                        .entry(::http::header::DATE)
                        .expect("DATE is a valid HeaderName")
                        .or_insert_with(::proto::h1::date::update_and_header_value);

                    macro_rules! reply {
                        ($eos:expr) => ({
                            match self.reply.send_response(res, $eos) {
                                Ok(tx) => tx,
                                Err(e) => {
                                    trace!("send response error: {}", e);
                                    self.reply.send_reset(Reason::INTERNAL_ERROR);
                                    return Err(::Error::new_h2(e));
                                }
                            }
                        })
                    }

                    // automatically set Content-Length from body...
                    if let Some(len) = body.content_length() {
                        headers::set_content_length_if_missing(res.headers_mut(), len);
                    }

                    if let Some(full) = body.__hyper_full_data(FullDataArg(())).0 {
                        let mut body_tx = reply!(false);
                        let buf = SendBuf(Some(full));
                        body_tx
                            .send_data(buf, true)
                            .map_err(::Error::new_body_write)?;
                        return Ok(Async::Ready(()));
                    }

                    if !body.is_end_stream() {
                        let body_tx = reply!(false);
                        H2StreamState::Body(PipeToSendStream::new(body, body_tx))
                    } else {
                        reply!(true);
                        return Ok(Async::Ready(()));
                    }
                },
                H2StreamState::Body(ref mut pipe) => {
                    return pipe.poll();
                }
            };
            self.state = next;
        }
    }
}

impl<F, B> Future for H2Stream<F, B>
where
    F: Future<Item=Response<B>>,
    F::Error: Into<Box<::std::error::Error + Send + Sync>>,
    B: Payload,
{
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.poll2()
            .map_err(|e| debug!("stream error: {}", e))
    }
}

<|endoftext|>


<commit_before>// Copyright 2014 Rich Lane.

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

#[feature(globs)];
#[feature(macro_rules)];

extern mod native;
extern mod extra;
extern mod glfw;
extern mod gl;
extern mod cgmath;
extern mod noise;

use std::libc;

use gl::types::*;

use cgmath::matrix::Matrix;
use cgmath::matrix::Mat3;
use cgmath::matrix::ToMat4;
use cgmath::vector::Vector;
use cgmath::vector::Vec2;
use cgmath::vector::Vec3;
use cgmath::angle::rad;
use cgmath::ptr::Ptr;

use spiral::Spiral;
use chunk::Chunk;
use chunk::ChunkLoader;

#[cfg(target_os = "linux")]
#[link(name="GLU")]
extern {}

mod offset_of;
mod chunk;
mod ratelimiter;
mod texture;
mod spiral;
mod renderer;

pub static VISIBLE_RADIUS: uint = 8;
pub static CHUNK_SIZE: uint = 32;
pub static WORLD_SEED: u32 = 42;

static CAMERA_SPEED : f32 = 30.0f32;

static DEFAULT_WINDOW_SIZE : Vec2<u32> = Vec2 { x: 800, y: 600 };

#[start]
fn start(argc: int, argv: **u8) -> int {
    do native::start(argc, argv) {
        main();
    }
}

fn main() {
   glfw::set_error_callback(~ErrorContext);

    do glfw::start {
        glfw::window_hint::samples(8);

        let window = glfw::Window::create(
            DEFAULT_WINDOW_SIZE.x, DEFAULT_WINDOW_SIZE.y,
            "Cubeland", glfw::Windowed)
            .expect("Failed to create GLFW window.");

        window.set_cursor_mode(glfw::CursorDisabled);
        window.make_context_current();

        gl::load_with(glfw::get_proc_address);

        glfw::set_swap_interval(1);

        let mut renderer = renderer::Renderer::new(DEFAULT_WINDOW_SIZE);

        let mut chunk_loader = ChunkLoader::new(WORLD_SEED);

        let (key_port, key_chan) = std::comm::Chan::new();
        window.set_key_callback(~KeyContext { chan: key_chan });

        let (fb_size_port, fb_size_chan): (Port<(u32,u32)>, Chan<(u32,u32)>) = std::comm::Chan::new();
        window.set_framebuffer_size_callback(~FramebufferSizeContext { chan: fb_size_chan });

        let mut fps_display_limiter = ratelimiter::RateLimiter::new(1000*1000*1000);
        let mut fps_frame_counter = 0;

        let mut camera_position = Vec3::<f32>::new(0.0f32, 30.0f32, 40.0f32);

        let mut last_tick = extra::time::precise_time_ns();

        let mut grabbed = true;

        let mut camera_angle_x = 0.0;
        let mut camera_angle_y = 0.0;

        while !window.should_close() {
            glfw::poll_events();

            loop {
                match fb_size_port.try_recv() {
                    Some((w,h)) => {
                        renderer.set_window_size(Vec2 { x: w, y: h });
                    }
                    None => break
                }
            }

            loop {
                match key_port.try_recv() {
                    Some((glfw::Press, glfw::KeyR)) => {
                        renderer.reload_resources();
                    },
                    Some((glfw::Press, glfw::KeyEscape)) => {
                        window.set_should_close(true);
                    },
                    Some((glfw::Press, glfw::KeyG)) => {
                        grabbed = !grabbed;
                        if grabbed {
                            window.set_cursor_mode(glfw::CursorDisabled);
                        } else {
                            window.set_cursor_mode(glfw::CursorNormal);
                        }
                    },
                    Some((glfw::Press, glfw::KeyL)) => {
                        renderer.toggle_wireframe_mode();
                    },
                    None => break,
                    _ => {}
                }
            }

            if grabbed {
                let (cursor_x, cursor_y) = window.get_cursor_pos();
                camera_angle_y = ((cursor_x * 0.0005) % 1.0) * std::f64::consts::PI * 2.0;
                camera_angle_x = ((cursor_y * 0.0005) % 1.0) * std::f64::consts::PI * 2.0;
            }

            let mut camera_velocity = Vec3::<f32>::new(0.0f32, 0.0f32, 0.0f32);

            match window.get_key(glfw::KeySpace) {
                glfw::Press => { camera_velocity.y += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyLeftControl) {
                glfw::Press => { camera_velocity.y += -1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyS) {
                glfw::Press => { camera_velocity.z += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyW) {
                glfw::Press => { camera_velocity.z += -1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyD) {
                glfw::Press => { camera_velocity.x += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyA) {
                glfw::Press => { camera_velocity.x += -1.0f32 }
                _ => {}
            }

            let now = extra::time::precise_time_ns();
            let tick_length = (now - last_tick) as f32 / (1000 * 1000 * 1000) as f32;
            last_tick = now;

            let inv_camera_rotation = Mat3::<f32>::from_euler(rad(-camera_angle_x as f32), rad(-camera_angle_y as f32), rad(0.0f32));
            let absolute_camera_velocity = inv_camera_rotation.mul_v(&camera_velocity).mul_s(CAMERA_SPEED).mul_s(tick_length);
            camera_position.add_self_v(&absolute_camera_velocity);

            let camera_position_i64 = Vec3 {
                x: camera_position.x as i64,
                y: 0,
                z: camera_position.z as i64
            };

            {
                let chunks = find_nearby_chunks(&chunk_loader, camera_position_i64);

                renderer.render(
                    chunks,
                    camera_position,
                    Vec2 { x: camera_angle_x, y: camera_angle_y });
            }

            window.swap_buffers();

            request_nearby_chunks(&mut chunk_loader, camera_position_i64);
            chunk_loader.work();

            check_gl("main loop");

            fps_frame_counter += 1;
            if fps_display_limiter.limit() {
                println!("{} frames per second", fps_frame_counter);
                fps_frame_counter = 0;
            }
        }
    }
}

fn nearby_chunk_coords(p: Vec3<i64>) -> ~[(i64, i64)] {
    static num_chunks : uint = (VISIBLE_RADIUS * 2 + 1) * (VISIBLE_RADIUS * 2 + 1);
    static mask : i64 = !(CHUNK_SIZE as i64 - 1);

    let chunk_coord = |v: Vec2<i64>| -> (i64, i64) {
        (
            (p.x & mask) + v.x*CHUNK_SIZE as i64,
            (p.z & mask) + v.y*CHUNK_SIZE as i64
        )
    };

    Spiral::<i64>::new(num_chunks).map(chunk_coord).to_owned_vec()
}

fn find_nearby_chunks<'a>(chunk_loader: &'a ChunkLoader, p: Vec3<i64>) -> ~[&'a ~Chunk] {
    let coords = nearby_chunk_coords(p);
    coords.iter().
        filter_map(|&c| chunk_loader.get(c)).
        to_owned_vec()
}

fn request_nearby_chunks(chunk_loader: &mut ChunkLoader, p: Vec3<i64>) {
    let coords = nearby_chunk_coords(p);
    for &c in coords.iter() {
        chunk_loader.request(c);
    }
}

extern "C" {
    fn gluErrorString(error: GLenum) -> *GLubyte;
}

fn check_gl(message : &str) {
    let err = gl::GetError();
    if (err != gl::NO_ERROR) {
        unsafe {
            let err = std::str::raw::from_c_str(gluErrorString(err) as *i8);
            fail!("GL error {} at {}", err, message);
        }
    }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        fail!("GLFW Error: {:s}", description);
    }
}

struct KeyContext {
    chan : Chan<(glfw::Action, glfw::Key)>,
}
impl glfw::KeyCallback for KeyContext {
    fn call(&self, _: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
        self.chan.send((action, key));
    }
}

struct FramebufferSizeContext {
    chan: Chan<(u32,u32)>
}
impl glfw::FramebufferSizeCallback for FramebufferSizeContext {
    fn call(&self, _: &glfw::Window, width: i32, height: i32) {
        self.chan.send((width as u32,height as u32));
    }
}
<commit_msg>increase render distance<commit_after>// Copyright 2014 Rich Lane.

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

#[feature(globs)];
#[feature(macro_rules)];

extern mod native;
extern mod extra;
extern mod glfw;
extern mod gl;
extern mod cgmath;
extern mod noise;

use std::libc;

use gl::types::*;

use cgmath::matrix::Matrix;
use cgmath::matrix::Mat3;
use cgmath::matrix::ToMat4;
use cgmath::vector::Vector;
use cgmath::vector::Vec2;
use cgmath::vector::Vec3;
use cgmath::angle::rad;
use cgmath::ptr::Ptr;

use spiral::Spiral;
use chunk::Chunk;
use chunk::ChunkLoader;

#[cfg(target_os = "linux")]
#[link(name="GLU")]
extern {}

mod offset_of;
mod chunk;
mod ratelimiter;
mod texture;
mod spiral;
mod renderer;

pub static VISIBLE_RADIUS: uint = 12;
pub static CHUNK_SIZE: uint = 32;
pub static WORLD_SEED: u32 = 42;

static CAMERA_SPEED : f32 = 30.0f32;

static DEFAULT_WINDOW_SIZE : Vec2<u32> = Vec2 { x: 800, y: 600 };

#[start]
fn start(argc: int, argv: **u8) -> int {
    do native::start(argc, argv) {
        main();
    }
}

fn main() {
   glfw::set_error_callback(~ErrorContext);

    do glfw::start {
        glfw::window_hint::samples(8);

        let window = glfw::Window::create(
            DEFAULT_WINDOW_SIZE.x, DEFAULT_WINDOW_SIZE.y,
            "Cubeland", glfw::Windowed)
            .expect("Failed to create GLFW window.");

        window.set_cursor_mode(glfw::CursorDisabled);
        window.make_context_current();

        gl::load_with(glfw::get_proc_address);

        glfw::set_swap_interval(1);

        let mut renderer = renderer::Renderer::new(DEFAULT_WINDOW_SIZE);

        let mut chunk_loader = ChunkLoader::new(WORLD_SEED);

        let (key_port, key_chan) = std::comm::Chan::new();
        window.set_key_callback(~KeyContext { chan: key_chan });

        let (fb_size_port, fb_size_chan): (Port<(u32,u32)>, Chan<(u32,u32)>) = std::comm::Chan::new();
        window.set_framebuffer_size_callback(~FramebufferSizeContext { chan: fb_size_chan });

        let mut fps_display_limiter = ratelimiter::RateLimiter::new(1000*1000*1000);
        let mut fps_frame_counter = 0;

        let mut camera_position = Vec3::<f32>::new(0.0f32, 30.0f32, 40.0f32);

        let mut last_tick = extra::time::precise_time_ns();

        let mut grabbed = true;

        let mut camera_angle_x = 0.0;
        let mut camera_angle_y = 0.0;

        while !window.should_close() {
            glfw::poll_events();

            loop {
                match fb_size_port.try_recv() {
                    Some((w,h)) => {
                        renderer.set_window_size(Vec2 { x: w, y: h });
                    }
                    None => break
                }
            }

            loop {
                match key_port.try_recv() {
                    Some((glfw::Press, glfw::KeyR)) => {
                        renderer.reload_resources();
                    },
                    Some((glfw::Press, glfw::KeyEscape)) => {
                        window.set_should_close(true);
                    },
                    Some((glfw::Press, glfw::KeyG)) => {
                        grabbed = !grabbed;
                        if grabbed {
                            window.set_cursor_mode(glfw::CursorDisabled);
                        } else {
                            window.set_cursor_mode(glfw::CursorNormal);
                        }
                    },
                    Some((glfw::Press, glfw::KeyL)) => {
                        renderer.toggle_wireframe_mode();
                    },
                    None => break,
                    _ => {}
                }
            }

            if grabbed {
                let (cursor_x, cursor_y) = window.get_cursor_pos();
                camera_angle_y = ((cursor_x * 0.0005) % 1.0) * std::f64::consts::PI * 2.0;
                camera_angle_x = ((cursor_y * 0.0005) % 1.0) * std::f64::consts::PI * 2.0;
            }

            let mut camera_velocity = Vec3::<f32>::new(0.0f32, 0.0f32, 0.0f32);

            match window.get_key(glfw::KeySpace) {
                glfw::Press => { camera_velocity.y += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyLeftControl) {
                glfw::Press => { camera_velocity.y += -1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyS) {
                glfw::Press => { camera_velocity.z += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyW) {
                glfw::Press => { camera_velocity.z += -1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyD) {
                glfw::Press => { camera_velocity.x += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyA) {
                glfw::Press => { camera_velocity.x += -1.0f32 }
                _ => {}
            }

            let now = extra::time::precise_time_ns();
            let tick_length = (now - last_tick) as f32 / (1000 * 1000 * 1000) as f32;
            last_tick = now;

            let inv_camera_rotation = Mat3::<f32>::from_euler(rad(-camera_angle_x as f32), rad(-camera_angle_y as f32), rad(0.0f32));
            let absolute_camera_velocity = inv_camera_rotation.mul_v(&camera_velocity).mul_s(CAMERA_SPEED).mul_s(tick_length);
            camera_position.add_self_v(&absolute_camera_velocity);

            let camera_position_i64 = Vec3 {
                x: camera_position.x as i64,
                y: 0,
                z: camera_position.z as i64
            };

            {
                let chunks = find_nearby_chunks(&chunk_loader, camera_position_i64);

                renderer.render(
                    chunks,
                    camera_position,
                    Vec2 { x: camera_angle_x, y: camera_angle_y });
            }

            window.swap_buffers();

            request_nearby_chunks(&mut chunk_loader, camera_position_i64);
            chunk_loader.work();

            check_gl("main loop");

            fps_frame_counter += 1;
            if fps_display_limiter.limit() {
                println!("{} frames per second", fps_frame_counter);
                fps_frame_counter = 0;
            }
        }
    }
}

fn nearby_chunk_coords(p: Vec3<i64>) -> ~[(i64, i64)] {
    static num_chunks : uint = (VISIBLE_RADIUS * 2 + 1) * (VISIBLE_RADIUS * 2 + 1);
    static mask : i64 = !(CHUNK_SIZE as i64 - 1);

    let chunk_coord = |v: Vec2<i64>| -> (i64, i64) {
        (
            (p.x & mask) + v.x*CHUNK_SIZE as i64,
            (p.z & mask) + v.y*CHUNK_SIZE as i64
        )
    };

    Spiral::<i64>::new(num_chunks).map(chunk_coord).to_owned_vec()
}

fn find_nearby_chunks<'a>(chunk_loader: &'a ChunkLoader, p: Vec3<i64>) -> ~[&'a ~Chunk] {
    let coords = nearby_chunk_coords(p);
    coords.iter().
        filter_map(|&c| chunk_loader.get(c)).
        to_owned_vec()
}

fn request_nearby_chunks(chunk_loader: &mut ChunkLoader, p: Vec3<i64>) {
    let coords = nearby_chunk_coords(p);
    for &c in coords.iter() {
        chunk_loader.request(c);
    }
}

extern "C" {
    fn gluErrorString(error: GLenum) -> *GLubyte;
}

fn check_gl(message : &str) {
    let err = gl::GetError();
    if (err != gl::NO_ERROR) {
        unsafe {
            let err = std::str::raw::from_c_str(gluErrorString(err) as *i8);
            fail!("GL error {} at {}", err, message);
        }
    }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        fail!("GLFW Error: {:s}", description);
    }
}

struct KeyContext {
    chan : Chan<(glfw::Action, glfw::Key)>,
}
impl glfw::KeyCallback for KeyContext {
    fn call(&self, _: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
        self.chan.send((action, key));
    }
}

struct FramebufferSizeContext {
    chan: Chan<(u32,u32)>
}
impl glfw::FramebufferSizeCallback for FramebufferSizeContext {
    fn call(&self, _: &glfw::Window, width: i32, height: i32) {
        self.chan.send((width as u32,height as u32));
    }
}
<|endoftext|>


<commit_before>use std;

import std::vec;
import std::str;

native "cdecl" mod libc = "" {
    fn my_strlen(str: *u8) -> uint = "strlen";
}

fn strlen(str: str) -> uint unsafe {
    // C string is terminated with a zero
    let bytes = str::bytes(str) + [0u8];
    ret libc::my_strlen(vec::unsafe::to_ptr(bytes));
}

fn main(_args: [str]) {
    let len = strlen("Rust");
    assert(len == 4u);
}
<commit_msg>Make run-pass/native-fn-linkname's main take no args<commit_after>use std;

import std::vec;
import std::str;

native "cdecl" mod libc = "" {
    fn my_strlen(str: *u8) -> uint = "strlen";
}

fn strlen(str: str) -> uint unsafe {
    // C string is terminated with a zero
    let bytes = str::bytes(str) + [0u8];
    ret libc::my_strlen(vec::unsafe::to_ptr(bytes));
}

fn main() {
    let len = strlen("Rust");
    assert(len == 4u);
}
<|endoftext|>


<commit_before>//! `StructureLab` data description.
use super::super::resources::{ResourceType, Store};
use crate::data::RoomName;

with_structure_fields_and_update_struct! {
    /// A lab structure - a structure that can be filled with energy and minerals, merge minerals with
    /// minerals from other labs, and use minerals and energy to boost creeps.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureLab {
        /// The user ID of the owner of this structure.
        pub user: String,
        /// Whether or not this structure is non-functional due to a degraded controller.
        #[serde(default, rename = "off")]
        pub disabled: bool,
        /// The amount of energy and the and a mineral or a compound that is stored in this structure.
        pub store: Store,
        /// The total amount of each resource that can be stored in this structure.
        #[serde(rename = "storeCapacityResource")]
        pub capacity_resource: Store,
        /// The tick until which this lab can't run any reactions.
        pub cooldown_time: i32,
        /// A record of all actions this structure performed last tick.
        pub action_log: StructureLabActions,
        /// Whether or not an attack on this structure will send an email to the owner automatically.
        pub notify_when_attacked: bool,
    }

    /// The update structure for a `StructureLab`.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureLabUpdate {
        - user: String,
        #[serde(rename = "off")]
        - disabled: bool,
        - store: Store,
        - capacity_resource: Store,
        - cooldown_time: i32,
        - action_log: StructureLabActions,
        - notify_when_attacked: bool,
    }
}

with_update_struct! {
    /// A struct describing the source labs for a lab performing a mineral reaction.
    #[derive(serde_derive::Deserialize, Clone, Debug, PartialEq)]
    pub struct LabActionTarget {
        /// The x position of the first source lab.
        pub x1: u32,
        /// The y position of the first source lab.
        pub y1: u32,
        /// The x position of the second source lab.
        pub x2: u32,
        /// The y position of the second source lab.
        pub y2: u32,
    }

    /// The update structure for a `LabActionTarget`.
    #[derive(serde_derive::Deserialize, Clone, Debug)]
    pub struct LabActionTargetUpdate { ... }
}

with_update_struct! {
    /// A struct describing a lab's actions.
    #[derive(serde_derive::Deserialize, Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureLabActions {
        /// The two source labs that provided minerals for the reaction that was run last tick.
        pub run_reaction: Option<LabActionTarget>,
    }

    /// The update structure for a `StructureLabActions`.
    #[derive(serde_derive::Deserialize, Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureLabActionsUpdate { ... }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;
    use serde_json;

    use crate::data::RoomName;

    use super::{LabActionTarget, ResourceType, StructureLab, StructureLabActions};

    #[test]
    fn parse_lab_and_updates() {
        let json = json!({
            "_id": "5aebc6e4ee797138fa7b4a4f",
            "type": "lab",
            "x": 24,
            "y": 17,
            "room": "E9S32",
            "notifyWhenAttacked": false,
            "user": "589f5265d25357e8253e3ee8",
            "hits": 500,
            "hitsMax": 500,
            "cooldown": 10,
            "actionLog": {
              "runReaction": {
                "x1": 24,
                "y1": 16,
                "x2": 23,
                "y2": 15
              },
              "reverseReaction": null
            },
            "store": {
              "energy": 2000,
              "XZHO2": 0,
              "XKHO2": 0,
              "KHO2": 0,
              "KO": 0,
              "XLHO2": 0,
              "XUH2O": 0,
              "ZO": 0,
              "G": 0,
              "UL": 0,
              "ZK": 0,
              "LO": 0,
              "UH2O": 0,
              "UH": 0,
              "OH": 0,
              "LHO2": 0,
              "ZHO2": 0,
              "ZH2O": 0,
              "GHO2": 0,
              "XGHO2": 0,
              "LH2O": 0,
              "LH": 0,
              "ZH": 0,
              "XZH2O": 0,
              "GO": 0,
              "XLH2O": 0,
              "UO": 45,
              "X": 0,
              "H": 0
            },
            "storeCapacityResource": {
              "energy": 2000,
              "XZHO2": null,
              "XKHO2": null,
              "KHO2": null,
              "KO": null,
              "XLHO2": null,
              "XUH2O": null,
              "ZO": null,
              "G": null,
              "UL": null,
              "ZK": null,
              "LO": null,
              "UH2O": null,
              "UH": null,
              "OH": null,
              "LHO2": null,
              "ZHO2": null,
              "ZH2O": null,
              "GHO2": null,
              "XGHO2": null,
              "LH2O": null,
              "LH": null,
              "ZH": null,
              "XZH2O": null,
              "GO": null,
              "XLH2O": null,
              "UO": 3000,
              "X": null,
              "H": null
            },
            "cooldownTime": 30246725,
            "storeCapacity": null,
            "effects": {
              "0": {
                "effect": 5,
                "power": 5,
                "level": 4,
                "endTime": 29752073
              }
            }
        });

        let mut obj = StructureLab::deserialize(json).unwrap();

        assert_eq!(
            obj,
            StructureLab {
                room: RoomName::new("E9S32").unwrap(),
                x: 24,
                y: 17,
                id: "5aebc6e4ee797138fa7b4a4f".to_owned(),
                store: store! { Energy: 2000, UtriumOxide: 45 },
                capacity_resource: store! { Energy: 2000, UtriumOxide: 3000 },
                hits: 500,
                hits_max: 500,
                cooldown_time: 30246725,
                notify_when_attacked: false,
                disabled: false,
                action_log: StructureLabActions {
                    run_reaction: Some(LabActionTarget {
                        x1: 24,
                        y1: 16,
                        x2: 23,
                        y2: 15,
                    })
                },
                user: "589f5265d25357e8253e3ee8".to_owned(),
            }
        );

        obj.update(
            serde_json::from_value(json!({
              "actionLog": {
                "runReaction": null
              }
            }))
            .unwrap(),
        );

        assert_eq!(obj.action_log.run_reaction, None);

        obj.update(
            serde_json::from_value(json!({
              "actionLog": {
                "runReaction": {
                  "x1": 24,
                  "y1": 16,
                  "x2": 23,
                  "y2": 15
                }
              },
              "store": {
                "UO": 50
              },
              "cooldownTime": 30246735
            }))
            .unwrap(),
        );

        assert_eq!(
            obj.action_log,
            StructureLabActions {
                run_reaction: Some(LabActionTarget {
                    x1: 24,
                    y1: 16,
                    x2: 23,
                    y2: 15,
                }),
            }
        );

        obj.update(
            serde_json::from_value(json!({
                "cooldown": 8,
                "actionLog": {
                    "runReaction": null,
                },
            }))
            .unwrap(),
        );

        assert_eq!(
            obj,
            StructureLab {
                room: RoomName::new("E9S32").unwrap(),
                x: 24,
                y: 17,
                id: "5aebc6e4ee797138fa7b4a4f".to_owned(),
                store: store! { Energy: 2000, UtriumOxide: 50 },
                capacity_resource: store! { Energy: 2000, UtriumOxide: 3000 },
                hits: 500,
                hits_max: 500,
                cooldown_time: 30246735,
                notify_when_attacked: false,
                disabled: false,
                action_log: StructureLabActions { run_reaction: None },
                user: "589f5265d25357e8253e3ee8".to_owned(),
            }
        );
    }

    #[test]
    fn parse_empty_lab() {
        let json = json!({
            "_id": "5d2aca5c5e41f216fb099492",
            "type": "lab",
            "x": 24,
            "y": 28,
            "room": "W44S12",
            "notifyWhenAttacked": true,
            "user": "5a8466038f866773f59fa6c8",
            "hits": 500,
            "hitsMax": 500,
            "cooldown": 0,
            "actionLog": {
              "runReaction": null,
              "reverseReaction": null
            },
            "store": {
              "energy": 2000,
              "ZH": 0,
              "UH": 0,
              "KO": 0,
              "LO": 0,
              "LH": 0,
              "ZK": 0,
              "UL": 0,
              "G": 0,
              "ZO": 0,
              "GO": 0,
              "UO": 0,
              "OH": 0,
              "UH2O": 0,
              "XUH2O": 0,
              "KHO2": 0,
              "LHO2": 0,
              "XKHO2": 0,
              "GH": 0,
              "XLHO2": 0,
              "ZHO2": 0,
              "KH": 0,
              "GHO2": 0,
              "XZHO2": 0,
              "LH2O": 0,
              "XGHO2": 0,
              "ZH2O": 0,
              "XLH2O": 0,
              "XZH2O": 0,
              "KH2O": 0,
              "GH2O": 0,
              "XKH2O": 0,
              "UHO2": 0,
              "XGH2O": 0,
              "XUHO2": 0
            },
            "storeCapacity": 5000,
            "storeCapacityResource": {
              "energy": 2000,
              "ZH": null,
              "UH": null,
              "KO": null,
              "LO": null,
              "LH": null,
              "ZK": null,
              "UL": null,
              "G": null,
              "ZO": null,
              "GO": null,
              "UO": null,
              "OH": null,
              "UH2O": null,
              "XUH2O": null,
              "KHO2": null,
              "LHO2": null,
              "XKHO2": null,
              "GH": null,
              "XLHO2": null,
              "ZHO2": null,
              "KH": null,
              "GHO2": null,
              "XZHO2": null,
              "LH2O": null,
              "XGHO2": null,
              "ZH2O": null,
              "XLH2O": null,
              "XZH2O": null,
              "KH2O": null,
              "GH2O": null,
              "XKH2O": null,
              "UHO2": null,
              "XGH2O": null,
              "XUHO2": null
            },
            "cooldownTime": 23464205
        });

        let obj = StructureLab::deserialize(json).unwrap();

        assert_eq!(
            obj,
            StructureLab {
                room: RoomName::new("W44S12").unwrap(),
                x: 24,
                y: 28,
                id: "5d2aca5c5e41f216fb099492".to_owned(),
                store: store! { Energy: 2000 },
                capacity_resource: store! { Energy: 2000 },
                hits: 500,
                hits_max: 500,
                notify_when_attacked: true,
                disabled: false,
                cooldown_time: 23464205,
                action_log: StructureLabActions { run_reaction: None },
                user: "5a8466038f866773f59fa6c8".to_owned(),
            }
        );
    }
}
<commit_msg>Removed unused imports<commit_after>//! `StructureLab` data description.
use super::super::resources::Store;
use crate::data::RoomName;

with_structure_fields_and_update_struct! {
    /// A lab structure - a structure that can be filled with energy and minerals, merge minerals with
    /// minerals from other labs, and use minerals and energy to boost creeps.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureLab {
        /// The user ID of the owner of this structure.
        pub user: String,
        /// Whether or not this structure is non-functional due to a degraded controller.
        #[serde(default, rename = "off")]
        pub disabled: bool,
        /// The amount of energy and the and a mineral or a compound that is stored in this structure.
        pub store: Store,
        /// The total amount of each resource that can be stored in this structure.
        #[serde(rename = "storeCapacityResource")]
        pub capacity_resource: Store,
        /// The tick until which this lab can't run any reactions.
        pub cooldown_time: i32,
        /// A record of all actions this structure performed last tick.
        pub action_log: StructureLabActions,
        /// Whether or not an attack on this structure will send an email to the owner automatically.
        pub notify_when_attacked: bool,
    }

    /// The update structure for a `StructureLab`.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureLabUpdate {
        - user: String,
        #[serde(rename = "off")]
        - disabled: bool,
        - store: Store,
        - capacity_resource: Store,
        - cooldown_time: i32,
        - action_log: StructureLabActions,
        - notify_when_attacked: bool,
    }
}

with_update_struct! {
    /// A struct describing the source labs for a lab performing a mineral reaction.
    #[derive(serde_derive::Deserialize, Clone, Debug, PartialEq)]
    pub struct LabActionTarget {
        /// The x position of the first source lab.
        pub x1: u32,
        /// The y position of the first source lab.
        pub y1: u32,
        /// The x position of the second source lab.
        pub x2: u32,
        /// The y position of the second source lab.
        pub y2: u32,
    }

    /// The update structure for a `LabActionTarget`.
    #[derive(serde_derive::Deserialize, Clone, Debug)]
    pub struct LabActionTargetUpdate { ... }
}

with_update_struct! {
    /// A struct describing a lab's actions.
    #[derive(serde_derive::Deserialize, Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureLabActions {
        /// The two source labs that provided minerals for the reaction that was run last tick.
        pub run_reaction: Option<LabActionTarget>,
    }

    /// The update structure for a `StructureLabActions`.
    #[derive(serde_derive::Deserialize, Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureLabActionsUpdate { ... }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;
    use serde_json;

    use crate::data::RoomName;

    use super::{LabActionTarget, StructureLab, StructureLabActions};

    #[test]
    fn parse_lab_and_updates() {
        let json = json!({
            "_id": "5aebc6e4ee797138fa7b4a4f",
            "type": "lab",
            "x": 24,
            "y": 17,
            "room": "E9S32",
            "notifyWhenAttacked": false,
            "user": "589f5265d25357e8253e3ee8",
            "hits": 500,
            "hitsMax": 500,
            "cooldown": 10,
            "actionLog": {
              "runReaction": {
                "x1": 24,
                "y1": 16,
                "x2": 23,
                "y2": 15
              },
              "reverseReaction": null
            },
            "store": {
              "energy": 2000,
              "XZHO2": 0,
              "XKHO2": 0,
              "KHO2": 0,
              "KO": 0,
              "XLHO2": 0,
              "XUH2O": 0,
              "ZO": 0,
              "G": 0,
              "UL": 0,
              "ZK": 0,
              "LO": 0,
              "UH2O": 0,
              "UH": 0,
              "OH": 0,
              "LHO2": 0,
              "ZHO2": 0,
              "ZH2O": 0,
              "GHO2": 0,
              "XGHO2": 0,
              "LH2O": 0,
              "LH": 0,
              "ZH": 0,
              "XZH2O": 0,
              "GO": 0,
              "XLH2O": 0,
              "UO": 45,
              "X": 0,
              "H": 0
            },
            "storeCapacityResource": {
              "energy": 2000,
              "XZHO2": null,
              "XKHO2": null,
              "KHO2": null,
              "KO": null,
              "XLHO2": null,
              "XUH2O": null,
              "ZO": null,
              "G": null,
              "UL": null,
              "ZK": null,
              "LO": null,
              "UH2O": null,
              "UH": null,
              "OH": null,
              "LHO2": null,
              "ZHO2": null,
              "ZH2O": null,
              "GHO2": null,
              "XGHO2": null,
              "LH2O": null,
              "LH": null,
              "ZH": null,
              "XZH2O": null,
              "GO": null,
              "XLH2O": null,
              "UO": 3000,
              "X": null,
              "H": null
            },
            "cooldownTime": 30246725,
            "storeCapacity": null,
            "effects": {
              "0": {
                "effect": 5,
                "power": 5,
                "level": 4,
                "endTime": 29752073
              }
            }
        });

        let mut obj = StructureLab::deserialize(json).unwrap();

        assert_eq!(
            obj,
            StructureLab {
                room: RoomName::new("E9S32").unwrap(),
                x: 24,
                y: 17,
                id: "5aebc6e4ee797138fa7b4a4f".to_owned(),
                store: store! { Energy: 2000, UtriumOxide: 45 },
                capacity_resource: store! { Energy: 2000, UtriumOxide: 3000 },
                hits: 500,
                hits_max: 500,
                cooldown_time: 30246725,
                notify_when_attacked: false,
                disabled: false,
                action_log: StructureLabActions {
                    run_reaction: Some(LabActionTarget {
                        x1: 24,
                        y1: 16,
                        x2: 23,
                        y2: 15,
                    })
                },
                user: "589f5265d25357e8253e3ee8".to_owned(),
            }
        );

        obj.update(
            serde_json::from_value(json!({
              "actionLog": {
                "runReaction": null
              }
            }))
            .unwrap(),
        );

        assert_eq!(obj.action_log.run_reaction, None);

        obj.update(
            serde_json::from_value(json!({
              "actionLog": {
                "runReaction": {
                  "x1": 24,
                  "y1": 16,
                  "x2": 23,
                  "y2": 15
                }
              },
              "store": {
                "UO": 50
              },
              "cooldownTime": 30246735
            }))
            .unwrap(),
        );

        assert_eq!(
            obj.action_log,
            StructureLabActions {
                run_reaction: Some(LabActionTarget {
                    x1: 24,
                    y1: 16,
                    x2: 23,
                    y2: 15,
                }),
            }
        );

        obj.update(
            serde_json::from_value(json!({
                "cooldown": 8,
                "actionLog": {
                    "runReaction": null,
                },
            }))
            .unwrap(),
        );

        assert_eq!(
            obj,
            StructureLab {
                room: RoomName::new("E9S32").unwrap(),
                x: 24,
                y: 17,
                id: "5aebc6e4ee797138fa7b4a4f".to_owned(),
                store: store! { Energy: 2000, UtriumOxide: 50 },
                capacity_resource: store! { Energy: 2000, UtriumOxide: 3000 },
                hits: 500,
                hits_max: 500,
                cooldown_time: 30246735,
                notify_when_attacked: false,
                disabled: false,
                action_log: StructureLabActions { run_reaction: None },
                user: "589f5265d25357e8253e3ee8".to_owned(),
            }
        );
    }

    #[test]
    fn parse_empty_lab() {
        let json = json!({
            "_id": "5d2aca5c5e41f216fb099492",
            "type": "lab",
            "x": 24,
            "y": 28,
            "room": "W44S12",
            "notifyWhenAttacked": true,
            "user": "5a8466038f866773f59fa6c8",
            "hits": 500,
            "hitsMax": 500,
            "cooldown": 0,
            "actionLog": {
              "runReaction": null,
              "reverseReaction": null
            },
            "store": {
              "energy": 2000,
              "ZH": 0,
              "UH": 0,
              "KO": 0,
              "LO": 0,
              "LH": 0,
              "ZK": 0,
              "UL": 0,
              "G": 0,
              "ZO": 0,
              "GO": 0,
              "UO": 0,
              "OH": 0,
              "UH2O": 0,
              "XUH2O": 0,
              "KHO2": 0,
              "LHO2": 0,
              "XKHO2": 0,
              "GH": 0,
              "XLHO2": 0,
              "ZHO2": 0,
              "KH": 0,
              "GHO2": 0,
              "XZHO2": 0,
              "LH2O": 0,
              "XGHO2": 0,
              "ZH2O": 0,
              "XLH2O": 0,
              "XZH2O": 0,
              "KH2O": 0,
              "GH2O": 0,
              "XKH2O": 0,
              "UHO2": 0,
              "XGH2O": 0,
              "XUHO2": 0
            },
            "storeCapacity": 5000,
            "storeCapacityResource": {
              "energy": 2000,
              "ZH": null,
              "UH": null,
              "KO": null,
              "LO": null,
              "LH": null,
              "ZK": null,
              "UL": null,
              "G": null,
              "ZO": null,
              "GO": null,
              "UO": null,
              "OH": null,
              "UH2O": null,
              "XUH2O": null,
              "KHO2": null,
              "LHO2": null,
              "XKHO2": null,
              "GH": null,
              "XLHO2": null,
              "ZHO2": null,
              "KH": null,
              "GHO2": null,
              "XZHO2": null,
              "LH2O": null,
              "XGHO2": null,
              "ZH2O": null,
              "XLH2O": null,
              "XZH2O": null,
              "KH2O": null,
              "GH2O": null,
              "XKH2O": null,
              "UHO2": null,
              "XGH2O": null,
              "XUHO2": null
            },
            "cooldownTime": 23464205
        });

        let obj = StructureLab::deserialize(json).unwrap();

        assert_eq!(
            obj,
            StructureLab {
                room: RoomName::new("W44S12").unwrap(),
                x: 24,
                y: 28,
                id: "5d2aca5c5e41f216fb099492".to_owned(),
                store: store! { Energy: 2000 },
                capacity_resource: store! { Energy: 2000 },
                hits: 500,
                hits_max: 500,
                notify_when_attacked: true,
                disabled: false,
                cooldown_time: 23464205,
                action_log: StructureLabActions { run_reaction: None },
                user: "5a8466038f866773f59fa6c8".to_owned(),
            }
        );
    }
}
<|endoftext|>


<commit_before>
use std::io::Write;
use std::io::Error as IoError;
use std::ascii::AsciiExt;
use super::{Parsable, ParseError, Streamable};
use super::types::{DateTime, MailboxList, Mailbox, AddressList, CFWS, MsgId,
                   Unstructured};

macro_rules! req_name {
    ($rem:ident, $str:expr, $input:ident) => {
        let len: usize = $str.len();
        if $rem.len() < len || &(&$rem[0..len]).to_ascii_lowercase()!=$str {
            return Err(ParseError::NotFound);
        }
        $rem = &$rem[len..];
    };
}

macro_rules! req_crlf {
    ($rem:ident, $input:ident) => {
        if &$rem[..2] != b"\r\n" {
            return Err(ParseError::NotFound);
        }
        $rem = &$rem[2..];
    }
}

// 3.6.1
// orig-date       =   "Date:" date-time CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct OrigDate(pub DateTime);
impl Parsable for OrigDate {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"date:", input);
        if let Ok(dt) = parse!(DateTime, rem) {
            req_crlf!(rem, input);
            Ok((OrigDate(dt), rem))
        } else {
            Err(ParseError::NotFound)
        }
    }
}
impl Streamable for OrigDate {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Date:"))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// from            =   "From:" mailbox-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct From(pub MailboxList);
impl Parsable for From {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"from:", input);
        if let Ok(mbl) = parse!(MailboxList, rem) {
            req_crlf!(rem, input);
            return Ok((From(mbl), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for From {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"From: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// sender          =   "Sender:" mailbox CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Sender(pub Mailbox);
impl Parsable for Sender {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"sender:", input);
        if let Ok(mb) = parse!(Mailbox, rem) {
            req_crlf!(rem, input);
            return Ok((Sender(mb), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Sender {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Sender: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// reply-to        =   "Reply-To:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct ReplyTo(pub AddressList);
impl Parsable for ReplyTo {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"reply-to:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((ReplyTo(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for ReplyTo {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Reply-To: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// to              =   "To:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct To(pub AddressList);
impl Parsable for To {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"to:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((To(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for To {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"To: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// cc              =   "Cc:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Cc(pub AddressList);
impl Parsable for Cc {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"cc:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((Cc(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Cc {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Cc: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// bcc             =   "Bcc:" [address-list / CFWS] CRLF
#[derive(Debug, Clone, PartialEq)]
pub enum Bcc {
    AddressList(AddressList),
    CFWS(CFWS),
    Empty
}
impl Parsable for Bcc {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"bcc:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((Bcc::AddressList(x), rem));
        }
        if let Ok(x) = parse!(CFWS, rem) {
            req_crlf!(rem, input);
            return Ok((Bcc::CFWS(x), rem));
        }
        req_crlf!(rem, input);
        return Ok((Bcc::Empty, rem));
    }
}
impl Streamable for Bcc {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        let mut count: usize = 0;
        count += try!(w.write(b"Bcc: "));
        count += match *self {
            Bcc::AddressList(ref al) => try!(al.stream(w)),
            Bcc::CFWS(ref cfws) => try!(cfws.stream(w)),
            Bcc::Empty => 0,
        };
        count += try!(w.write(b"\r\n"));
        Ok(count)
    }
}

// 3.6.4
// message-id      =   "Message-ID:" msg-id CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct MessageId(pub MsgId);
impl Parsable for MessageId {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"message-id:", input);
        if let Ok(x) = parse!(MsgId, rem) {
            req_crlf!(rem, input);
            return Ok((MessageId(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for MessageId {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Message-ID: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.4
// in-reply-to     =   "In-Reply-To:" 1*msg-id CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct InReplyTo(pub Vec<MsgId>);
impl Parsable for InReplyTo {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        let mut contents: Vec<MsgId> = Vec::new();
        req_name!(rem, b"in-reply-to:", input);
        while let Ok(x) = parse!(MsgId, rem) {
            contents.push(x);
        }
        if contents.len() == 0 {
            return Err(ParseError::NotFound);
        }
        req_crlf!(rem, input);
        Ok((InReplyTo(contents), rem))
    }
}
impl Streamable for InReplyTo {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        let mut count: usize = 0;
        count += try!(w.write(b"In-Reply-To: "));
        for msgid in &self.0 {
            count += try!(msgid.stream(w))
        }
        count += try!(w.write(b"\r\n"));
        Ok(count)
    }
}

// 3.6.4
// references      =   "References:" 1*msg-id CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct References(pub Vec<MsgId>);
impl Parsable for References {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        let mut contents: Vec<MsgId> = Vec::new();
        req_name!(rem, b"references:", input);
        while let Ok(x) = parse!(MsgId, rem) {
            contents.push(x);
        }
        if contents.len() == 0 {
            return Err(ParseError::NotFound);
        }
        req_crlf!(rem, input);
        Ok((References(contents), rem))
    }
}
impl Streamable for References {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        let mut count: usize = 0;
        count += try!(w.write(b"References: "));
        for msgid in &self.0 {
            count += try!(msgid.stream(w))
        }
        count += try!(w.write(b"\r\n"));
        Ok(count)
    }
}

// 3.6.5
// subject         =   "Subject:" unstructured CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Subject(pub Unstructured);
impl Parsable for Subject {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"subject:", input);
        if let Ok(x) = parse!(Unstructured, rem) {
            req_crlf!(rem, input);
            return Ok((Subject(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Subject {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Subject: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.5
// comments        =   "Comments:" unstructured CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Comments(pub Unstructured);
impl Parsable for Comments {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"comments:", input);
        if let Ok(x) = parse!(Unstructured, rem) {
            req_crlf!(rem, input);
            return Ok((Comments(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Comments {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Comments: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}
<commit_msg>rfc5322: 3.6.5 keywords<commit_after>
use std::io::Write;
use std::io::Error as IoError;
use std::ascii::AsciiExt;
use super::{Parsable, ParseError, Streamable};
use super::types::{DateTime, MailboxList, Mailbox, AddressList, CFWS, MsgId,
                   Unstructured, Phrase};

macro_rules! req_name {
    ($rem:ident, $str:expr, $input:ident) => {
        let len: usize = $str.len();
        if $rem.len() < len || &(&$rem[0..len]).to_ascii_lowercase()!=$str {
            return Err(ParseError::NotFound);
        }
        $rem = &$rem[len..];
    };
}

macro_rules! req_crlf {
    ($rem:ident, $input:ident) => {
        if &$rem[..2] != b"\r\n" {
            return Err(ParseError::NotFound);
        }
        $rem = &$rem[2..];
    }
}

// 3.6.1
// orig-date       =   "Date:" date-time CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct OrigDate(pub DateTime);
impl Parsable for OrigDate {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"date:", input);
        if let Ok(dt) = parse!(DateTime, rem) {
            req_crlf!(rem, input);
            Ok((OrigDate(dt), rem))
        } else {
            Err(ParseError::NotFound)
        }
    }
}
impl Streamable for OrigDate {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Date:"))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// from            =   "From:" mailbox-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct From(pub MailboxList);
impl Parsable for From {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"from:", input);
        if let Ok(mbl) = parse!(MailboxList, rem) {
            req_crlf!(rem, input);
            return Ok((From(mbl), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for From {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"From: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// sender          =   "Sender:" mailbox CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Sender(pub Mailbox);
impl Parsable for Sender {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"sender:", input);
        if let Ok(mb) = parse!(Mailbox, rem) {
            req_crlf!(rem, input);
            return Ok((Sender(mb), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Sender {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Sender: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.2
// reply-to        =   "Reply-To:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct ReplyTo(pub AddressList);
impl Parsable for ReplyTo {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"reply-to:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((ReplyTo(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for ReplyTo {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Reply-To: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// to              =   "To:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct To(pub AddressList);
impl Parsable for To {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"to:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((To(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for To {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"To: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// cc              =   "Cc:" address-list CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Cc(pub AddressList);
impl Parsable for Cc {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"cc:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((Cc(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Cc {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Cc: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.3
// bcc             =   "Bcc:" [address-list / CFWS] CRLF
#[derive(Debug, Clone, PartialEq)]
pub enum Bcc {
    AddressList(AddressList),
    CFWS(CFWS),
    Empty
}
impl Parsable for Bcc {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"bcc:", input);
        if let Ok(x) = parse!(AddressList, rem) {
            req_crlf!(rem, input);
            return Ok((Bcc::AddressList(x), rem));
        }
        if let Ok(x) = parse!(CFWS, rem) {
            req_crlf!(rem, input);
            return Ok((Bcc::CFWS(x), rem));
        }
        req_crlf!(rem, input);
        return Ok((Bcc::Empty, rem));
    }
}
impl Streamable for Bcc {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        let mut count: usize = 0;
        count += try!(w.write(b"Bcc: "));
        count += match *self {
            Bcc::AddressList(ref al) => try!(al.stream(w)),
            Bcc::CFWS(ref cfws) => try!(cfws.stream(w)),
            Bcc::Empty => 0,
        };
        count += try!(w.write(b"\r\n"));
        Ok(count)
    }
}

// 3.6.4
// message-id      =   "Message-ID:" msg-id CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct MessageId(pub MsgId);
impl Parsable for MessageId {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"message-id:", input);
        if let Ok(x) = parse!(MsgId, rem) {
            req_crlf!(rem, input);
            return Ok((MessageId(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for MessageId {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Message-ID: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.4
// in-reply-to     =   "In-Reply-To:" 1*msg-id CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct InReplyTo(pub Vec<MsgId>);
impl Parsable for InReplyTo {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        let mut contents: Vec<MsgId> = Vec::new();
        req_name!(rem, b"in-reply-to:", input);
        while let Ok(x) = parse!(MsgId, rem) {
            contents.push(x);
        }
        if contents.len() == 0 {
            return Err(ParseError::NotFound);
        }
        req_crlf!(rem, input);
        Ok((InReplyTo(contents), rem))
    }
}
impl Streamable for InReplyTo {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        let mut count: usize = 0;
        count += try!(w.write(b"In-Reply-To: "));
        for msgid in &self.0 {
            count += try!(msgid.stream(w))
        }
        count += try!(w.write(b"\r\n"));
        Ok(count)
    }
}

// 3.6.4
// references      =   "References:" 1*msg-id CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct References(pub Vec<MsgId>);
impl Parsable for References {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        let mut contents: Vec<MsgId> = Vec::new();
        req_name!(rem, b"references:", input);
        while let Ok(x) = parse!(MsgId, rem) {
            contents.push(x);
        }
        if contents.len() == 0 {
            return Err(ParseError::NotFound);
        }
        req_crlf!(rem, input);
        Ok((References(contents), rem))
    }
}
impl Streamable for References {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        let mut count: usize = 0;
        count += try!(w.write(b"References: "));
        for msgid in &self.0 {
            count += try!(msgid.stream(w))
        }
        count += try!(w.write(b"\r\n"));
        Ok(count)
    }
}

// 3.6.5
// subject         =   "Subject:" unstructured CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Subject(pub Unstructured);
impl Parsable for Subject {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"subject:", input);
        if let Ok(x) = parse!(Unstructured, rem) {
            req_crlf!(rem, input);
            return Ok((Subject(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Subject {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Subject: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.5
// comments        =   "Comments:" unstructured CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Comments(pub Unstructured);
impl Parsable for Comments {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"comments:", input);
        if let Ok(x) = parse!(Unstructured, rem) {
            req_crlf!(rem, input);
            return Ok((Comments(x), rem));
        }
        Err(ParseError::NotFound)
    }
}
impl Streamable for Comments {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        Ok(try!(w.write(b"Comments: "))
           + try!(self.0.stream(w))
           + try!(w.write(b"\r\n")))
    }
}

// 3.6.5
// keywords        =   "Keywords:" phrase *("," phrase) CRLF
#[derive(Debug, Clone, PartialEq)]
pub struct Keywords(pub Vec<Phrase>);
impl Parsable for Keywords {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        if input.len() == 0 { return Err(ParseError::Eof); }
        let mut rem = input;
        req_name!(rem, b"keywords:", input);
        let mut output: Vec<Phrase> = Vec::new();
        while let Ok(x) = parse!(Phrase, rem) {
            output.push(x);
        }
        if output.len()==0 {
            return Err(ParseError::NotFound);
        }
        req_crlf!(rem, input);
        Ok((Keywords(output), rem))
    }
}
impl Streamable for Keywords {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        let mut count: usize = 0;
        count += try!(w.write(b"Keywords: "));
        let mut virgin = true;
        for phrase in &self.0 {
            if ! virgin {
                count += try!(w.write(b","));
            }
            count += try!(phrase.stream(w));
            virgin = false
        }
        count += try!(w.write(b"\r\n"));
        Ok(count)
    }
}
<|endoftext|>


<commit_before>/// This file contains commands to generally control and administer the bot.
use irc::Client;
use irc::interface::CommandEvent;

fn say(event: &CommandEvent) {
    if event.args[0].starts_with("#") {
        if !event.client.is_admin(event) {
            return;
        }
        event.client.send_message(event.args[0], &*event.args.slice_from(1).connect(" "));
    } else {
        event.client.send_message(event.channel, &*event.args.connect(" "));
    }
}

fn quit(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return
    }
    event.client.send_command("QUIT".to_string(), &[]);
}

fn raw(event: &CommandEvent) {
    event.client.send_raw(event.args.connect(" "));
    event.client.send_message(event.channel, "Sent raw message.");
}

fn join(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return;
    }
    event.client.join(event.args[0]);
    event.client.send_message(event.channel, format!("Joined {}.", event.args[0]).as_slice());
}

fn part(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return;
    }
    if event.args.len() > 1 {
        event.client.part(event.args[0], Some(event.args.slice_from(1).connect(" ").as_slice()));
    } else {
        event.client.part(event.args[0], None)
    }

    event.client.send_message(event.channel, format!("Parted {}.", event.args[0]).as_slice());
}

fn message(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return;
    }
    event.client.send_message(event.args[0], event.args.slice_from(1).connect(" ").as_slice());
    event.client.send_message(event.channel, format!("Sent message to {}.", event.args[0]).as_slice());
}

pub fn register(client: &mut Client) {
    client.add_command("say", say);
    client.add_command("message", message);
    client.add_command("raw", raw);
    client.add_command("join", join);
    client.add_command("part", part);
    client.add_command("leave", part);
    client.add_command("quit", quit);
}
<commit_msg>Require admin permissions for any say command at all<commit_after>/// This file contains commands to generally control and administer the bot.
use irc::Client;
use irc::interface::CommandEvent;

fn say(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return;
    }
    if event.args[0].starts_with("#") {
        event.client.send_message(event.args[0], event.args.slice_from(1).connect(" ").as_slice());
    } else {
        event.client.send_message(event.channel, event.args.connect(" ").as_slice());
    }
}

fn quit(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return
    }
    event.client.send_command("QUIT".to_string(), &[]);
}

fn raw(event: &CommandEvent) {
    event.client.send_raw(event.args.connect(" "));
    event.client.send_message(event.channel, "Sent raw message.");
}

fn join(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return;
    }
    event.client.join(event.args[0]);
    event.client.send_message(event.channel, format!("Joined {}.", event.args[0]).as_slice());
}

fn part(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return;
    }
    if event.args.len() > 1 {
        event.client.part(event.args[0], Some(event.args.slice_from(1).connect(" ").as_slice()));
    } else {
        event.client.part(event.args[0], None)
    }

    event.client.send_message(event.channel, format!("Parted {}.", event.args[0]).as_slice());
}

fn message(event: &CommandEvent) {
    if !event.client.is_admin(event) {
        return;
    }
    event.client.send_message(event.args[0], event.args.slice_from(1).connect(" ").as_slice());
    event.client.send_message(event.channel, format!("Sent message to {}.", event.args[0]).as_slice());
}

pub fn register(client: &mut Client) {
    client.add_command("say", say);
    client.add_command("message", message);
    client.add_command("raw", raw);
    client.add_command("join", join);
    client.add_command("part", part);
    client.add_command("leave", part);
    client.add_command("quit", quit);
}
<|endoftext|>


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

use crate::types::Namespace;
use syn::{parse_quote, Ident, Type};

#[derive(Clone)]
pub(crate) enum CppConversionType {
    None,
    FromUniquePtrToValue,
    FromValueToUniquePtr,
}

#[derive(Clone)]
pub(crate) enum RustConversionType {
    None,
    FromStr,
}

/// A policy for converting types. Conversion may occur on both the Rust and
/// C++ side. The most complex example is a C++ function which takes
/// std::string by value, which might do this:
/// * Client Rust code: `&str`
/// * Rust wrapper function: converts `&str` to `UniquePtr<CxxString>`
/// * cxx::bridge mod: refers to `UniquePtr<CxxString>`
/// * C++ wrapper function converts `std::unique_ptr<std::string>` to just
///   `std::string`
/// * Finally, the actual C++ API receives a `std::string` by value.
/// The implementation here is distributed across this file, and
/// `function_wrapper_rs` and `function_wrapper_cpp`.
#[derive(Clone)]
pub(crate) struct TypeConversionPolicy {
    pub(crate) unwrapped_type: Type,
    pub(crate) cpp_conversion: CppConversionType,
    pub(crate) rust_conversion: RustConversionType,
}

impl TypeConversionPolicy {
    pub(crate) fn new_unconverted(ty: Type) -> Self {
        TypeConversionPolicy {
            unwrapped_type: ty,
            cpp_conversion: CppConversionType::None,
            rust_conversion: RustConversionType::None,
        }
    }

    pub(crate) fn new_to_unique_ptr(ty: Type) -> Self {
        TypeConversionPolicy {
            unwrapped_type: ty,
            cpp_conversion: CppConversionType::FromValueToUniquePtr,
            rust_conversion: RustConversionType::None,
        }
    }

    pub(crate) fn new_from_unique_ptr(ty: Type) -> Self {
        TypeConversionPolicy {
            unwrapped_type: ty,
            cpp_conversion: CppConversionType::FromUniquePtrToValue,
            rust_conversion: RustConversionType::None,
        }
    }

    pub(crate) fn new_from_str(ty: Type) -> Self {
        TypeConversionPolicy {
            unwrapped_type: ty,
            cpp_conversion: CppConversionType::FromUniquePtrToValue,
            rust_conversion: RustConversionType::FromStr,
        }
    }

    pub(crate) fn cpp_work_needed(&self) -> bool {
        !matches!(self.cpp_conversion, CppConversionType::None)
    }

    pub(crate) fn unconverted_rust_type(&self) -> Type {
        match self.cpp_conversion {
            CppConversionType::FromValueToUniquePtr => self.make_unique_ptr_type(),
            _ => self.unwrapped_type.clone(),
        }
    }

    pub(crate) fn converted_rust_type(&self) -> Type {
        match self.cpp_conversion {
            CppConversionType::FromUniquePtrToValue => self.make_unique_ptr_type(),
            _ => self.unwrapped_type.clone(),
        }
    }

    fn make_unique_ptr_type(&self) -> Type {
        let innerty = &self.unwrapped_type;
        parse_quote! {
            cxx::UniquePtr < #innerty >
        }
    }

    pub(crate) fn rust_work_needed(&self) -> bool {
        !matches!(self.rust_conversion, RustConversionType::None)
    }
}

#[derive(Clone)] // TODO wish this didn't need to be cloneable
pub(crate) enum FunctionWrapperPayload {
    FunctionCall(Namespace, Ident),
    StaticMethodCall(Namespace, Ident, Ident),
    Constructor,
}

#[derive(Clone)] // TODO wish this didn't need to be cloneable
pub(crate) struct FunctionWrapper {
    pub(crate) payload: FunctionWrapperPayload,
    pub(crate) wrapper_function_name: Ident,
    pub(crate) return_conversion: Option<TypeConversionPolicy>,
    pub(crate) argument_conversion: Vec<TypeConversionPolicy>,
    pub(crate) is_a_method: bool,
}
<commit_msg>Remove some cloneability<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::types::Namespace;
use syn::{parse_quote, Ident, Type};

#[derive(Clone)]
pub(crate) enum CppConversionType {
    None,
    FromUniquePtrToValue,
    FromValueToUniquePtr,
}

#[derive(Clone)]
pub(crate) enum RustConversionType {
    None,
    FromStr,
}

/// A policy for converting types. Conversion may occur on both the Rust and
/// C++ side. The most complex example is a C++ function which takes
/// std::string by value, which might do this:
/// * Client Rust code: `&str`
/// * Rust wrapper function: converts `&str` to `UniquePtr<CxxString>`
/// * cxx::bridge mod: refers to `UniquePtr<CxxString>`
/// * C++ wrapper function converts `std::unique_ptr<std::string>` to just
///   `std::string`
/// * Finally, the actual C++ API receives a `std::string` by value.
/// The implementation here is distributed across this file, and
/// `function_wrapper_rs` and `function_wrapper_cpp`.
#[derive(Clone)]
pub(crate) struct TypeConversionPolicy {
    pub(crate) unwrapped_type: Type,
    pub(crate) cpp_conversion: CppConversionType,
    pub(crate) rust_conversion: RustConversionType,
}

impl TypeConversionPolicy {
    pub(crate) fn new_unconverted(ty: Type) -> Self {
        TypeConversionPolicy {
            unwrapped_type: ty,
            cpp_conversion: CppConversionType::None,
            rust_conversion: RustConversionType::None,
        }
    }

    pub(crate) fn new_to_unique_ptr(ty: Type) -> Self {
        TypeConversionPolicy {
            unwrapped_type: ty,
            cpp_conversion: CppConversionType::FromValueToUniquePtr,
            rust_conversion: RustConversionType::None,
        }
    }

    pub(crate) fn new_from_unique_ptr(ty: Type) -> Self {
        TypeConversionPolicy {
            unwrapped_type: ty,
            cpp_conversion: CppConversionType::FromUniquePtrToValue,
            rust_conversion: RustConversionType::None,
        }
    }

    pub(crate) fn new_from_str(ty: Type) -> Self {
        TypeConversionPolicy {
            unwrapped_type: ty,
            cpp_conversion: CppConversionType::FromUniquePtrToValue,
            rust_conversion: RustConversionType::FromStr,
        }
    }

    pub(crate) fn cpp_work_needed(&self) -> bool {
        !matches!(self.cpp_conversion, CppConversionType::None)
    }

    pub(crate) fn unconverted_rust_type(&self) -> Type {
        match self.cpp_conversion {
            CppConversionType::FromValueToUniquePtr => self.make_unique_ptr_type(),
            _ => self.unwrapped_type.clone(),
        }
    }

    pub(crate) fn converted_rust_type(&self) -> Type {
        match self.cpp_conversion {
            CppConversionType::FromUniquePtrToValue => self.make_unique_ptr_type(),
            _ => self.unwrapped_type.clone(),
        }
    }

    fn make_unique_ptr_type(&self) -> Type {
        let innerty = &self.unwrapped_type;
        parse_quote! {
            cxx::UniquePtr < #innerty >
        }
    }

    pub(crate) fn rust_work_needed(&self) -> bool {
        !matches!(self.rust_conversion, RustConversionType::None)
    }
}

pub(crate) enum FunctionWrapperPayload {
    FunctionCall(Namespace, Ident),
    StaticMethodCall(Namespace, Ident, Ident),
    Constructor,
}

pub(crate) struct FunctionWrapper {
    pub(crate) payload: FunctionWrapperPayload,
    pub(crate) wrapper_function_name: Ident,
    pub(crate) return_conversion: Option<TypeConversionPolicy>,
    pub(crate) argument_conversion: Vec<TypeConversionPolicy>,
    pub(crate) is_a_method: bool,
}
<|endoftext|>


<commit_before>use super::shared::hex_string_to_bytes;
use std::collections::HashMap;

// there has to be a better way to do this
fn base64_keys() -> HashMap<u8, char> {
    (('A' as u8)..('Z' as u8 + 1))
        .chain(('a' as u8)..('z' as u8 + 1))
        .chain(('0' as u8)..('9' as u8 + 1))
        .chain(('+' as u8)..('+' as u8 + 1))
        .chain(('/' as u8)..('/' as u8 + 1))
        .enumerate()
        .map(|(k, v)| (k as u8, v as char))
        .collect()
}

fn triplet_to_base64(triplet: u32) -> Vec<char> {
    let base64_chars = base64_keys();
    let mut chars: Vec<char> = Vec::new();
    let mut trip = triplet;

    // we only care about the bottom 3 bytes (4 6-bit values)
    while trip & 0xffffff != 0u32 {
        // base 64 has 64 keys (duh) so each key is 6 bits
        let key = (
            // drop the first 3 6-bit values
            (trip >> 18)
            // and mask off the remaining 6-bit value
            & 0x3f
        ) as u8;
        chars.push(*base64_chars.get(&key).unwrap());
        trip <<= 6;
    }

    chars
}

pub fn hex_to_base64(hex_str: &str) -> String {
    let bytes = hex_string_to_bytes(hex_str).unwrap();
    let mut chars: Vec<char> = Vec::new();

    let mut triplet = 0u32;

    for i in 0..bytes.len() {
        triplet = (triplet << 8) + bytes.get(i).unwrap().clone() as u32;

        if i % 3 == 2 {
            for c in triplet_to_base64(triplet).iter() {
                chars.push(c.clone());
            }
        }
    }

    chars.into_iter().collect()
}

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

    #[test]
    fn test_hex_to_base64() {
        let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
        let expected = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t".to_string();
        assert_eq!(expected, hex_to_base64(input));
    }
}
<commit_msg>Fix base64 conversion for incomplete triplets<commit_after>use super::shared::hex_string_to_bytes;
use std::collections::HashMap;

// there has to be a better way to do this
fn base64_keys() -> HashMap<u8, char> {
    (('A' as u8)..('Z' as u8 + 1))
        .chain(('a' as u8)..('z' as u8 + 1))
        .chain(('0' as u8)..('9' as u8 + 1))
        .chain(('+' as u8)..('+' as u8 + 1))
        .chain(('/' as u8)..('/' as u8 + 1))
        .enumerate()
        .map(|(k, v)| (k as u8, v as char))
        .collect()
}

fn triplet_to_base64(triplet: u32) -> Vec<char> {
    let base64_chars = base64_keys();
    let mut chars: Vec<char> = Vec::new();
    let mut trip = triplet;

    // we only care about the bottom 3 bytes (4 6-bit values)
    while trip & 0xffffff != 0u32 {
        // base 64 has 64 keys (duh) so each key is 6 bits
        let key = (
            // drop the first 3 6-bit values
            (trip >> 18)
            // and mask off the remaining 6-bit value
            & 0x3f
        ) as u8;
        chars.push(*base64_chars.get(&key).unwrap());
        trip <<= 6;
    }

    while chars.len() < 4 {
        chars.push('=');
    }

    chars
}

pub fn hex_to_base64(hex_str: &str) -> String {
    // this probably shouldn't be a .unwrap()
    let bytes = hex_string_to_bytes(hex_str).unwrap();
    let mut chars: Vec<char> = Vec::new();

    let mut triplet = 0u32;
    let triplet_count = (bytes.len() + 2) / 3;

    for i in 0..(triplet_count * 3) {
        let num = if let Some(n) = bytes.get(i) { *n } else { 0 } as u32;
        triplet = (triplet << 8) + num;

        if i % 3 == 2 {
            for c in triplet_to_base64(triplet).iter() {
                chars.push(*c);
            }
        }
    }

    chars.into_iter().collect()
}

#[cfg(test)]
mod test {
    use super::super::shared::bytes_to_hex_string;
    use super::hex_to_base64;

    #[test]
    fn test_hex_to_base64() {
        let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
        let expected = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t".to_string();
        assert_eq!(expected, hex_to_base64(input));

        let input = bytes_to_hex_string("this is a test".as_bytes().to_vec());
        let expected = "dGhpcyBpcyBhIHRlc3Q=".to_string();
        assert_eq!(expected, hex_to_base64(&input));

        let input = "4d";
        let expected = "TQ==".to_string();
        assert_eq!(expected, hex_to_base64(input));
    }
}
<|endoftext|>


<commit_before>/// The game's grid, internally represented by matrices provided by the nalgebra crate.
pub struct Grid {

}
<commit_msg>Voeg een korte implementatie van de grid toe<commit_after>use nalgebra::DMatrix;
use std::ops::{Index, IndexMut};

/// The game's grid, internally represented by matrices provided by the nalgebra crate.
pub struct Grid {
    matrix: DMatrix<bool>,
}

impl Grid {
    /// Create a new grid with the specified dimensions. All cells default to `false`.
    pub fn new(rows: usize, columns: usize) -> Grid {
        Grid { matrix: DMatrix::from_element(rows, columns, false) }
    }

    /// The number of columns in the grid.
    pub fn cols(&self) -> usize {
        self.matrix.ncols()
    }

    /// The number of rows in the grid.
    pub fn rows(&self) -> usize {
        self.matrix.nrows()
    }
}

impl Index<(usize, usize)> for Grid {
    type Output = bool;

    fn index(&self, index: (usize, usize)) -> &bool {
        &self.matrix[index]
    }
}

impl IndexMut<(usize, usize)> for Grid {
    fn index_mut(&mut self, index: (usize, usize)) -> &mut bool {
        &mut self.matrix[index]
    }
}
<|endoftext|>