<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

// This is more or less in the order it appears in the Lua manual, with the
// exception of constants, which appear scattered throughout the manual text.

// luaconf.h functions
pub use self::luaconf::lua_numtointeger;

// C API types
pub use self::lua::{
  lua_Alloc,
  lua_CFunction,
  lua_Ctx,
  lua_Debug,
  lua_Hook,
  lua_Integer,
  lua_KFunction,
  lua_Number,
  lua_Reader,
  lua_State,
  lua_Unsigned,
  lua_Writer
};

// C API functions
pub use self::lua::{
  lua_absindex,
  lua_arith,
  lua_atpanic,
  lua_call,
  lua_callk,
  lua_checkstack,
  lua_close,
  lua_compare,
  lua_concat,
  lua_copy,
  lua_createtable,
  lua_dump,
  lua_error,
  lua_gc,
  lua_getallocf,
  lua_getextraspace,
  lua_getfield,
  lua_getglobal,
  lua_gethook,
  lua_gethookcount,
  lua_gethookmask,
  lua_getinfo,
  lua_getlocal,
  lua_getmetatable,
  lua_getstack,
  lua_gettable,
  lua_gettop,
  lua_getupvalue,
  lua_getuservalue,
  lua_insert,
  lua_isboolean,
  lua_iscfunction,
  lua_isfunction,
  lua_isinteger,
  lua_islightuserdata,
  lua_isnil,
  lua_isnone,
  lua_isnoneornil,
  lua_isnumber,
  lua_isstring,
  lua_istable,
  lua_isthread,
  lua_isuserdata,
  lua_isyieldable,
  lua_len,
  lua_load,
  lua_newstate,
  lua_newtable,
  lua_newthread,
  lua_newuserdata,
  lua_next,
  lua_pcall,
  lua_pcallk,
  lua_pop,
  lua_pushboolean,
  lua_pushcclosure,
  lua_pushcfunction,
  lua_pushfstring,
  lua_pushglobaltable,
  lua_pushinteger,
  lua_pushlightuserdata,
  lua_pushliteral,
  lua_pushlstring,
  lua_pushnil,
  lua_pushnumber,
  lua_pushstring,
  lua_pushthread,
  lua_pushvalue,
  // omitted: lua_pushvfstring
  lua_rawequal,
  lua_rawget,
  lua_rawgeti,
  lua_rawgetp,
  lua_rawlen,
  lua_rawset,
  lua_rawseti,
  lua_rawsetp,
  lua_register,
  lua_remove,
  lua_replace,
  lua_resume,
  lua_rotate,
  lua_setallocf,
  lua_setfield,
  lua_setglobal,
  lua_sethook,
  lua_setlocal,
  lua_setmetatable,
  lua_settable,
  lua_settop,
  lua_setupvalue,
  lua_setuservalue,
  lua_status,
  lua_strtonum,
  lua_toboolean,
  lua_tocfunction,
  lua_tointeger,
  lua_tointegerx,
  lua_tolstring,
  lua_tonumber,
  lua_tonumberx,
  lua_topointer,
  lua_tostring,
  lua_tothread,
  lua_touserdata,
  lua_type,
  lua_typename,
  lua_upvalueid,
  lua_upvalueindex,
  lua_upvaluejoin,
  lua_version,
  lua_xmove,
  lua_yield,
  lua_yieldk
};

// auxiliary library types
pub use self::lauxlib::{
  luaL_Buffer,
  luaL_Reg,
  luaL_Stream
};

// auxiliary library functions
pub use self::lauxlib::{
  luaL_addchar,
  luaL_addlstring,
  luaL_addsize,
  luaL_addstring,
  luaL_addvalue,
  luaL_argcheck,
  luaL_argerror,
  luaL_buffinit,
  luaL_buffinitsize,
  luaL_callmeta,
  luaL_checkany,
  luaL_checkint,
  luaL_checkinteger,
  luaL_checklong,
  luaL_checklstring,
  luaL_checknumber,
  luaL_checkoption,
  luaL_checkstack,
  luaL_checkstring,
  luaL_checktype,
  luaL_checkudata,
  luaL_checkversion,
  luaL_dofile,
  luaL_dostring,
  luaL_error,
  luaL_execresult,
  luaL_fileresult,
  luaL_getmetafield,
  luaL_getmetatable,
  luaL_getsubtable,
  luaL_gsub,
  luaL_len,
  luaL_loadbuffer,
  luaL_loadbufferx,
  luaL_loadfile,
  luaL_loadfilex,
  luaL_loadstring,
  luaL_newlib,
  luaL_newlibtable,
  luaL_newmetatable,
  luaL_newstate,
  luaL_optint,
  luaL_optinteger,
  luaL_optlong,
  luaL_optlstring,
  luaL_optnumber,
  luaL_optstring,
  luaL_prepbuffer,
  luaL_prepbuffsize,
  luaL_pushresult,
  luaL_pushresultsize,
  luaL_ref,
  luaL_requiref,
  luaL_setfuncs,
  luaL_setmetatable,
  luaL_testudata,
  luaL_tolstring,
  luaL_traceback,
  luaL_typename,
  luaL_unref,
  luaL_where
};

// lualib.h functions
pub use self::lualib::{
  luaopen_base,
  luaopen_coroutine,
  luaopen_table,
  luaopen_io,
  luaopen_os,
  luaopen_string,
  luaopen_utf8,
  luaopen_bit32,
  luaopen_math,
  luaopen_debug,
  luaopen_package,

  luaL_openlibs
};

// constants from lua.h
pub use self::lua::{
  LUA_MULTRET,
  LUA_REGISTRYINDEX,

  LUA_RIDX_MAINTHREAD, LUA_RIDX_GLOBALS,

  LUA_OPADD, LUA_OPSUB, LUA_OPMUL, LUA_OPDIV, LUA_OPIDIV,
  LUA_OPMOD, LUA_OPPOW, LUA_OPUNM,
  LUA_OPBNOT, LUA_OPBAND, LUA_OPBOR, LUA_OPBXOR, LUA_OPSHL, LUA_OPSHR,
  LUA_OPEQ, LUA_OPLT, LUA_OPLE,

  LUA_OK, LUA_ERRRUN, LUA_ERRMEM, LUA_ERRERR, LUA_ERRGCMM,

  LUA_TNONE, LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE,
  LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, LUA_TLIGHTUSERDATA,

  LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_HOOKLINE, LUA_HOOKCOUNT,

  LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCCOUNTB,
  LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCISRUNNING
};

// constants from lauxlib.h
pub use self::lauxlib::{
  LUA_REFNIL, LUA_NOREF,
  LUA_ERRFILE,
  LUA_FILEHANDLE
};

// constants from lualib.h
pub use self::lualib::{
  LUA_COLIBNAME, LUA_TABLIBNAME, LUA_IOLIBNAME, LUA_OSLIBNAME, LUA_STRLIBNAME,
  LUA_UTF8LIBNAME, LUA_BITLIBNAME, LUA_MATHLIBNAME, LUA_DBLIBNAME, LUA_LOADLIBNAME
};

mod glue;
pub mod luaconf;
pub mod lua;
pub mod lauxlib;
pub mod lualib;

<commit_msg>Re-export LUA_YIELD and LUA_SYNTAX<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

// This is more or less in the order it appears in the Lua manual, with the
// exception of constants, which appear scattered throughout the manual text.

// luaconf.h functions
pub use self::luaconf::lua_numtointeger;

// C API types
pub use self::lua::{
  lua_Alloc,
  lua_CFunction,
  lua_Ctx,
  lua_Debug,
  lua_Hook,
  lua_Integer,
  lua_KFunction,
  lua_Number,
  lua_Reader,
  lua_State,
  lua_Unsigned,
  lua_Writer
};

// C API functions
pub use self::lua::{
  lua_absindex,
  lua_arith,
  lua_atpanic,
  lua_call,
  lua_callk,
  lua_checkstack,
  lua_close,
  lua_compare,
  lua_concat,
  lua_copy,
  lua_createtable,
  lua_dump,
  lua_error,
  lua_gc,
  lua_getallocf,
  lua_getextraspace,
  lua_getfield,
  lua_getglobal,
  lua_gethook,
  lua_gethookcount,
  lua_gethookmask,
  lua_getinfo,
  lua_getlocal,
  lua_getmetatable,
  lua_getstack,
  lua_gettable,
  lua_gettop,
  lua_getupvalue,
  lua_getuservalue,
  lua_insert,
  lua_isboolean,
  lua_iscfunction,
  lua_isfunction,
  lua_isinteger,
  lua_islightuserdata,
  lua_isnil,
  lua_isnone,
  lua_isnoneornil,
  lua_isnumber,
  lua_isstring,
  lua_istable,
  lua_isthread,
  lua_isuserdata,
  lua_isyieldable,
  lua_len,
  lua_load,
  lua_newstate,
  lua_newtable,
  lua_newthread,
  lua_newuserdata,
  lua_next,
  lua_pcall,
  lua_pcallk,
  lua_pop,
  lua_pushboolean,
  lua_pushcclosure,
  lua_pushcfunction,
  lua_pushfstring,
  lua_pushglobaltable,
  lua_pushinteger,
  lua_pushlightuserdata,
  lua_pushliteral,
  lua_pushlstring,
  lua_pushnil,
  lua_pushnumber,
  lua_pushstring,
  lua_pushthread,
  lua_pushvalue,
  // omitted: lua_pushvfstring
  lua_rawequal,
  lua_rawget,
  lua_rawgeti,
  lua_rawgetp,
  lua_rawlen,
  lua_rawset,
  lua_rawseti,
  lua_rawsetp,
  lua_register,
  lua_remove,
  lua_replace,
  lua_resume,
  lua_rotate,
  lua_setallocf,
  lua_setfield,
  lua_setglobal,
  lua_sethook,
  lua_setlocal,
  lua_setmetatable,
  lua_settable,
  lua_settop,
  lua_setupvalue,
  lua_setuservalue,
  lua_status,
  lua_strtonum,
  lua_toboolean,
  lua_tocfunction,
  lua_tointeger,
  lua_tointegerx,
  lua_tolstring,
  lua_tonumber,
  lua_tonumberx,
  lua_topointer,
  lua_tostring,
  lua_tothread,
  lua_touserdata,
  lua_type,
  lua_typename,
  lua_upvalueid,
  lua_upvalueindex,
  lua_upvaluejoin,
  lua_version,
  lua_xmove,
  lua_yield,
  lua_yieldk
};

// auxiliary library types
pub use self::lauxlib::{
  luaL_Buffer,
  luaL_Reg,
  luaL_Stream
};

// auxiliary library functions
pub use self::lauxlib::{
  luaL_addchar,
  luaL_addlstring,
  luaL_addsize,
  luaL_addstring,
  luaL_addvalue,
  luaL_argcheck,
  luaL_argerror,
  luaL_buffinit,
  luaL_buffinitsize,
  luaL_callmeta,
  luaL_checkany,
  luaL_checkint,
  luaL_checkinteger,
  luaL_checklong,
  luaL_checklstring,
  luaL_checknumber,
  luaL_checkoption,
  luaL_checkstack,
  luaL_checkstring,
  luaL_checktype,
  luaL_checkudata,
  luaL_checkversion,
  luaL_dofile,
  luaL_dostring,
  luaL_error,
  luaL_execresult,
  luaL_fileresult,
  luaL_getmetafield,
  luaL_getmetatable,
  luaL_getsubtable,
  luaL_gsub,
  luaL_len,
  luaL_loadbuffer,
  luaL_loadbufferx,
  luaL_loadfile,
  luaL_loadfilex,
  luaL_loadstring,
  luaL_newlib,
  luaL_newlibtable,
  luaL_newmetatable,
  luaL_newstate,
  luaL_optint,
  luaL_optinteger,
  luaL_optlong,
  luaL_optlstring,
  luaL_optnumber,
  luaL_optstring,
  luaL_prepbuffer,
  luaL_prepbuffsize,
  luaL_pushresult,
  luaL_pushresultsize,
  luaL_ref,
  luaL_requiref,
  luaL_setfuncs,
  luaL_setmetatable,
  luaL_testudata,
  luaL_tolstring,
  luaL_traceback,
  luaL_typename,
  luaL_unref,
  luaL_where
};

// lualib.h functions
pub use self::lualib::{
  luaopen_base,
  luaopen_coroutine,
  luaopen_table,
  luaopen_io,
  luaopen_os,
  luaopen_string,
  luaopen_utf8,
  luaopen_bit32,
  luaopen_math,
  luaopen_debug,
  luaopen_package,

  luaL_openlibs
};

// constants from lua.h
pub use self::lua::{
  LUA_MULTRET,
  LUA_REGISTRYINDEX,

  LUA_RIDX_MAINTHREAD, LUA_RIDX_GLOBALS,

  LUA_OPADD, LUA_OPSUB, LUA_OPMUL, LUA_OPDIV, LUA_OPIDIV,
  LUA_OPMOD, LUA_OPPOW, LUA_OPUNM,
  LUA_OPBNOT, LUA_OPBAND, LUA_OPBOR, LUA_OPBXOR, LUA_OPSHL, LUA_OPSHR,
  LUA_OPEQ, LUA_OPLT, LUA_OPLE,

  LUA_OK, LUA_YIELD, LUA_ERRRUN, LUA_ERRSYNTAX, LUA_ERRMEM, LUA_ERRGCMM, LUA_ERRERR,

  LUA_TNONE, LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE,
  LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, LUA_TLIGHTUSERDATA,

  LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_HOOKLINE, LUA_HOOKCOUNT,

  LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCCOUNTB,
  LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCISRUNNING
};

// constants from lauxlib.h
pub use self::lauxlib::{
  LUA_REFNIL, LUA_NOREF,
  LUA_ERRFILE,
  LUA_FILEHANDLE
};

// constants from lualib.h
pub use self::lualib::{
  LUA_COLIBNAME, LUA_TABLIBNAME, LUA_IOLIBNAME, LUA_OSLIBNAME, LUA_STRLIBNAME,
  LUA_UTF8LIBNAME, LUA_BITLIBNAME, LUA_MATHLIBNAME, LUA_DBLIBNAME, LUA_LOADLIBNAME
};

mod glue;
pub mod luaconf;
pub mod lua;
pub mod lauxlib;
pub mod lualib;

<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

#![crate_name = "gfx"]
#![comment = "A lightweight graphics device manager for Rust"]
#![license = "ASL2"]
#![crate_type = "lib"]

#![feature(phase)]

//! An efficient, low-level, bindless graphics API for Rust. See [the
//! blog](http://gfx-rs.github.io/) for explanations and annotated examples.

#[phase(plugin, link)] extern crate log;
extern crate libc;

extern crate device;
extern crate render;

// public re-exports
pub use render::{DeviceHelper, Renderer};
pub use render::batch;
pub use render::mesh::{Attribute, Mesh, VertexFormat};
pub use render::mesh::{Slice, ToSlice};
pub use render::mesh::{VertexSlice, IndexSlice8, IndexSlice16, IndexSlice32};
pub use render::state::{DrawState, BlendAdditive, BlendAlpha};
pub use render::shade;
pub use render::target::{Frame, Plane, PlaneEmpty, PlaneSurface, PlaneTexture};
pub use device::Device;
pub use device::{attrib, state, tex};
pub use device::{BufferHandle, BufferInfo, RawBufferHandle, ShaderHandle};
pub use device::{ProgramHandle, SurfaceHandle, TextureHandle};
pub use device::{BufferUsage, UsageStatic, UsageDynamic, UsageStream};
pub use device::{VertexCount, IndexCount, InstanceCount};
pub use device::{Point, Line, LineStrip, TriangleList, TriangleStrip, TriangleFan};
pub use device::blob::Blob;
pub use device::shade::UniformValue;
pub use device::shade::{ValueI32, ValueF32};
pub use device::shade::{ValueI32Vector2, ValueI32Vector3, ValueI32Vector4};
pub use device::shade::{ValueF32Vector2, ValueF32Vector3, ValueF32Vector4};
pub use device::shade::{ValueF32Matrix2, ValueF32Matrix3, ValueF32Matrix4};
pub use device::shade::{ShaderSource, StaticBytes, OwnedBytes, ProgramInfo};
pub use device::target::{Color, ClearData, Layer, Level};

// TODO: Remove this re-export once `gl_device` becomes a separate crate.
pub use device::gl_device::{GlDevice, GlCommandBuffer};

use render::batch::Context as BatchContext;
use render::batch::RefBatch;

/// A convenient wrapper suitable for single-threaded operation.
pub struct Graphics<D, C: device::draw::CommandBuffer> {
    /// Graphics device.
    pub device: D,
    /// Renderer front-end.
    pub renderer: Renderer<C>,
    /// Hidden batch context.
    context: BatchContext,
}

impl<D: device::Device<C>, C: device::draw::CommandBuffer> Graphics<D, C> {
    /// Create a new graphics wrapper.
    pub fn new(mut device: D) -> Graphics<D, C> {
        let rend = device.create_renderer();
        Graphics {
            device: device,
            renderer: rend,
            context: BatchContext::new(),
        }
    }

    /// Create a new ref batch.
    pub fn make_batch<L, T: shade::ShaderParam<L>>(&mut self,
                      program: &ProgramHandle,
                      mesh: &Mesh,
                      slice: Slice,
                      state: &DrawState)
                      -> Result<RefBatch<L, T>, batch::BatchError> {
        self.context.batch(mesh, slice, program, state)
    }

    /// Clear the `Frame` as the `ClearData` specifies.
    pub fn clear(&mut self, data: ClearData, frame: &Frame) {
        self.renderer.clear(data, frame)
    }

    /// Draw a ref batch.
    pub fn draw<'a, L, T: shade::ShaderParam<L>>(&'a mut self,
        batch: &'a RefBatch<L, T>, data: &'a T, frame: &Frame) {
        self.renderer.draw((batch, data, &self.context), frame)
    }

    /// Submit the internal command buffer and reset for the next frame.
    pub fn end_frame(&mut self) {
        self.device.submit(self.renderer.as_buffer());
        self.renderer.reset();
    }
}
<commit_msg>Added CommandBuffer export<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

#![crate_name = "gfx"]
#![comment = "A lightweight graphics device manager for Rust"]
#![license = "ASL2"]
#![crate_type = "lib"]

#![feature(phase)]

//! An efficient, low-level, bindless graphics API for Rust. See [the
//! blog](http://gfx-rs.github.io/) for explanations and annotated examples.

#[phase(plugin, link)] extern crate log;
extern crate libc;

extern crate device;
extern crate render;

// public re-exports
pub use render::{DeviceHelper, Renderer};
pub use render::batch;
pub use render::mesh::{Attribute, Mesh, VertexFormat};
pub use render::mesh::{Slice, ToSlice};
pub use render::mesh::{VertexSlice, IndexSlice8, IndexSlice16, IndexSlice32};
pub use render::state::{DrawState, BlendAdditive, BlendAlpha};
pub use render::shade;
pub use render::target::{Frame, Plane, PlaneEmpty, PlaneSurface, PlaneTexture};
pub use device::Device;
pub use device::{attrib, state, tex};
pub use device::{BufferHandle, BufferInfo, RawBufferHandle, ShaderHandle};
pub use device::{ProgramHandle, SurfaceHandle, TextureHandle};
pub use device::{BufferUsage, UsageStatic, UsageDynamic, UsageStream};
pub use device::{VertexCount, IndexCount, InstanceCount};
pub use device::{Point, Line, LineStrip, TriangleList, TriangleStrip, TriangleFan};
pub use device::blob::Blob;
pub use device::draw::CommandBuffer;
pub use device::shade::UniformValue;
pub use device::shade::{ValueI32, ValueF32};
pub use device::shade::{ValueI32Vector2, ValueI32Vector3, ValueI32Vector4};
pub use device::shade::{ValueF32Vector2, ValueF32Vector3, ValueF32Vector4};
pub use device::shade::{ValueF32Matrix2, ValueF32Matrix3, ValueF32Matrix4};
pub use device::shade::{ShaderSource, StaticBytes, OwnedBytes, ProgramInfo};
pub use device::target::{Color, ClearData, Layer, Level};

// TODO: Remove this re-export once `gl_device` becomes a separate crate.
pub use device::gl_device::{GlDevice, GlCommandBuffer};

use render::batch::Context as BatchContext;
use render::batch::RefBatch;

/// A convenient wrapper suitable for single-threaded operation.
pub struct Graphics<D, C: device::draw::CommandBuffer> {
    /// Graphics device.
    pub device: D,
    /// Renderer front-end.
    pub renderer: Renderer<C>,
    /// Hidden batch context.
    context: BatchContext,
}

impl<D: device::Device<C>, C: device::draw::CommandBuffer> Graphics<D, C> {
    /// Create a new graphics wrapper.
    pub fn new(mut device: D) -> Graphics<D, C> {
        let rend = device.create_renderer();
        Graphics {
            device: device,
            renderer: rend,
            context: BatchContext::new(),
        }
    }

    /// Create a new ref batch.
    pub fn make_batch<L, T: shade::ShaderParam<L>>(&mut self,
                      program: &ProgramHandle,
                      mesh: &Mesh,
                      slice: Slice,
                      state: &DrawState)
                      -> Result<RefBatch<L, T>, batch::BatchError> {
        self.context.batch(mesh, slice, program, state)
    }

    /// Clear the `Frame` as the `ClearData` specifies.
    pub fn clear(&mut self, data: ClearData, frame: &Frame) {
        self.renderer.clear(data, frame)
    }

    /// Draw a ref batch.
    pub fn draw<'a, L, T: shade::ShaderParam<L>>(&'a mut self,
        batch: &'a RefBatch<L, T>, data: &'a T, frame: &Frame) {
        self.renderer.draw((batch, data, &self.context), frame)
    }

    /// Submit the internal command buffer and reset for the next frame.
    pub fn end_frame(&mut self) {
        self.device.submit(self.renderer.as_buffer());
        self.renderer.reset();
    }
}
<|endoftext|>


<commit_before>use directives::DirectiveDef;
use registry::Registry;
use context::Context;
use render::{RenderError, RenderContext, Directive};

#[derive(Clone, Copy)]
pub struct InlineDirective;

impl DirectiveDef for InlineDirective {
    fn call(&self,
            _: &Context,
            d: &Directive,
            _: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let name = try!(d.param(0)
                         .ok_or_else(|| RenderError::new("Param required for directive \"inline\""))
                         .and_then(|v| {
                             v.value()
                              .as_string()
                              .ok_or_else(|| RenderError::new("inline name must be string"))
                         }));

        let template = try!(d.template()
                             .ok_or_else(|| RenderError::new("inline should have a block")));

        rc.set_partial(name.to_owned(), template.clone());
        Ok(())
    }
}

pub static INLINE_DIRECTIVE: InlineDirective = InlineDirective;

#[cfg(test)]
mod test {
    use template::Template;
    use registry::Registry;
    use context::Context;
    use render::{RenderContext, Evalable};
    use support::str::StringWriter;

    #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
    use serialize::json::Json;
    #[cfg(feature = "serde_type")]
    use serde::json::Value as Json;

    #[test]
    fn test_inline() {
        let t0 =
            Template::compile("{{#*inline \"hello\"}}the hello world inline partial.{{/inline}}"
                                  .to_string())
                .ok()
                .unwrap();

        let hbs = Registry::new();

        let mut sw = StringWriter::new();
        let mut rc = RenderContext::new(&mut sw);
        t0.elements[0].eval(&Context::wraps(&Json::Null), &hbs, &mut rc).unwrap();

        assert!(rc.get_partial(&"hello".to_owned()).is_some());
    }
}
<commit_msg>(fix) test for serde<commit_after>use directives::DirectiveDef;
use registry::Registry;
use context::Context;
use render::{RenderError, RenderContext, Directive};

#[derive(Clone, Copy)]
pub struct InlineDirective;

#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
fn get_name<'a>(d: &'a Directive) -> Result<&'a str, RenderError> {
    d.param(0)
     .ok_or_else(|| RenderError::new("Param required for directive \"inline\""))
     .and_then(|v| {
         v.value()
          .as_string()
          .ok_or_else(|| RenderError::new("inline name must be string"))
     })
}

#[cfg(feature = "serde_type")]
fn get_name<'a>(d: &'a Directive) -> Result<&'a str, RenderError> {
    d.param(0)
     .ok_or_else(|| RenderError::new("Param required for directive \"inline\""))
     .and_then(|v| {
         v.value()
          .as_str()
          .ok_or_else(|| RenderError::new("inline name must be string"))
     })
}

impl DirectiveDef for InlineDirective {
    fn call(&self,
            _: &Context,
            d: &Directive,
            _: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let name = try!(get_name(d));

        let template = try!(d.template()
                             .ok_or_else(|| RenderError::new("inline should have a block")));

        rc.set_partial(name.to_owned(), template.clone());
        Ok(())
    }
}

pub static INLINE_DIRECTIVE: InlineDirective = InlineDirective;

#[cfg(test)]
mod test {
    use template::Template;
    use registry::Registry;
    use context::Context;
    use render::{RenderContext, Evalable};
    use support::str::StringWriter;

    #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
    use serialize::json::Json;
    #[cfg(feature = "serde_type")]
    use serde_json::value::Value as Json;

    #[test]
    fn test_inline() {
        let t0 =
            Template::compile("{{#*inline \"hello\"}}the hello world inline partial.{{/inline}}"
                                  .to_string())
                .ok()
                .unwrap();

        let hbs = Registry::new();

        let mut sw = StringWriter::new();
        let mut rc = RenderContext::new(&mut sw);
        t0.elements[0].eval(&Context::wraps(&Json::Null), &hbs, &mut rc).unwrap();

        assert!(rc.get_partial(&"hello".to_owned()).is_some());
    }
}
<|endoftext|>


<commit_before>use error::Result;
use postgres::Connection;
use std::collections::BTreeMap;
use std::time::Duration;

#[derive(Debug, PartialEq)]
pub(crate) struct Limits {
    memory: usize,
    targets: usize,
    timeout: Duration,
    networking: bool,
    max_log_size: usize,
}

impl Default for Limits {
    fn default() -> Self {
        Self {
            memory: 3 * 1024 * 1024 * 1024,  // 3 GB
            timeout: Duration::from_secs(15 * 60),  // 15 minutes
            targets: 10,
            networking: false,
            max_log_size: 100 * 1024, // 100 KB
        }
    }
}

impl Limits {
    pub(crate) fn for_crate(conn: &Connection, name: &str) -> Result<Self> {
        let mut limits = Self::default();

        let res = conn.query(
            "SELECT * FROM sandbox_overrides WHERE crate_name = $1;",
            &[&name],
        )?;
        if !res.is_empty() {
            let row = res.get(0);
            if let Some(memory) = row.get::<_, Option<i64>>("max_memory_bytes") {
                limits.memory = memory as usize;
            }
            if let Some(timeout) = row.get::<_, Option<i32>>("timeout_seconds") {
                limits.timeout = Duration::from_secs(timeout as u64);
            }
            if let Some(targets) = row.get::<_, Option<i32>>("max_targets") {
                limits.targets = targets as usize;
            }
        }

        Ok(limits)
    }

    pub(crate) fn memory(&self) -> usize {
        self.memory
    }

    pub(crate) fn timeout(&self) -> Duration {
        self.timeout
    }

    pub(crate) fn networking(&self) -> bool {
        self.networking
    }

    pub(crate) fn max_log_size(&self) -> usize {
        self.max_log_size
    }

    pub(crate) fn targets(&self) -> usize {
        self.targets
    }

    pub(crate) fn for_website(&self) -> BTreeMap<String, String> {

        let mut res = BTreeMap::new();
        res.insert("Available RAM".into(), SIZE_SCALE(self.memory));
        res.insert(
            "Maximum rustdoc execution time".into(),
            TIME_SCALE(self.timeout.as_secs() as usize),
        );
        res.insert("Maximum size of a build log".into(), SIZE_SCALE(self.max_log_size));
        if self.networking {
            res.insert("Network access".into(), "allowed".into());
        } else {
            res.insert("Network access".into(), "blocked".into());
        }
        res.insert("Maximum number of build targets".into(), self.targets.to_string());
        res
    }
}

const TIME_SCALE: fn(usize) -> String = |v| scale(v, 60, &["seconds", "minutes", "hours"]);
const SIZE_SCALE: fn(usize) -> String = |v| scale(v, 1024, &["bytes", "KB", "MB", "GB"]);

fn scale(value: usize, interval: usize, labels: &[&str]) -> String {
    let (mut value, interval) = (value as f64, interval as f64);
    let mut chosen_label = &labels[0];
    for label in &labels[1..] {
        if value / interval >= 1.0 {
            chosen_label = label;
            value = value / interval;
        } else {
            break;
        }
    }
    // 2.x
    let mut value = format!("{:.1}", value);
    // 2.0 -> 2
    if &value[value.len() - 1..] == "0" {
        value.truncate(value.len() - 2);
    }
    format!("{} {}", value, chosen_label)
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::test::*;
    #[test]
    fn retrieve_limits() {
        wrapper(|env| {
            let db = env.db();

            let krate = "hexponent";
            // limits work if no crate has limits set
            let hexponent = Limits::for_crate(&db.conn(), krate)?;
            assert_eq!(hexponent, Limits::default());

            db.conn().query("INSERT INTO sandbox_overrides (crate_name, max_targets) VALUES ($1, 15)", &[&krate])?;
            // limits work if crate has limits set
            let hexponent = Limits::for_crate(&db.conn(), krate)?;
            assert_eq!(hexponent, Limits { targets: 15, ..Limits::default() });

            // all limits work
            let krate = "regex";
            let limits = Limits {
                memory: 100_000,
                timeout: Duration::from_secs(300),
                targets: 1,
                ..Limits::default()
            };
            db.conn().query("INSERT INTO sandbox_overrides (crate_name, max_memory_bytes, timeout_seconds, max_targets)
                                    VALUES ($1, $2, $3, $4)",
                                    &[&krate, &(limits.memory as i64), &(limits.timeout.as_secs() as i32), &(limits.targets as i32)])?;
            assert_eq!(limits, Limits::for_crate(&db.conn(), krate)?);
            Ok(())
        });
    }
    #[test]
    fn display_limits() {
        let limits = Limits {
            memory: 102400,
            timeout: Duration::from_secs(300),
            targets: 1,
            ..Limits::default()
        };
        let display = limits.for_website();
        assert_eq!(display.get("Network access".into()), Some(&"blocked".into()));
        assert_eq!(display.get("Maximum size of a build log".into()), Some(&"100 KB".into()));
        assert_eq!(display.get("Maximum number of build targets".into()), Some(&limits.targets.to_string()));
        assert_eq!(display.get("Maximum rustdoc execution time".into()), Some(&"5 minutes".into()));
        assert_eq!(display.get("Available RAM".into()), Some(&"100 KB".into()));
    }
    #[test]
    fn scale_limits() {
        // time
        assert_eq!(TIME_SCALE(300), "5 minutes");
        assert_eq!(TIME_SCALE(1), "1 seconds");
        assert_eq!(TIME_SCALE(7200), "2 hours");

        // size
        assert_eq!(SIZE_SCALE(1), "1 bytes");
        assert_eq!(SIZE_SCALE(100), "100 bytes");
        assert_eq!(SIZE_SCALE(1024), "1 KB");
        assert_eq!(SIZE_SCALE(10240), "10 KB");
        assert_eq!(SIZE_SCALE(1048576), "1 MB");
        assert_eq!(SIZE_SCALE(10485760), "10 MB");
        assert_eq!(SIZE_SCALE(1073741824), "1 GB");
        assert_eq!(SIZE_SCALE(10737418240), "10 GB");
        assert_eq!(SIZE_SCALE(std::u32::MAX as usize), "4 GB");

        // fractional sizes
        assert_eq!(TIME_SCALE(90), "1.5 minutes");
        assert_eq!(TIME_SCALE(5400), "1.5 hours");

        assert_eq!(SIZE_SCALE(1288490189), "1.2 GB");
        assert_eq!(SIZE_SCALE(3758096384), "3.5 GB");
        assert_eq!(SIZE_SCALE(1048051712), "999.5 MB");
    }
}
<commit_msg>Use standard library instead of rewriting it<commit_after>use error::Result;
use postgres::Connection;
use std::collections::BTreeMap;
use std::time::Duration;

#[derive(Debug, PartialEq)]
pub(crate) struct Limits {
    memory: usize,
    targets: usize,
    timeout: Duration,
    networking: bool,
    max_log_size: usize,
}

impl Default for Limits {
    fn default() -> Self {
        Self {
            memory: 3 * 1024 * 1024 * 1024,  // 3 GB
            timeout: Duration::from_secs(15 * 60),  // 15 minutes
            targets: 10,
            networking: false,
            max_log_size: 100 * 1024, // 100 KB
        }
    }
}

impl Limits {
    pub(crate) fn for_crate(conn: &Connection, name: &str) -> Result<Self> {
        let mut limits = Self::default();

        let res = conn.query(
            "SELECT * FROM sandbox_overrides WHERE crate_name = $1;",
            &[&name],
        )?;
        if !res.is_empty() {
            let row = res.get(0);
            if let Some(memory) = row.get::<_, Option<i64>>("max_memory_bytes") {
                limits.memory = memory as usize;
            }
            if let Some(timeout) = row.get::<_, Option<i32>>("timeout_seconds") {
                limits.timeout = Duration::from_secs(timeout as u64);
            }
            if let Some(targets) = row.get::<_, Option<i32>>("max_targets") {
                limits.targets = targets as usize;
            }
        }

        Ok(limits)
    }

    pub(crate) fn memory(&self) -> usize {
        self.memory
    }

    pub(crate) fn timeout(&self) -> Duration {
        self.timeout
    }

    pub(crate) fn networking(&self) -> bool {
        self.networking
    }

    pub(crate) fn max_log_size(&self) -> usize {
        self.max_log_size
    }

    pub(crate) fn targets(&self) -> usize {
        self.targets
    }

    pub(crate) fn for_website(&self) -> BTreeMap<String, String> {

        let mut res = BTreeMap::new();
        res.insert("Available RAM".into(), SIZE_SCALE(self.memory));
        res.insert(
            "Maximum rustdoc execution time".into(),
            TIME_SCALE(self.timeout.as_secs() as usize),
        );
        res.insert("Maximum size of a build log".into(), SIZE_SCALE(self.max_log_size));
        if self.networking {
            res.insert("Network access".into(), "allowed".into());
        } else {
            res.insert("Network access".into(), "blocked".into());
        }
        res.insert("Maximum number of build targets".into(), self.targets.to_string());
        res
    }
}

const TIME_SCALE: fn(usize) -> String = |v| scale(v, 60, &["seconds", "minutes", "hours"]);
const SIZE_SCALE: fn(usize) -> String = |v| scale(v, 1024, &["bytes", "KB", "MB", "GB"]);

fn scale(value: usize, interval: usize, labels: &[&str]) -> String {
    let (mut value, interval) = (value as f64, interval as f64);
    let mut chosen_label = &labels[0];
    for label in &labels[1..] {
        if value / interval >= 1.0 {
            chosen_label = label;
            value = value / interval;
        } else {
            break;
        }
    }
    // 2.x
    let mut value = format!("{:.1}", value);
    // 2.0 -> 2
    if value.ends_with(".0") {
        value.truncate(value.len() - 2);
    }
    format!("{} {}", value, chosen_label)
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::test::*;
    #[test]
    fn retrieve_limits() {
        wrapper(|env| {
            let db = env.db();

            let krate = "hexponent";
            // limits work if no crate has limits set
            let hexponent = Limits::for_crate(&db.conn(), krate)?;
            assert_eq!(hexponent, Limits::default());

            db.conn().query("INSERT INTO sandbox_overrides (crate_name, max_targets) VALUES ($1, 15)", &[&krate])?;
            // limits work if crate has limits set
            let hexponent = Limits::for_crate(&db.conn(), krate)?;
            assert_eq!(hexponent, Limits { targets: 15, ..Limits::default() });

            // all limits work
            let krate = "regex";
            let limits = Limits {
                memory: 100_000,
                timeout: Duration::from_secs(300),
                targets: 1,
                ..Limits::default()
            };
            db.conn().query("INSERT INTO sandbox_overrides (crate_name, max_memory_bytes, timeout_seconds, max_targets)
                                    VALUES ($1, $2, $3, $4)",
                                    &[&krate, &(limits.memory as i64), &(limits.timeout.as_secs() as i32), &(limits.targets as i32)])?;
            assert_eq!(limits, Limits::for_crate(&db.conn(), krate)?);
            Ok(())
        });
    }
    #[test]
    fn display_limits() {
        let limits = Limits {
            memory: 102400,
            timeout: Duration::from_secs(300),
            targets: 1,
            ..Limits::default()
        };
        let display = limits.for_website();
        assert_eq!(display.get("Network access".into()), Some(&"blocked".into()));
        assert_eq!(display.get("Maximum size of a build log".into()), Some(&"100 KB".into()));
        assert_eq!(display.get("Maximum number of build targets".into()), Some(&limits.targets.to_string()));
        assert_eq!(display.get("Maximum rustdoc execution time".into()), Some(&"5 minutes".into()));
        assert_eq!(display.get("Available RAM".into()), Some(&"100 KB".into()));
    }
    #[test]
    fn scale_limits() {
        // time
        assert_eq!(TIME_SCALE(300), "5 minutes");
        assert_eq!(TIME_SCALE(1), "1 seconds");
        assert_eq!(TIME_SCALE(7200), "2 hours");

        // size
        assert_eq!(SIZE_SCALE(1), "1 bytes");
        assert_eq!(SIZE_SCALE(100), "100 bytes");
        assert_eq!(SIZE_SCALE(1024), "1 KB");
        assert_eq!(SIZE_SCALE(10240), "10 KB");
        assert_eq!(SIZE_SCALE(1048576), "1 MB");
        assert_eq!(SIZE_SCALE(10485760), "10 MB");
        assert_eq!(SIZE_SCALE(1073741824), "1 GB");
        assert_eq!(SIZE_SCALE(10737418240), "10 GB");
        assert_eq!(SIZE_SCALE(std::u32::MAX as usize), "4 GB");

        // fractional sizes
        assert_eq!(TIME_SCALE(90), "1.5 minutes");
        assert_eq!(TIME_SCALE(5400), "1.5 hours");

        assert_eq!(SIZE_SCALE(1288490189), "1.2 GB");
        assert_eq!(SIZE_SCALE(3758096384), "3.5 GB");
        assert_eq!(SIZE_SCALE(1048051712), "999.5 MB");
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
extern crate rand;

use capnp::{message, serialize, serialize_packed};
use capnp::traits::Owned;

pub mod common;

pub mod carsales_capnp {
  include!(concat!(env!("OUT_DIR"), "/carsales_capnp.rs"));
}
pub mod carsales;

pub mod catrank_capnp {
  include!(concat!(env!("OUT_DIR"), "/catrank_capnp.rs"));
}
pub mod catrank;

pub mod eval_capnp {
  include!(concat!(env!("OUT_DIR"), "/eval_capnp.rs"));
}

pub mod eval;

trait TestCase {
    type Request: for<'a> Owned<'a>;
    type Response: for<'a> Owned<'a>;
    type Expectation;

    fn setup_request(&self, &mut common::FastRand, <Self::Request as Owned>::Builder) -> Self::Expectation;
    fn handle_request(&self, <Self::Request as Owned>::Reader, <Self::Response as Owned>::Builder)
                      -> ::capnp::Result<()>;
    fn check_response(&self, <Self::Response as Owned>::Reader, Self::Expectation) -> ::capnp::Result<()>;
}

trait Serialize {
    fn read_message<R>(
        &self,
        read: &mut R,
        options: message::ReaderOptions)
                       -> ::capnp::Result<message::Reader<::capnp::serialize::OwnedSegments>>
        where R: ::std::io::BufRead;

    fn write_message<W, A>(&self, write: &mut W, message: &message::Builder<A>) -> ::capnp::Result<()>
        where W: ::std::io::Write, A: message::Allocator;
}

struct NoCompression;

impl Serialize for NoCompression {
    fn read_message<R>(&self, read: &mut R,
                       options: message::ReaderOptions)
                       -> ::capnp::Result<message::Reader<::capnp::serialize::OwnedSegments>>
        where R: ::std::io::BufRead
    {
        serialize::read_message(read, options)
    }

    fn write_message<W, A>(&self, write: &mut W, message: &message::Builder<A>) -> ::capnp::Result<()>
        where W: ::std::io::Write, A: message::Allocator {
        serialize::write_message(write, message).map_err(|e| e.into())
    }
}

struct Packed;

impl Serialize for Packed {
    fn read_message<R>(&self, read: &mut R,
                       options: message::ReaderOptions)
                       -> ::capnp::Result<message::Reader<::capnp::serialize::OwnedSegments>>
        where R: ::std::io::BufRead
    {
        serialize_packed::read_message(read, options)
    }

    fn write_message<W, A>(&self, write: &mut W, message: &message::Builder<A>) -> ::capnp::Result<()>
        where W: ::std::io::Write, A: message::Allocator {
        serialize_packed::write_message(write, message).map_err(|e| e.into())
    }
}

trait Scratch<'a> {
    type Allocator: message::Allocator;

    fn get_builders(&'a mut self) -> (message::Builder<Self::Allocator>, message::Builder<Self::Allocator>);
}

const SCRATCH_SIZE: usize = 128 * 1024;

#[derive(Clone, Copy)]
pub struct NoScratch;

impl <'a> Scratch<'a> for NoScratch {
    type Allocator = message::HeapAllocator;

    fn get_builders(&'a mut self) -> (message::Builder<Self::Allocator>, message::Builder<Self::Allocator>) {
        (capnp::message::Builder::new_default(), capnp::message::Builder::new_default())
    }
}

pub struct UseScratch {
    _owned_space: ::std::vec::Vec<::std::vec::Vec<capnp::Word>>,
    scratch_space: ::std::vec::Vec<::capnp::message::ScratchSpace<'static>>,
}

impl UseScratch {
    pub fn new() -> UseScratch {
        let mut owned = Vec::new();
        let mut scratch = Vec::new();
        for _ in 0..6 {
            let mut words = ::capnp::Word::allocate_zeroed_vec(SCRATCH_SIZE);
            scratch.push(::capnp::message::ScratchSpace::new(
                unsafe {::std::mem::transmute(&mut words[..])}));
            owned.push(words);
        }
        UseScratch {
            _owned_space: owned,
            scratch_space: scratch,
        }
    }
}

impl <'a> Scratch<'a> for UseScratch {
    type Allocator = capnp::message::ScratchSpaceHeapAllocator<'a, 'a>;

    fn get_builders(&'a mut self) -> (message::Builder<Self::Allocator>, message::Builder<Self::Allocator>) {
        (capnp::message::Builder::new(::capnp::message::ScratchSpaceHeapAllocator::new(
            unsafe{::std::mem::transmute(&mut self.scratch_space[0])})),
         capnp::message::Builder::new(::capnp::message::ScratchSpaceHeapAllocator::new(
             unsafe{::std::mem::transmute(&mut self.scratch_space[1])})))

    }
}

fn pass_by_object<S, T>(testcase: T, mut reuse: S, iters: u64) -> ::capnp::Result<()>
    where S: for<'a> Scratch<'a>, T: TestCase,
{
    let mut rng = common::FastRand::new();
    for _ in 0..iters {
        let (mut message_req, mut message_res) = reuse.get_builders();

        let expected = testcase.setup_request(
            &mut rng,
            message_req.init_root());

        try!(testcase.handle_request(
            try!(message_req.get_root_as_reader()),
            message_res.init_root()));

        try!(testcase.check_response(
            try!(message_res.get_root_as_reader()),
            expected));
    }
    Ok(())
}

fn pass_by_bytes<C, S, T>(testcase: T, mut reuse: S, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase,
{
    let mut request_bytes: ::std::vec::Vec<u8> =
        ::std::iter::repeat(0u8).take(SCRATCH_SIZE * 8).collect();
    let mut response_bytes: ::std::vec::Vec<u8> =
        ::std::iter::repeat(0u8).take(SCRATCH_SIZE * 8).collect();
    let mut rng = common::FastRand::new();
    for _ in 0..iters {
        let (mut message_req, mut message_res) = reuse.get_builders();

        let expected = {
            let request = message_req.init_root();
            testcase.setup_request(&mut rng, request)
        };

        {
            let response = message_res.init_root();

            {
                let mut writer: &mut [u8] = &mut request_bytes;
                compression.write_message(&mut writer, &mut message_req).unwrap()
            }

            let mut request_bytes1: &[u8] = &request_bytes;
            let message_reader = compression.read_message(
                &mut request_bytes1,
                capnp::message::DEFAULT_READER_OPTIONS).unwrap();

            let request_reader = message_reader.get_root().unwrap();
            try!(testcase.handle_request(request_reader, response));
        }

        {
            let mut writer: &mut [u8] = &mut response_bytes;
            compression.write_message(&mut writer, &mut message_res).unwrap()
        }

        let mut response_bytes1: &[u8] = &response_bytes;
        let message_reader = compression.read_message(
            &mut response_bytes1,
            capnp::message::DEFAULT_READER_OPTIONS).unwrap();

        let response_reader = message_reader.get_root().unwrap();
        try!(testcase.check_response(response_reader, expected));
    }
    Ok(())
}

fn server<C, S, T, R, W>(testcase: T, mut reuse: S, compression: C, iters: u64, mut input: R, mut output: W)
                         -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase, R: ::std::io::Read, W: ::std::io::Write,
{
    let mut out_buffered = ::std::io::BufWriter::new(&mut output);
    let mut in_buffered = ::std::io::BufReader::new(&mut input);
    for _ in 0..iters {
        use std::io::Write;
        let (mut message_res, _) = reuse.get_builders();

        {
            let response = message_res.init_root();
            let message_reader = try!(compression.read_message(
                &mut in_buffered,
                capnp::message::DEFAULT_READER_OPTIONS));
            let request_reader = try!(message_reader.get_root());
            try!(testcase.handle_request(request_reader, response));
        }

        try!(compression.write_message(&mut out_buffered, &mut message_res));
        try!(out_buffered.flush());
    }
    Ok(())
}

fn sync_client<C, S, T>(testcase: T, mut reuse: S, compression: C, iters: u64)
                        -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase,
{
    let mut out_stream: ::std::fs::File = unsafe { ::std::os::unix::io::FromRawFd::from_raw_fd(1) };
    let mut in_stream: ::std::fs::File = unsafe { ::std::os::unix::io::FromRawFd::from_raw_fd(0) };
    let mut in_buffered = ::std::io::BufReader::new(&mut in_stream);
    let mut out_buffered = ::std::io::BufWriter::new(&mut out_stream);
    let mut rng = common::FastRand::new();
    for _ in 0..iters {
        use std::io::Write;
        let (mut message_req, _) = reuse.get_builders();

        let expected = {
            let request = message_req.init_root();
            testcase.setup_request(&mut rng, request)
        };
        try!(compression.write_message(&mut out_buffered, &mut message_req));
        try!(out_buffered.flush());

        let message_reader = compression.read_message(
            &mut in_buffered,
            capnp::message::DEFAULT_READER_OPTIONS).unwrap();
        let response_reader = try!(message_reader.get_root());
        try!(testcase.check_response(response_reader, expected));
    }
    Ok(())
}

fn pass_by_pipe<C, S, T>(testcase: T, reuse: S, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase,
{
    use std::process;

    let mut args: Vec<String> = ::std::env::args().collect();
    args[2] = "client".to_string();

    let mut command = process::Command::new(&args[0]);
    command.args(&args[1..args.len()]);
    command.stdin(process::Stdio::piped());
    command.stdout(process::Stdio::piped());
    command.stderr(process::Stdio::null());
    match command.spawn() {
        Ok(ref mut p) => {
            let child_std_out = p.stdout.take().unwrap();
            let child_std_in = p.stdin.take().unwrap();
            try!(server(testcase, reuse, compression, iters, child_std_out, child_std_in));
            println!("{}", p.wait().unwrap());
            Ok(())
        }
        Err(e) => {
            println!("could not start process: {}", e);
            Ok(())
        }
    }
}

fn do_testcase<C, S, T>(testcase: T, mode: &str, reuse: S, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase,
{
    match mode {
        "object" => pass_by_object(testcase, reuse, iters),
        "bytes" => pass_by_bytes(testcase, reuse, compression, iters),
        "client" => sync_client(testcase, reuse, compression, iters),
        "server" => {
            let input: ::std::fs::File = unsafe { ::std::os::unix::io::FromRawFd::from_raw_fd(1) };
            let output: ::std::fs::File = unsafe { ::std::os::unix::io::FromRawFd::from_raw_fd(0) };
            server(testcase, reuse, compression, iters, input, output)
        }
        "pipe" => pass_by_pipe(testcase, reuse, compression, iters),
        s => panic!("unrecognized mode: {}", s)
    }
}

fn do_testcase1<C, S>(case: &str, mode: &str, scratch: S, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>,
{
    match case {
        "carsales" => do_testcase(carsales::CarSales, mode, scratch, compression, iters),
        "catrank" => do_testcase(catrank::CatRank, mode, scratch, compression, iters),
        "eval" => do_testcase(eval::Eval, mode, scratch, compression, iters),
        s => panic!("unrecognized test case: {}", s)
    }
}

fn do_testcase2<C>(case: &str, mode: &str, scratch: &str, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize,
{
    match scratch {
        "no-reuse" => do_testcase1(case, mode, NoScratch, compression, iters),
        "reuse" => do_testcase1(case, mode, UseScratch::new(), compression, iters),
        s => panic!("unrecognized reuse option: {}", s),
    }
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();

    assert!(args.len() == 6,
            "USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT",
            args[0]);

    let iters = match args[5].parse::<u64>() {
        Ok(n) => n,
        Err(_) => {
            panic!("Could not parse a u64 from: {}", args[5]);
        }
    };

    let result = match &*args[4] {
        "none" => do_testcase2(&*args[1], &*args[2], &*args[3], NoCompression, iters),
        "packed" => do_testcase2(&*args[1], &*args[2], &*args[3], Packed, iters),
        s => panic!("unrecognized compression: {}", s)
    };

    match result {
        Ok(()) => (),
        Err(e) => {
            panic!("error: {:?}", e);
        }
    }
}
<commit_msg>add benchmark::Mode enum<commit_after>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
extern crate rand;

use std::{mem, io};

use capnp::{message, serialize, serialize_packed};
use capnp::traits::Owned;

pub mod common;

pub mod carsales_capnp {
  include!(concat!(env!("OUT_DIR"), "/carsales_capnp.rs"));
}
pub mod carsales;

pub mod catrank_capnp {
  include!(concat!(env!("OUT_DIR"), "/catrank_capnp.rs"));
}
pub mod catrank;

pub mod eval_capnp {
  include!(concat!(env!("OUT_DIR"), "/eval_capnp.rs"));
}

pub mod eval;

trait TestCase {
    type Request: for<'a> Owned<'a>;
    type Response: for<'a> Owned<'a>;
    type Expectation;

    fn setup_request(&self, &mut common::FastRand, <Self::Request as Owned>::Builder) -> Self::Expectation;
    fn handle_request(&self, <Self::Request as Owned>::Reader, <Self::Response as Owned>::Builder)
                      -> ::capnp::Result<()>;
    fn check_response(&self, <Self::Response as Owned>::Reader, Self::Expectation) -> ::capnp::Result<()>;
}

trait Serialize {
    fn read_message<R>(
        &self,
        read: &mut R,
        options: message::ReaderOptions)
                       -> ::capnp::Result<message::Reader<::capnp::serialize::OwnedSegments>>
        where R: io::BufRead;

    fn write_message<W, A>(&self, write: &mut W, message: &message::Builder<A>) -> ::capnp::Result<()>
        where W: io::Write, A: message::Allocator;
}

struct NoCompression;

impl Serialize for NoCompression {
    fn read_message<R>(&self, read: &mut R,
                       options: message::ReaderOptions)
                       -> ::capnp::Result<message::Reader<::capnp::serialize::OwnedSegments>>
        where R: io::BufRead
    {
        serialize::read_message(read, options)
    }

    fn write_message<W, A>(&self, write: &mut W, message: &message::Builder<A>) -> ::capnp::Result<()>
        where W: io::Write, A: message::Allocator {
        serialize::write_message(write, message).map_err(|e| e.into())
    }
}

struct Packed;

impl Serialize for Packed {
    fn read_message<R>(&self, read: &mut R,
                       options: message::ReaderOptions)
                       -> ::capnp::Result<message::Reader<::capnp::serialize::OwnedSegments>>
        where R: io::BufRead
    {
        serialize_packed::read_message(read, options)
    }

    fn write_message<W, A>(&self, write: &mut W, message: &message::Builder<A>) -> ::capnp::Result<()>
        where W: io::Write, A: message::Allocator {
        serialize_packed::write_message(write, message).map_err(|e| e.into())
    }
}

trait Scratch<'a> {
    type Allocator: message::Allocator;

    fn get_builders(&'a mut self) -> (message::Builder<Self::Allocator>, message::Builder<Self::Allocator>);
}

const SCRATCH_SIZE: usize = 128 * 1024;

#[derive(Clone, Copy)]
pub struct NoScratch;

impl <'a> Scratch<'a> for NoScratch {
    type Allocator = message::HeapAllocator;

    fn get_builders(&'a mut self) -> (message::Builder<Self::Allocator>, message::Builder<Self::Allocator>) {
        (message::Builder::new_default(), message::Builder::new_default())
    }
}

pub struct UseScratch {
    _owned_space: ::std::vec::Vec<::std::vec::Vec<capnp::Word>>,
    scratch_space: ::std::vec::Vec<message::ScratchSpace<'static>>,
}

impl UseScratch {
    pub fn new() -> UseScratch {
        let mut owned = Vec::new();
        let mut scratch = Vec::new();
        for _ in 0..6 {
            let mut words = ::capnp::Word::allocate_zeroed_vec(SCRATCH_SIZE);
            scratch.push(message::ScratchSpace::new(
                unsafe { mem::transmute(&mut words[..]) }));
            owned.push(words);
        }
        UseScratch {
            _owned_space: owned,
            scratch_space: scratch,
        }
    }
}

impl <'a> Scratch<'a> for UseScratch {
    type Allocator = message::ScratchSpaceHeapAllocator<'a, 'a>;

    fn get_builders(&'a mut self) -> (message::Builder<Self::Allocator>, message::Builder<Self::Allocator>) {
        (message::Builder::new(message::ScratchSpaceHeapAllocator::new(
            unsafe { mem::transmute(&mut self.scratch_space[0]) })),
         message::Builder::new(message::ScratchSpaceHeapAllocator::new(
             unsafe { mem::transmute(&mut self.scratch_space[1]) })))

    }
}

fn pass_by_object<S, T>(testcase: T, mut reuse: S, iters: u64) -> ::capnp::Result<()>
    where S: for<'a> Scratch<'a>, T: TestCase,
{
    let mut rng = common::FastRand::new();
    for _ in 0..iters {
        let (mut message_req, mut message_res) = reuse.get_builders();

        let expected = testcase.setup_request(
            &mut rng,
            message_req.init_root());

        try!(testcase.handle_request(
            try!(message_req.get_root_as_reader()),
            message_res.init_root()));

        try!(testcase.check_response(
            try!(message_res.get_root_as_reader()),
            expected));
    }
    Ok(())
}

fn pass_by_bytes<C, S, T>(testcase: T, mut reuse: S, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase,
{
    let mut request_bytes: ::std::vec::Vec<u8> =
        ::std::iter::repeat(0u8).take(SCRATCH_SIZE * 8).collect();
    let mut response_bytes: ::std::vec::Vec<u8> =
        ::std::iter::repeat(0u8).take(SCRATCH_SIZE * 8).collect();
    let mut rng = common::FastRand::new();
    for _ in 0..iters {
        let (mut message_req, mut message_res) = reuse.get_builders();

        let expected = {
            let request = message_req.init_root();
            testcase.setup_request(&mut rng, request)
        };

        {
            let response = message_res.init_root();

            {
                let mut writer: &mut [u8] = &mut request_bytes;
                compression.write_message(&mut writer, &mut message_req).unwrap()
            }

            let mut request_bytes1: &[u8] = &request_bytes;
            let message_reader = compression.read_message(
                &mut request_bytes1,
                Default::default()).unwrap();

            let request_reader = message_reader.get_root().unwrap();
            try!(testcase.handle_request(request_reader, response));
        }

        {
            let mut writer: &mut [u8] = &mut response_bytes;
            compression.write_message(&mut writer, &mut message_res).unwrap()
        }

        let mut response_bytes1: &[u8] = &response_bytes;
        let message_reader = compression.read_message(
            &mut response_bytes1,
            Default::default()).unwrap();

        let response_reader = message_reader.get_root().unwrap();
        try!(testcase.check_response(response_reader, expected));
    }
    Ok(())
}

fn server<C, S, T, R, W>(testcase: T, mut reuse: S, compression: C, iters: u64, mut input: R, mut output: W)
                         -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase, R: io::Read, W: io::Write,
{
    let mut out_buffered = io::BufWriter::new(&mut output);
    let mut in_buffered = io::BufReader::new(&mut input);
    for _ in 0..iters {
        use std::io::Write;
        let (mut message_res, _) = reuse.get_builders();

        {
            let response = message_res.init_root();
            let message_reader = try!(compression.read_message(
                &mut in_buffered,
                capnp::message::DEFAULT_READER_OPTIONS));
            let request_reader = try!(message_reader.get_root());
            try!(testcase.handle_request(request_reader, response));
        }

        try!(compression.write_message(&mut out_buffered, &mut message_res));
        try!(out_buffered.flush());
    }
    Ok(())
}

fn sync_client<C, S, T>(testcase: T, mut reuse: S, compression: C, iters: u64)
                        -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase,
{
    let mut out_stream: ::std::fs::File = unsafe { ::std::os::unix::io::FromRawFd::from_raw_fd(1) };
    let mut in_stream: ::std::fs::File = unsafe { ::std::os::unix::io::FromRawFd::from_raw_fd(0) };
    let mut in_buffered = io::BufReader::new(&mut in_stream);
    let mut out_buffered = io::BufWriter::new(&mut out_stream);
    let mut rng = common::FastRand::new();
    for _ in 0..iters {
        use std::io::Write;
        let (mut message_req, _) = reuse.get_builders();

        let expected = {
            let request = message_req.init_root();
            testcase.setup_request(&mut rng, request)
        };
        try!(compression.write_message(&mut out_buffered, &mut message_req));
        try!(out_buffered.flush());

        let message_reader = compression.read_message(
            &mut in_buffered,
            Default::default()).unwrap();
        let response_reader = try!(message_reader.get_root());
        try!(testcase.check_response(response_reader, expected));
    }
    Ok(())
}

fn pass_by_pipe<C, S, T>(testcase: T, reuse: S, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase,
{
    use std::{process, env};

    let mut args: Vec<String> = env::args().collect();
    args[2] = "client".to_string();

    let mut command = process::Command::new(&args[0]);
    command.args(&args[1..args.len()]);
    command.stdin(process::Stdio::piped());
    command.stdout(process::Stdio::piped());
    command.stderr(process::Stdio::null());
    match command.spawn() {
        Ok(ref mut p) => {
            let child_std_out = p.stdout.take().unwrap();
            let child_std_in = p.stdin.take().unwrap();
            try!(server(testcase, reuse, compression, iters, child_std_out, child_std_in));
            println!("{}", p.wait().unwrap());
            Ok(())
        }
        Err(e) => {
            println!("could not start process: {}", e);
            Ok(())
        }
    }
}

pub enum Mode {
    Object,
    Bytes,
    Client,
    Server,
    Pipe,
}

impl Mode {
    pub fn parse(s: &str) -> ::capnp::Result<Mode> {
        match s {
            "object" => Ok(Mode::Object),
            "bytes" => Ok(Mode::Bytes),
            "client" => Ok(Mode::Client),
            "server" => Ok(Mode::Server),
            "pipe" => Ok(Mode::Pipe),
            s => Err(::capnp::Error::failed(format!("unrecognized mode: {}", s)))
        }
    }
}

fn do_testcase<C, S, T>(testcase: T, mode: Mode, reuse: S, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>, T: TestCase,
{
    match mode {
        Mode::Object => pass_by_object(testcase, reuse, iters),
        Mode::Bytes => pass_by_bytes(testcase, reuse, compression, iters),
        Mode::Client => sync_client(testcase, reuse, compression, iters),
        Mode::Server => {
            let input: ::std::fs::File = unsafe { ::std::os::unix::io::FromRawFd::from_raw_fd(1) };
            let output: ::std::fs::File = unsafe { ::std::os::unix::io::FromRawFd::from_raw_fd(0) };
            server(testcase, reuse, compression, iters, input, output)
        }
        Mode::Pipe => pass_by_pipe(testcase, reuse, compression, iters),
    }
}

fn do_testcase1<C, S>(case: &str, mode: Mode, scratch: S, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize, S: for<'a> Scratch<'a>,
{
    match case {
        "carsales" => do_testcase(carsales::CarSales, mode, scratch, compression, iters),
        "catrank" => do_testcase(catrank::CatRank, mode, scratch, compression, iters),
        "eval" => do_testcase(eval::Eval, mode, scratch, compression, iters),
        s => panic!("unrecognized test case: {}", s)
    }
}

fn do_testcase2<C>(case: &str, mode: Mode, scratch: &str, compression: C, iters: u64) -> ::capnp::Result<()>
    where C: Serialize,
{
    match scratch {
        "no-reuse" => do_testcase1(case, mode, NoScratch, compression, iters),
        "reuse" => do_testcase1(case, mode, UseScratch::new(), compression, iters),
        s => panic!("unrecognized reuse option: {}", s),
    }
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();

    assert!(args.len() == 6,
            "USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT",
            args[0]);

    let iters = match args[5].parse::<u64>() {
        Ok(n) => n,
        Err(_) => {
            panic!("Could not parse a u64 from: {}", args[5]);
        }
    };

    let mode = Mode::parse(&*args[2]).unwrap();

    let result = match &*args[4] {
        "none" => do_testcase2(&*args[1], mode, &*args[3], NoCompression, iters),
        "packed" => do_testcase2(&*args[1], mode, &*args[3], Packed, iters),
        s => panic!("unrecognized compression: {}", s)
    };

    match result {
        Ok(()) => (),
        Err(e) => {
            panic!("error: {:?}", e);
        }
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate httpbis;
extern crate httpbis_h2spec_test;

use std::process;
use std::sync::Arc;

fn main() {
    env_logger::init();

    let mut server = httpbis::ServerBuilder::new_plain();
    server
        .service
        .set_service("/", Arc::new(httpbis_h2spec_test::Ok200));
    server.set_port(8888);
    let _server = server.build().expect("server.build()");

    let mut h2spec = process::Command::new("h2spec")
        .args(&["-p", "8888", "-v"])
        .stdin(process::Stdio::null())
        .stdout(process::Stdio::inherit())
        .stderr(process::Stdio::inherit())
        .spawn()
        .expect("spawn h2spec");

    let exit_status = h2spec.wait().expect("h2spec wait");
    assert!(exit_status.success(), "{}", exit_status);
}
<commit_msg>Pass parameters to h2spec in the test<commit_after>extern crate env_logger;
extern crate httpbis;
extern crate httpbis_h2spec_test;

use std::env;
use std::process;
use std::sync::Arc;

fn main() {
    env_logger::init();

    let mut server = httpbis::ServerBuilder::new_plain();
    server
        .service
        .set_service("/", Arc::new(httpbis_h2spec_test::Ok200));
    server.set_port(8888);
    let _server = server.build().expect("server.build()");

    let mut h2spec = process::Command::new("h2spec")
        .args(&["-p", "8888", "-v"])
        .args(env::args().skip(1))
        .stdin(process::Stdio::null())
        .stdout(process::Stdio::inherit())
        .stderr(process::Stdio::inherit())
        .spawn()
        .expect("spawn h2spec");

    let exit_status = h2spec.wait().expect("h2spec wait");
    assert!(exit_status.success(), "{}", exit_status);
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Equilibrium_index
use std::iter::AdditiveIterator;
use std::num::Zero;
use std::ops::Add;

fn equilibrium_indices<T: Add<T, T> + Sub<T, T> + Eq + Zero + Copy>(v: &[T]) -> Vec<uint> {
    let mut right = v.iter().map(|&x| x).sum();
    let mut left: T = Zero::zero();
    let mut ret = vec![];

    for (i, &el) in v.iter().enumerate() {
        // NOTE: -= and += doesn't work on left/right and el for some reason.
        right = right - el;
        if left == right {
            ret.push(i);
        }
        left = left + el;
    }
    ret
}

#[test]
fn test_equilibrium_indices() {
    let v = [-7i, 1, 5, 2, -4, 3, 0];
    assert_eq!(equilibrium_indices(v), vec![3u, 6]);
}

#[cfg(not(test))]
fn main() {
    let v = [-7i, 1, 5, 2, -4, 3, 0];
    let indices = equilibrium_indices(v);
    println!("Equilibrium indices for {} are: {}", v.as_slice(), indices);
}
<commit_msg>equilibrium index: Simplify + style<commit_after>// http://rosettacode.org/wiki/Equilibrium_index
use std::iter::AdditiveIterator;
use std::num::Zero;
use std::ops::Add;

fn equilibrium_indices<T: Add<T, T> + Sub<T, T> + Eq + Zero + Copy>(v: &[T]) -> Vec<uint> {
    let mut right = v.iter().map(|&x| x).sum();
    let mut left: T = Zero::zero();

    v.iter().enumerate().fold(vec![], |mut out, (i, &el)| {
        // NOTE: -= and += doesn't work on left/right and el for some reason.
        right = right - el;
        if left == right {
            out.push(i);
        }
        left = left + el;

        out
    })
}

#[cfg(not(test))]
fn main() {
    let v = &[-7i, 1, 5, 2, -4, 3, 0];
    let indices = equilibrium_indices(v);
    println!("Equilibrium indices for {} are: {}", v, indices);
}

#[test]
fn test_equilibrium_indices() {
    let v = [-7i, 1, 5, 2, -4, 3, 0];
    assert_eq!(equilibrium_indices(v), vec![3, 6]);
}
<|endoftext|>


<commit_before>use index::boolean_index::{QueryAtom, BooleanOperator, PositionalOperator, FilterOperator,
                           BooleanQuery};

pub struct QueryBuilder<TTerm> {
    query: BooleanQuery<TTerm>,
}

impl<TTerm> QueryBuilder<TTerm> {
    pub fn and(operands: Vec<QueryBuilder<TTerm>>) -> Self {
        QueryBuilder {
            query: BooleanQuery::NAry(BooleanOperator::And,
                                      operands.into_iter().map(|o| o.build()).collect::<Vec<_>>()),
        }
    }

    pub fn or(operands: Vec<QueryBuilder<TTerm>>) -> Self {
        QueryBuilder {
            query: BooleanQuery::NAry(BooleanOperator::Or,
                                      operands.into_iter().map(|o| o.build()).collect::<Vec<_>>()),
        }
    }

    pub fn atoms(terms: Vec<TTerm>) -> Vec<Self> {
        terms.into_iter().map(|t| QueryBuilder::atom(t)).collect::<Vec<_>>()
    }

    pub fn atom(term: TTerm) -> Self {
        QueryBuilder { query: BooleanQuery::Atom(QueryAtom::new(0, term)) }
    }

    pub fn in_order(operands: Vec<Option<TTerm>>) -> Self {
        QueryBuilder {
            query: BooleanQuery::Positional(PositionalOperator::InOrder,
                                            operands.into_iter()
                                                .enumerate()
                                                .filter(|&(_, ref t)| t.is_some())
                                                .map(|(i, t)| QueryAtom::new(i, t.unwrap()))
                                                .collect::<Vec<_>>()),
        }
    }

    pub fn not(self, filter: Self) -> Self {
        QueryBuilder {
            query: BooleanQuery::Filter(FilterOperator::Not,
                                        Box::new(self.build()),
                                        Box::new(filter.build())),
        }

    }

    pub fn build(self) -> BooleanQuery<TTerm> {
        self.query
    }
}

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

    use index::Index;
    use index::boolean_index::tests::prepare_index;

    #[test]
    fn and_query() {
        let index = prepare_index();
        let query = QueryBuilder::and(QueryBuilder::atoms(vec![0, 5])).build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![0, 2]);
    }

    #[test]
    fn nested_and() {
        let index = prepare_index();
        let query = QueryBuilder::and(vec![QueryBuilder::or(QueryBuilder::atoms(vec![12, 7])),
                                           QueryBuilder::atom(9)])
            .build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![0]);
    }

    #[test]
    fn not() {
        let index = prepare_index();
        let query = QueryBuilder::and(QueryBuilder::atoms(vec![0, 5])).not(QueryBuilder::atom(9)).build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![2]);
    }

    #[test]
    fn in_order() {
        let index = prepare_index();
        let query = QueryBuilder::in_order(vec![Some(0), None, Some(2)]).build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![0]);
        let query = QueryBuilder::in_order(vec![Some(0), Some(2)]).build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![1]);
    }
}
<commit_msg>clippy + fmt<commit_after>use index::boolean_index::{QueryAtom, BooleanOperator, PositionalOperator, FilterOperator,
                           BooleanQuery};

pub struct QueryBuilder<TTerm> {
    query: BooleanQuery<TTerm>,
}

impl<TTerm> QueryBuilder<TTerm> {
    pub fn and(operands: Vec<QueryBuilder<TTerm>>) -> Self {
        QueryBuilder {
            query: BooleanQuery::NAry(BooleanOperator::And,
                                      operands.into_iter().map(|o| o.build()).collect::<Vec<_>>()),
        }
    }

    pub fn or(operands: Vec<QueryBuilder<TTerm>>) -> Self {
        QueryBuilder {
            query: BooleanQuery::NAry(BooleanOperator::Or,
                                      operands.into_iter().map(|o| o.build()).collect::<Vec<_>>()),
        }
    }

    pub fn atoms(terms: Vec<TTerm>) -> Vec<Self> {
        terms.into_iter().map(QueryBuilder::atom).collect::<Vec<_>>()
    }

    pub fn atom(term: TTerm) -> Self {
        QueryBuilder { query: BooleanQuery::Atom(QueryAtom::new(0, term)) }
    }

    pub fn in_order(operands: Vec<Option<TTerm>>) -> Self {
        QueryBuilder {
            query: BooleanQuery::Positional(PositionalOperator::InOrder,
                                            operands.into_iter()
                                                .enumerate()
                                                .filter(|&(_, ref t)| t.is_some())
                                                .map(|(i, t)| QueryAtom::new(i, t.unwrap()))
                                                .collect::<Vec<_>>()),
        }
    }

    pub fn not(self, filter: Self) -> Self {
        QueryBuilder {
            query: BooleanQuery::Filter(FilterOperator::Not,
                                        Box::new(self.build()),
                                        Box::new(filter.build())),
        }

    }

    pub fn build(self) -> BooleanQuery<TTerm> {
        self.query
    }
}

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

    use index::Index;
    use index::boolean_index::tests::prepare_index;

    #[test]
    fn and_query() {
        let index = prepare_index();
        let query = QueryBuilder::and(QueryBuilder::atoms(vec![0, 5])).build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![0, 2]);
    }

    #[test]
    fn nested_and() {
        let index = prepare_index();
        let query = QueryBuilder::and(vec![QueryBuilder::or(QueryBuilder::atoms(vec![12, 7])),
                                           QueryBuilder::atom(9)])
            .build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![0]);
    }

    #[test]
    fn not() {
        let index = prepare_index();
        let query =
            QueryBuilder::and(QueryBuilder::atoms(vec![0, 5])).not(QueryBuilder::atom(9)).build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![2]);
    }

    #[test]
    fn in_order() {
        let index = prepare_index();
        let query = QueryBuilder::in_order(vec![Some(0), None, Some(2)]).build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![0]);
        let query = QueryBuilder::in_order(vec![Some(0), Some(2)]).build();
        assert_eq!(index.execute_query(&query).collect::<Vec<_>>(), vec![1]);
    }
}
<|endoftext|>


<commit_before>//! Defines an instance of some piece of geometry in the scene, instances
//! can re-use loaded geometry but apply different transformations and materials
//! to them

use geometry::{Geometry, DifferentialGeometry};
use linalg;

/// Defines an instance of some geometry with its own transform and material
pub struct Instance<'a> {
    /// The geometry that's being instanced
    geom: &'a (Geometry + 'a),
    /// The transform to world space
    transform: linalg::Transform,
    /// The inverse transform, to object space
    inv_transform: linalg::Transform,
}

impl<'a> Geometry for Instance<'a> {
    fn intersect(&self, ray: &mut linalg::Ray, dg: &mut DifferentialGeometry) -> bool {
        let mut local = self.inv_transform * *ray;
        if self.geom.intersect(&mut local, dg) {
            ray.max_t = local.max_t;
            dg.p = self.transform * dg.p;
            dg.n = self.transform * dg.n;
            dg.ng = self.transform * dg.ng;
            true
        } else {
            false
        }
    }
}

<commit_msg>Add instance ctor<commit_after>//! Defines an instance of some piece of geometry in the scene, instances
//! can re-use loaded geometry but apply different transformations and materials
//! to them

use geometry::{Geometry, DifferentialGeometry};
use linalg;

/// Defines an instance of some geometry with its own transform and material
pub struct Instance<'a> {
    /// The geometry that's being instanced
    geom: &'a (Geometry + 'a),
    /// The transform to world space
    transform: linalg::Transform,
    /// The inverse transform, to object space
    inv_transform: linalg::Transform,
}

impl<'a> Instance<'a> {
    /// Create a new instance of some geometry in the scene
    pub fn new(geom: &'a (Geometry + 'a), transform: linalg::Transform) -> Instance<'a> {
        Instance { geom: geom, transform: transform, inv_transform: transform.inverse() }
    }
}

impl<'a> Geometry for Instance<'a> {
    fn intersect(&self, ray: &mut linalg::Ray, dg: &mut DifferentialGeometry) -> bool {
        let mut local = self.inv_transform * *ray;
        if self.geom.intersect(&mut local, dg) {
            ray.max_t = local.max_t;
            dg.p = self.transform * dg.p;
            dg.n = self.transform * dg.n;
            dg.ng = self.transform * dg.ng;
            true
        } else {
            false
        }
    }
}

<|endoftext|>


<commit_before>//!

use super::{
    context::GraphicsContext,
    draw::{DrawParam, DrawUniforms, Std140DrawUniforms},
    gpu::arc::ArcBuffer,
    Canvas, Draw, Drawable, Image, Rect, WgpuContext,
};
use crevice::std140::AsStd140;
use std::collections::BTreeMap;

/// Array of instances for fast rendering of many meshes.
///
/// Traditionally known as a "batch".
#[derive(Debug)]
pub struct InstanceArray {
    pub(crate) buffer: ArcBuffer,
    pub(crate) indices: ArcBuffer,
    pub(crate) image: Image,
    pub(crate) ordered: bool,
    dirty: bool,
    capacity: u32,
    uniforms: Vec<Std140DrawUniforms>,
    params: Vec<DrawParam>,
}

impl InstanceArray {
    /// Creates a new [InstanceArray] capable of storing up to n-`capacity` instances (this can be changed and is resized automatically when needed).
    ///
    /// If `image` is `None`, a 1x1 white image will be used which can be used to draw solid rectangles.
    pub fn new(
        gfx: &GraphicsContext,
        image: impl Into<Option<Image>>,
        capacity: u32,
        ordered: bool,
    ) -> Self {
        InstanceArray::new_wgpu(
            &gfx.wgpu,
            image.into().unwrap_or_else(|| gfx.white_image.clone()),
            capacity,
            ordered,
        )
    }

    fn new_wgpu(wgpu: &WgpuContext, image: Image, capacity: u32, ordered: bool) -> Self {
        assert!(capacity > 0);

        let buffer = ArcBuffer::new(wgpu.device.create_buffer(&wgpu::BufferDescriptor {
            label: None,
            size: DrawUniforms::std140_size_static() as u64 * capacity as u64,
            usage: wgpu::BufferUsages::STORAGE
                | wgpu::BufferUsages::COPY_DST
                | wgpu::BufferUsages::COPY_SRC,
            mapped_at_creation: false,
        }));

        let indices = ArcBuffer::new(wgpu.device.create_buffer(&wgpu::BufferDescriptor {
            label: None,
            size: if ordered {
                std::mem::size_of::<u32>() as u64 * capacity as u64
            } else {
                4 // min for layout
            },
            usage: wgpu::BufferUsages::STORAGE
                | wgpu::BufferUsages::COPY_SRC
                | wgpu::BufferUsages::COPY_DST,
            mapped_at_creation: false,
        }));

        let uniforms = Vec::with_capacity(capacity as usize);
        let params = Vec::with_capacity(capacity as usize);

        InstanceArray {
            buffer,
            indices,
            image,
            ordered,
            dirty: false,
            capacity,
            uniforms,
            params,
        }
    }

    /// Resets all the instance data to a set of `DrawParam`.
    pub fn set(&mut self, instances: impl IntoIterator<Item = DrawParam>) {
        self.dirty = true;
        self.params.clear();
        self.params.extend(instances);
        self.uniforms.clear();
        self.uniforms.extend(self.params.iter().map(|x| {
            DrawUniforms::from_param(
                x,
                [self.image.width() as f32, self.image.height() as f32].into(),
            )
            .as_std140()
        }));
    }

    /// Pushes a new instance onto the end.
    pub fn push(&mut self, instance: DrawParam) {
        self.dirty = true;
        self.uniforms.push(
            DrawUniforms::from_param(
                &instance,
                [self.image.width() as f32, self.image.height() as f32].into(),
            )
            .as_std140(),
        );
        self.params.push(instance);
    }

    /// Updates an existing instance at a given index, if it is valid.
    pub fn update(&mut self, index: u32, instance: DrawParam) {
        if let Some((uniform, param)) = self
            .uniforms
            .get_mut(index as usize)
            .and_then(|x| Some((x, self.params.get_mut(index as usize)?)))
        {
            self.dirty = true;
            *uniform = DrawUniforms::from_param(
                &instance,
                [self.image.width() as f32, self.image.height() as f32].into(),
            )
            .as_std140();
            *param = instance;
        }
    }

    /// Clears all instance data.
    pub fn clear(&mut self) {
        // don't need to set dirty here
        self.uniforms.clear();
        self.params.clear();
    }

    /// Returns whether the instance data has been changed without [`InstanceArray::flush()`] being called.
    #[inline]
    pub fn is_dirty(&self) -> bool {
        self.dirty
    }

    /// Returns an immutable slice of all the instance data in this [`InstanceArray`].
    #[inline]
    pub fn instances(&self) -> &[DrawParam] {
        &self.params
    }

    /// Uploads the instance data to the GPU.
    ///
    /// You do not usually need to call this yourself as it is done automatically during drawing.
    pub fn flush(&mut self, gfx: &GraphicsContext) {
        self.flush_wgpu(&gfx.wgpu)
    }

    #[allow(unsafe_code)]
    pub(crate) fn flush_wgpu(&mut self, wgpu: &WgpuContext) {
        if !self.dirty {
            return;
        } else {
            self.dirty = false;
        }

        let len = self.uniforms.len() as u32;
        if len > self.capacity {
            let resized = InstanceArray::new_wgpu(wgpu, self.image.clone(), len, self.ordered);
            self.buffer = resized.buffer;
            self.indices = resized.indices;
            self.capacity = len;
        }

        wgpu.queue.write_buffer(&self.buffer, 0, unsafe {
            std::slice::from_raw_parts(
                self.uniforms.as_ptr() as *const u8,
                self.uniforms.len() * DrawUniforms::std140_size_static(),
            )
        });

        if self.ordered {
            let mut layers = BTreeMap::<_, Vec<_>>::new();
            for (i, param) in self.params.iter().enumerate() {
                layers.entry(param.z).or_default().push(i);
            }
            let indices = layers.into_values().flatten().collect::<Vec<_>>();
            wgpu.queue.write_buffer(&self.indices, 0, unsafe {
                std::slice::from_raw_parts(
                    indices.as_ptr() as *const u8,
                    indices.len() * std::mem::size_of::<u32>(),
                )
            });
        }
    }

    /// Changes the capacity of this `InstanceArray` while preserving instances.
    ///
    /// If `new_capacity` is less than the `len`, the instances will be truncated.
    pub fn resize(&mut self, gfx: &GraphicsContext, new_capacity: u32) {
        let resized = InstanceArray::new(gfx, self.image.clone(), new_capacity, self.ordered);
        self.buffer = resized.buffer;
        self.indices = resized.indices;
        self.capacity = new_capacity;
        self.dirty = true;
        self.uniforms.truncate(new_capacity as usize);
        self.params.truncate(new_capacity as usize);
        self.uniforms
            .reserve((new_capacity as usize).min(self.uniforms.len()) - self.uniforms.len());
        self.params
            .reserve((new_capacity as usize).min(self.params.len()) - self.params.len());
    }

    /// Returns this `InstanceArray`'s associated `image`.
    #[inline]
    pub fn image(&self) -> Image {
        self.image.clone()
    }

    /// Returns the number of instances this [InstanceArray] is capable of holding.
    /// This number was specified when creating the [InstanceArray], or if the [InstanceArray]
    /// was automatically resized, the greatest length of instances.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.capacity as usize
    }
}

impl<'a> Drawable for &'a mut InstanceArray {
    fn draw(self, canvas: &mut Canvas, param: DrawParam) {
        self.flush_wgpu(&canvas.wgpu);
        canvas.push_draw(
            Draw::MeshInstances {
                mesh: canvas.default_resources().mesh.clone(),
                instances: (&*self).into(),
            },
            param,
        );
    }

    fn dimensions(self, _gfx: &mut GraphicsContext) -> Option<Rect> {
        None
    }
}
<commit_msg>remove public InstanceArray::flush<commit_after>//!

use super::{
    context::GraphicsContext,
    draw::{DrawParam, DrawUniforms, Std140DrawUniforms},
    gpu::arc::ArcBuffer,
    Canvas, Draw, Drawable, Image, Rect, WgpuContext,
};
use crevice::std140::AsStd140;
use std::collections::BTreeMap;

/// Array of instances for fast rendering of many meshes.
///
/// Traditionally known as a "batch".
#[derive(Debug)]
pub struct InstanceArray {
    pub(crate) buffer: ArcBuffer,
    pub(crate) indices: ArcBuffer,
    pub(crate) image: Image,
    pub(crate) ordered: bool,
    dirty: bool,
    capacity: u32,
    uniforms: Vec<Std140DrawUniforms>,
    params: Vec<DrawParam>,
}

impl InstanceArray {
    /// Creates a new [InstanceArray] capable of storing up to n-`capacity` instances (this can be changed and is resized automatically when needed).
    ///
    /// If `image` is `None`, a 1x1 white image will be used which can be used to draw solid rectangles.
    pub fn new(
        gfx: &GraphicsContext,
        image: impl Into<Option<Image>>,
        capacity: u32,
        ordered: bool,
    ) -> Self {
        InstanceArray::new_wgpu(
            &gfx.wgpu,
            image.into().unwrap_or_else(|| gfx.white_image.clone()),
            capacity,
            ordered,
        )
    }

    fn new_wgpu(wgpu: &WgpuContext, image: Image, capacity: u32, ordered: bool) -> Self {
        assert!(capacity > 0);

        let buffer = ArcBuffer::new(wgpu.device.create_buffer(&wgpu::BufferDescriptor {
            label: None,
            size: DrawUniforms::std140_size_static() as u64 * capacity as u64,
            usage: wgpu::BufferUsages::STORAGE
                | wgpu::BufferUsages::COPY_DST
                | wgpu::BufferUsages::COPY_SRC,
            mapped_at_creation: false,
        }));

        let indices = ArcBuffer::new(wgpu.device.create_buffer(&wgpu::BufferDescriptor {
            label: None,
            size: if ordered {
                std::mem::size_of::<u32>() as u64 * capacity as u64
            } else {
                4 // min for layout
            },
            usage: wgpu::BufferUsages::STORAGE
                | wgpu::BufferUsages::COPY_SRC
                | wgpu::BufferUsages::COPY_DST,
            mapped_at_creation: false,
        }));

        let uniforms = Vec::with_capacity(capacity as usize);
        let params = Vec::with_capacity(capacity as usize);

        InstanceArray {
            buffer,
            indices,
            image,
            ordered,
            dirty: false,
            capacity,
            uniforms,
            params,
        }
    }

    /// Resets all the instance data to a set of `DrawParam`.
    pub fn set(&mut self, instances: impl IntoIterator<Item = DrawParam>) {
        self.dirty = true;
        self.params.clear();
        self.params.extend(instances);
        self.uniforms.clear();
        self.uniforms.extend(self.params.iter().map(|x| {
            DrawUniforms::from_param(
                x,
                [self.image.width() as f32, self.image.height() as f32].into(),
            )
            .as_std140()
        }));
    }

    /// Pushes a new instance onto the end.
    pub fn push(&mut self, instance: DrawParam) {
        self.dirty = true;
        self.uniforms.push(
            DrawUniforms::from_param(
                &instance,
                [self.image.width() as f32, self.image.height() as f32].into(),
            )
            .as_std140(),
        );
        self.params.push(instance);
    }

    /// Updates an existing instance at a given index, if it is valid.
    pub fn update(&mut self, index: u32, instance: DrawParam) {
        if let Some((uniform, param)) = self
            .uniforms
            .get_mut(index as usize)
            .and_then(|x| Some((x, self.params.get_mut(index as usize)?)))
        {
            self.dirty = true;
            *uniform = DrawUniforms::from_param(
                &instance,
                [self.image.width() as f32, self.image.height() as f32].into(),
            )
            .as_std140();
            *param = instance;
        }
    }

    /// Clears all instance data.
    pub fn clear(&mut self) {
        // don't need to set dirty here
        self.uniforms.clear();
        self.params.clear();
    }

    /// Returns whether the instance data has been changed without [`InstanceArray::flush()`] being called.
    #[inline]
    pub fn is_dirty(&self) -> bool {
        self.dirty
    }

    /// Returns an immutable slice of all the instance data in this [`InstanceArray`].
    #[inline]
    pub fn instances(&self) -> &[DrawParam] {
        &self.params
    }

    #[allow(unsafe_code)]
    pub(crate) fn flush_wgpu(&mut self, wgpu: &WgpuContext) {
        if !self.dirty {
            return;
        } else {
            self.dirty = false;
        }

        let len = self.uniforms.len() as u32;
        if len > self.capacity {
            let resized = InstanceArray::new_wgpu(wgpu, self.image.clone(), len, self.ordered);
            self.buffer = resized.buffer;
            self.indices = resized.indices;
            self.capacity = len;
        }

        wgpu.queue.write_buffer(&self.buffer, 0, unsafe {
            std::slice::from_raw_parts(
                self.uniforms.as_ptr() as *const u8,
                self.uniforms.len() * DrawUniforms::std140_size_static(),
            )
        });

        if self.ordered {
            let mut layers = BTreeMap::<_, Vec<_>>::new();
            for (i, param) in self.params.iter().enumerate() {
                layers.entry(param.z).or_default().push(i);
            }
            let indices = layers.into_values().flatten().collect::<Vec<_>>();
            wgpu.queue.write_buffer(&self.indices, 0, unsafe {
                std::slice::from_raw_parts(
                    indices.as_ptr() as *const u8,
                    indices.len() * std::mem::size_of::<u32>(),
                )
            });
        }
    }

    /// Changes the capacity of this `InstanceArray` while preserving instances.
    ///
    /// If `new_capacity` is less than the `len`, the instances will be truncated.
    pub fn resize(&mut self, gfx: &GraphicsContext, new_capacity: u32) {
        let resized = InstanceArray::new(gfx, self.image.clone(), new_capacity, self.ordered);
        self.buffer = resized.buffer;
        self.indices = resized.indices;
        self.capacity = new_capacity;
        self.dirty = true;
        self.uniforms.truncate(new_capacity as usize);
        self.params.truncate(new_capacity as usize);
        self.uniforms
            .reserve((new_capacity as usize).min(self.uniforms.len()) - self.uniforms.len());
        self.params
            .reserve((new_capacity as usize).min(self.params.len()) - self.params.len());
    }

    /// Returns this `InstanceArray`'s associated `image`.
    #[inline]
    pub fn image(&self) -> Image {
        self.image.clone()
    }

    /// Returns the number of instances this [InstanceArray] is capable of holding.
    /// This number was specified when creating the [InstanceArray], or if the [InstanceArray]
    /// was automatically resized, the greatest length of instances.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.capacity as usize
    }
}

impl<'a> Drawable for &'a mut InstanceArray {
    fn draw(self, canvas: &mut Canvas, param: DrawParam) {
        self.flush_wgpu(&canvas.wgpu);
        canvas.push_draw(
            Draw::MeshInstances {
                mesh: canvas.default_resources().mesh.clone(),
                instances: (&*self).into(),
            },
            param,
        );
    }

    fn dimensions(self, _gfx: &mut GraphicsContext) -> Option<Rect> {
        None
    }
}
<|endoftext|>